diff --git a/fern/apis/fdr/definition/api/latest/type.yml b/fern/apis/fdr/definition/api/latest/type.yml index e36ddc8ef5..f6d36eefd7 100644 --- a/fern/apis/fdr/definition/api/latest/type.yml +++ b/fern/apis/fdr/definition/api/latest/type.yml @@ -25,6 +25,7 @@ types: id: TypeReferenceId primitive: PrimitiveType optional: OptionalType + nullable: NullableType list: ListType set: SetType map: MapType @@ -136,6 +137,10 @@ types: isOptional: boolean contentType: optional<ContentType> + NullableType: + properties: + shape: TypeShape + OptionalType: properties: shape: TypeShape diff --git a/fern/apis/fdr/definition/api/v1/read/type.yml b/fern/apis/fdr/definition/api/v1/read/type.yml index 1876c3f680..d72b0c543d 100644 --- a/fern/apis/fdr/definition/api/v1/read/type.yml +++ b/fern/apis/fdr/definition/api/v1/read/type.yml @@ -84,6 +84,7 @@ types: StringType: properties: + format: optional<string> regex: optional<string> minLength: optional<integer> maxLength: optional<integer> diff --git a/fern/apis/fdr/definition/api/v1/register/type.yml b/fern/apis/fdr/definition/api/v1/register/type.yml index d4894fceaf..f228c49f2b 100644 --- a/fern/apis/fdr/definition/api/v1/register/type.yml +++ b/fern/apis/fdr/definition/api/v1/register/type.yml @@ -84,6 +84,7 @@ types: StringType: properties: + format: optional<string> regex: optional<string> minLength: optional<integer> maxLength: optional<integer> diff --git a/packages/fdr-sdk/src/api-definition/__test__/join.test.ts b/packages/fdr-sdk/src/api-definition/__test__/join.test.ts index ee73b78ddb..9926a75ae0 100644 --- a/packages/fdr-sdk/src/api-definition/__test__/join.test.ts +++ b/packages/fdr-sdk/src/api-definition/__test__/join.test.ts @@ -6,6 +6,7 @@ const PRIMITIVE_SHAPE: Latest.TypeReference.Primitive = { type: "primitive" as const, value: { type: "string", + format: undefined, regex: undefined, minLength: undefined, maxLength: undefined, diff --git a/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts b/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts index 0f8de2e6f1..2e9ce75c70 100644 --- a/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts +++ b/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts @@ -6,6 +6,7 @@ const PRIMITIVE_SHAPE: Latest.TypeReference.Primitive = { type: "primitive" as const, value: { type: "string", + format: undefined, regex: undefined, minLength: undefined, maxLength: undefined, diff --git a/packages/fdr-sdk/src/api-definition/__test__/unwrap.test.ts b/packages/fdr-sdk/src/api-definition/__test__/unwrap.test.ts index 69cc22819f..8cd542536e 100644 --- a/packages/fdr-sdk/src/api-definition/__test__/unwrap.test.ts +++ b/packages/fdr-sdk/src/api-definition/__test__/unwrap.test.ts @@ -14,6 +14,7 @@ const PRIMITIVE_SHAPE: TypeShape = { type: "primitive" as const, value: { type: "string", + format: undefined, regex: undefined, minLength: undefined, maxLength: undefined, @@ -24,26 +25,28 @@ const PRIMITIVE_SHAPE: TypeShape = { describe("unwrapReference", () => { it("should noop for a non-reference", () => { - expect(unwrapReference(PRIMITIVE_SHAPE["value"], {})).toMatchInlineSnapshot( + expect(unwrapReference(PRIMITIVE_SHAPE.value, {})).toMatchInlineSnapshot( ` - { - "availability": undefined, + { + "availability": undefined, + "default": undefined, + "descriptions": [], + "isNullable": false, + "isOptional": false, + "shape": { + "type": "primitive", + "value": { "default": undefined, - "descriptions": [], - "isOptional": false, - "shape": { - "type": "primitive", - "value": { - "default": undefined, - "maxLength": undefined, - "minLength": undefined, - "regex": undefined, - "type": "string", - }, - }, - "visitedTypeIds": Set {}, - } - ` + "format": undefined, + "maxLength": undefined, + "minLength": undefined, + "regex": undefined, + "type": "string", + }, + }, + "visitedTypeIds": Set {}, + } + ` ); }); @@ -63,26 +66,28 @@ describe("unwrapReference", () => { }; expect(unwrapReference(shape, types)).toMatchInlineSnapshot( ` - { - "availability": undefined, + { + "availability": undefined, + "default": undefined, + "descriptions": [], + "isNullable": false, + "isOptional": false, + "shape": { + "type": "primitive", + "value": { "default": undefined, - "descriptions": [], - "isOptional": false, - "shape": { - "type": "primitive", - "value": { - "default": undefined, - "maxLength": undefined, - "minLength": undefined, - "regex": undefined, - "type": "string", - }, - }, - "visitedTypeIds": Set { - "foo", - }, - } - ` + "format": undefined, + "maxLength": undefined, + "minLength": undefined, + "regex": undefined, + "type": "string", + }, + }, + "visitedTypeIds": Set { + "foo", + }, + } + ` ); }); @@ -93,20 +98,21 @@ describe("unwrapReference", () => { default: undefined, }; expect(unwrapReference(shape, {})).toMatchInlineSnapshot(` - { - "availability": undefined, - "default": undefined, - "descriptions": [], - "isOptional": false, - "shape": { - "displayName": undefined, - "type": "unknown", - }, - "visitedTypeIds": Set { - "foo", - }, - } - `); + { + "availability": undefined, + "default": undefined, + "descriptions": [], + "isNullable": false, + "isOptional": false, + "shape": { + "displayName": undefined, + "type": "unknown", + }, + "visitedTypeIds": Set { + "foo", + }, + } + `); }); it("should unwrap optionals", () => { @@ -132,26 +138,28 @@ describe("unwrapReference", () => { }; expect(unwrapReference(shape, types)).toMatchInlineSnapshot( ` - { - "availability": undefined, + { + "availability": undefined, + "default": undefined, + "descriptions": [], + "isNullable": false, + "isOptional": true, + "shape": { + "type": "primitive", + "value": { "default": undefined, - "descriptions": [], - "isOptional": true, - "shape": { - "type": "primitive", - "value": { - "default": undefined, - "maxLength": undefined, - "minLength": undefined, - "regex": undefined, - "type": "string", - }, - }, - "visitedTypeIds": Set { - "foo", - }, - } - ` + "format": undefined, + "maxLength": undefined, + "minLength": undefined, + "regex": undefined, + "type": "string", + }, + }, + "visitedTypeIds": Set { + "foo", + }, + } + ` ); }); @@ -271,7 +279,7 @@ describe("unwrapReference", () => { }, }; const unwrapped = unwrapReference(shape, types); - expect(unwrapped.shape).toStrictEqual(PRIMITIVE_SHAPE["value"]); + expect(unwrapped.shape).toStrictEqual(PRIMITIVE_SHAPE.value); expect(unwrapped.availability).toBe("Deprecated"); expect(unwrapped.descriptions).toStrictEqual(["a", "b", "c"]); expect(unwrapped.isOptional).toBe(true); diff --git a/packages/fdr-sdk/src/api-definition/sort-keys.ts b/packages/fdr-sdk/src/api-definition/sort-keys.ts index 7729febe04..d1af386785 100644 --- a/packages/fdr-sdk/src/api-definition/sort-keys.ts +++ b/packages/fdr-sdk/src/api-definition/sort-keys.ts @@ -35,6 +35,7 @@ export function sortKeysByShape( primitive: () => obj, literal: () => obj, optional: ({ shape }) => sortKeysByShape(obj, shape, types), + nullable: ({ shape }) => sortKeysByShape(obj, shape, types), list: ({ itemShape }) => Array.isArray(obj) ? obj.map((o) => sortKeysByShape(o, itemShape, types)) diff --git a/packages/fdr-sdk/src/api-definition/typeid-visitor.ts b/packages/fdr-sdk/src/api-definition/typeid-visitor.ts index 431629350b..aff7378655 100644 --- a/packages/fdr-sdk/src/api-definition/typeid-visitor.ts +++ b/packages/fdr-sdk/src/api-definition/typeid-visitor.ts @@ -149,6 +149,7 @@ export class ApiTypeIdVisitor { id: (value) => visit(value.id), primitive: noop, optional: (value) => ApiTypeIdVisitor.visitTypeShape(value.shape, visit), + nullable: (value) => ApiTypeIdVisitor.visitTypeShape(value.shape, visit), list: (value) => ApiTypeIdVisitor.visitTypeShape(value.itemShape, visit), set: (value) => ApiTypeIdVisitor.visitTypeShape(value.itemShape, visit), map: (value) => { diff --git a/packages/fdr-sdk/src/api-definition/types.ts b/packages/fdr-sdk/src/api-definition/types.ts index 861aca9470..7e5cb28b1d 100644 --- a/packages/fdr-sdk/src/api-definition/types.ts +++ b/packages/fdr-sdk/src/api-definition/types.ts @@ -14,5 +14,5 @@ export type DereferencedTypeShapeOrReference = | DereferencedTypeReference; export type DereferencedNonOptionalTypeShapeOrReference = Exclude< DereferencedTypeShapeOrReference, - Latest.TypeReference.Optional + Latest.TypeReference.Optional | Latest.TypeReference.Nullable >; diff --git a/packages/fdr-sdk/src/api-definition/unwrap.ts b/packages/fdr-sdk/src/api-definition/unwrap.ts index cc8770f605..c8d55df0e8 100644 --- a/packages/fdr-sdk/src/api-definition/unwrap.ts +++ b/packages/fdr-sdk/src/api-definition/unwrap.ts @@ -16,6 +16,7 @@ export type UnwrappedReference = { descriptions: FernDocs.MarkdownText[]; visitedTypeIds: Set<Latest.TypeId>; isOptional: boolean; + isNullable: boolean; default?: unknown; }; @@ -74,6 +75,7 @@ export function unwrapReference( } let isOptional = false; + let isNullable = false; const defaults: InternalDefaultValue[] = []; const descriptions: FernDocs.MarkdownText[] = []; const availabilities: Latest.Availability[] = []; @@ -89,7 +91,10 @@ export function unwrapReference( break; } - if (internalTypeRef.type === "optional") { + if (internalTypeRef.type === "nullable") { + isNullable = true; + internalTypeRef = internalTypeRef.shape; + } else if (internalTypeRef.type === "optional") { isOptional = true; if (internalTypeRef.default != null) { defaults.push({ @@ -137,12 +142,10 @@ export function unwrapReference( if (internalTypeRef == null) { // Note: this should be a fatal error, but we're handling it gracefully for now if (circularReference) { - // eslint-disable-next-line no-console console.error( `Circular reference detected. Falling back to unknown type. types=[${[...visitedTypeIds].join(", ")}]` ); } else { - // eslint-disable-next-line no-console console.error( `Type reference is invalid. Falling back to unknown type. types=[${[...visitedTypeIds].join(", ")}]` ); @@ -154,6 +157,7 @@ export function unwrapReference( availability: coalesceAvailability(availabilities), visitedTypeIds, isOptional, + isNullable, default: selectDefaultValue(internalTypeRef, defaults), descriptions, }; @@ -235,7 +239,6 @@ export function unwrapObjectType( const extendedProperties = object.extends.flatMap( (typeId): Latest.ObjectProperty[] => { if (parentVisitedTypeIds?.has(typeId)) { - // eslint-disable-next-line no-console console.error( `Circular reference detected. Cannot extend type=${typeId}` ); @@ -256,7 +259,6 @@ export function unwrapObjectType( // TODO: should we be able to extend discriminated and undiscriminated unions? if (unwrapped?.shape.type !== "object") { - // eslint-disable-next-line no-console console.error("Object extends non-object", typeId); return []; } diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/NullableType.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/NullableType.ts new file mode 100644 index 0000000000..de3af143a4 --- /dev/null +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/NullableType.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernRegistry from "../../../../../../../index"; + +export interface NullableType { + shape: FernRegistry.api.latest.TypeShape; +} diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts index 5a0b72d115..75bb5909e2 100644 --- a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts @@ -8,6 +8,7 @@ export type TypeReference = | FernRegistry.api.latest.TypeReference.Id | FernRegistry.api.latest.TypeReference.Primitive | FernRegistry.api.latest.TypeReference.Optional + | FernRegistry.api.latest.TypeReference.Nullable | FernRegistry.api.latest.TypeReference.List | FernRegistry.api.latest.TypeReference.Set | FernRegistry.api.latest.TypeReference.Map @@ -28,6 +29,10 @@ export declare namespace TypeReference { type: "optional"; } + interface Nullable extends FernRegistry.api.latest.NullableType { + type: "nullable"; + } + interface List extends FernRegistry.api.latest.ListType { type: "list"; } diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts index 7c3d80e6b6..79cdba3349 100644 --- a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts @@ -21,6 +21,7 @@ export * from "./FormDataField"; export * from "./FormDataProperty"; export * from "./FormDataFile"; export * from "./FormDataFiles"; +export * from "./NullableType"; export * from "./OptionalType"; export * from "./ListType"; export * from "./SetType"; diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts index 8903b99b94..fbca354844 100644 --- a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts @@ -3,6 +3,7 @@ */ export interface StringType { + format: string | undefined; regex: string | undefined; minLength: number | undefined; maxLength: number | undefined; diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts index 8903b99b94..fbca354844 100644 --- a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts @@ -3,6 +3,7 @@ */ export interface StringType { + format: string | undefined; regex: string | undefined; minLength: number | undefined; maxLength: number | undefined; diff --git a/packages/fern-docs/search-server/src/algolia/records/archive/v1-record-converter/generateEndpointContent.ts b/packages/fern-docs/search-server/src/algolia/records/archive/v1-record-converter/generateEndpointContent.ts index cb81eea191..8ba2b27ddb 100644 --- a/packages/fern-docs/search-server/src/algolia/records/archive/v1-record-converter/generateEndpointContent.ts +++ b/packages/fern-docs/search-server/src/algolia/records/archive/v1-record-converter/generateEndpointContent.ts @@ -63,6 +63,8 @@ function stringifyTypeRef( primitive: (value) => value.value.type, optional: (value) => `${stringifyTypeShape(value.shape, types, depth + 1)}?`, + nullable: (value) => + `${stringifyTypeShape(value.shape, types, depth + 1)} | null`, list: (value) => `List<${stringifyTypeShape(value.itemShape, types, depth + 1)}>`, set: (value) => diff --git a/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx b/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx index da8706415b..1384262ff4 100644 --- a/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx +++ b/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx @@ -108,6 +108,7 @@ const UnmemoizedEndpointContentLeft: React.FC<EndpointContentLeft.Props> = ({ type: "primitive", value: { type: "string", + format: undefined, regex: undefined, minLength: undefined, maxLength: undefined, diff --git a/packages/fern-docs/ui/src/playground/code-snippets/__test__/code-snippets.test.ts b/packages/fern-docs/ui/src/playground/code-snippets/__test__/code-snippets.test.ts index b235fece2e..60124b63ce 100644 --- a/packages/fern-docs/ui/src/playground/code-snippets/__test__/code-snippets.test.ts +++ b/packages/fern-docs/ui/src/playground/code-snippets/__test__/code-snippets.test.ts @@ -63,6 +63,7 @@ describe("PlaygroundCodeSnippetBuilder", () => { type: "primitive", value: { type: "string", + format: undefined, regex: undefined, minLength: undefined, maxLength: undefined, diff --git a/packages/fern-docs/ui/src/playground/form/PlaygroundAdditionalProperties.tsx b/packages/fern-docs/ui/src/playground/form/PlaygroundAdditionalProperties.tsx index 0382ed89f6..e7e109fe04 100644 --- a/packages/fern-docs/ui/src/playground/form/PlaygroundAdditionalProperties.tsx +++ b/packages/fern-docs/ui/src/playground/form/PlaygroundAdditionalProperties.tsx @@ -11,6 +11,7 @@ const ADDITIONAL_PROPERTIES_KEY_SHAPE = { type: "primitive", value: { type: "string", + format: undefined, regex: undefined, minLength: undefined, maxLength: undefined, @@ -22,6 +23,7 @@ const ADDITIONAL_PROPERTIES_VALUE_SHAPE = { type: "primitive", value: { type: "string", + format: undefined, regex: undefined, minLength: undefined, maxLength: undefined, diff --git a/packages/fern-docs/ui/src/type-shorthand/index.tsx b/packages/fern-docs/ui/src/type-shorthand/index.tsx index 545d36ae22..e176379181 100644 --- a/packages/fern-docs/ui/src/type-shorthand/index.tsx +++ b/packages/fern-docs/ui/src/type-shorthand/index.tsx @@ -24,11 +24,7 @@ export function renderTypeShorthandRoot( hideOptional = false ): ReactNode { const unwrapped = unwrapReference(shape, types); - const typeShorthand = renderTypeShorthand( - unwrapped.shape, - { nullable: isResponse }, - types - ); + const typeShorthand = renderTypeShorthand(unwrapped.shape, {}, types); return ( <span className="fern-api-property-meta"> <span>{typeShorthand}</span> @@ -109,18 +105,20 @@ function toPrimitiveTypeLabelsNumeric( } function toPrimitiveTypeLabelsString({ + format, minLength, maxLength, regex, }: { + format: string | undefined; minLength: number | undefined; maxLength: number | undefined; regex: string | undefined; }): string[] { const labels = []; - if (regex != null) { - labels.push(`format: "${regex}"`); + if (format != null || regex != null) { + labels.push(`format: "${format ?? regex}"`); } if (minLength != null && maxLength != null && minLength === maxLength) { @@ -157,14 +155,9 @@ function toPrimitiveTypeLabelsString({ export function renderTypeShorthand( shape: TypeShapeOrReference, - { - plural = false, - withArticle = false, - nullable = false, - }: TypeShorthandOptions = { + { plural = false, withArticle = false }: TypeShorthandOptions = { plural: false, withArticle: false, - nullable: false, }, types: Record<string, TypeDefinition> ): string { @@ -173,8 +166,12 @@ export function renderTypeShorthand( const maybeWithArticle = (article: string, stringWithoutArticle: string) => withArticle ? `${article} ${stringWithoutArticle}` : stringWithoutArticle; - if (unwrapped.isOptional) { - return `${maybeWithArticle("an", nullable ? "optional" : "optional")} ${renderTypeShorthand(unwrapped.shape, { plural }, types)}`; + if (unwrapped.isNullable && unwrapped.isOptional) { + return `${maybeWithArticle("a", "nullable or optional")} ${renderTypeShorthand(unwrapped.shape, { plural }, types)}`; + } else if (unwrapped.isNullable) { + return `${maybeWithArticle("a", "nullable")} ${renderTypeShorthand(unwrapped.shape, { plural }, types)}`; + } else if (unwrapped.isOptional) { + return `${maybeWithArticle("an", "optional")} ${renderTypeShorthand(unwrapped.shape, { plural }, types)}`; } return visitDiscriminatedUnion(unwrapped.shape)._visit({ diff --git a/packages/parsers/package.json b/packages/parsers/package.json index 5829c82d9c..b3d4e5bfc5 100644 --- a/packages/parsers/package.json +++ b/packages/parsers/package.json @@ -1,6 +1,6 @@ { "name": "@fern-api/docs-parsers", - "version": "0.0.22", + "version": "0.0.25", "repository": { "type": "git", "url": "https://github.com/fern-api/fern-platform.git", diff --git a/packages/parsers/src/__test__/__snapshots__/openapi/cohere.json b/packages/parsers/src/__test__/__snapshots__/openapi/cohere.json index 5968d256f7..18a6359bf9 100644 --- a/packages/parsers/src/__test__/__snapshots__/openapi/cohere.json +++ b/packages/parsers/src/__test__/__snapshots__/openapi/cohere.json @@ -3364,9 +3364,9 @@ "type": "json", "value": { "id": "string", - "finish_reason": "string", + "finish_reason": "COMPLETE", "message": { - "role": "string" + "role": "assistant" } } }, @@ -3379,9 +3379,9 @@ "type": "json", "value": { "id": "string", - "finish_reason": "string", + "finish_reason": "COMPLETE", "message": { - "role": "string" + "role": "assistant" } } }, @@ -4404,7 +4404,7 @@ "text": "string", "index": 0, "is_finished": false, - "event_type": "string" + "event_type": "text-generation" } }, "snippets": {} @@ -4435,7 +4435,7 @@ "text": "string", "index": 0, "is_finished": false, - "event_type": "string" + "event_type": "text-generation" } }, "snippets": {} @@ -12649,11 +12649,11 @@ "embed_jobs": [ { "job_id": "string", - "status": "string", + "status": "processing", "created_at": "string", "input_dataset_id": "string", "model": "string", - "truncate": "string" + "truncate": "START" } ] } @@ -13730,11 +13730,11 @@ "type": "json", "value": { "job_id": "string", - "status": "string", + "status": "processing", "created_at": "string", "input_dataset_id": "string", "model": "string", - "truncate": "string" + "truncate": "START" } }, "snippets": {} @@ -16871,7 +16871,7 @@ 0 ], "labels": {}, - "classification_type": "string" + "classification_type": "single-label" } ] } @@ -17479,8 +17479,8 @@ "name": "string", "created_at": "string", "updated_at": "string", - "dataset_type": "string", - "validation_status": "string" + "dataset_type": "embed-input", + "validation_status": "unknown" } ] } @@ -19192,8 +19192,8 @@ "name": "string", "created_at": "string", "updated_at": "string", - "dataset_type": "string", - "validation_status": "string" + "dataset_type": "embed-input", + "validation_status": "unknown" } } }, @@ -25463,13 +25463,13 @@ "value": { "name": "string", "endpoints": [ - "string" + "chat" ], "finetuned": false, "context_length": 0, "tokenizer_url": "string", "default_endpoints": [ - "string" + "chat" ] } }, @@ -26000,13 +26000,13 @@ { "name": "string", "endpoints": [ - "string" + "chat" ], "finetuned": false, "context_length": 0, "tokenizer_url": "string", "default_endpoints": [ - "string" + "chat" ] } ] diff --git a/packages/parsers/src/__test__/__snapshots__/openapi/deeptune.json b/packages/parsers/src/__test__/__snapshots__/openapi/deeptune.json index 5af287268a..5023c472c7 100644 --- a/packages/parsers/src/__test__/__snapshots__/openapi/deeptune.json +++ b/packages/parsers/src/__test__/__snapshots__/openapi/deeptune.json @@ -617,9 +617,15 @@ "shape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } } @@ -712,9 +718,15 @@ "shape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } } diff --git a/packages/parsers/src/__test__/__snapshots__/openapi/uploadcare.json b/packages/parsers/src/__test__/__snapshots__/openapi/uploadcare.json index 6f663fc341..13dae9546f 100644 --- a/packages/parsers/src/__test__/__snapshots__/openapi/uploadcare.json +++ b/packages/parsers/src/__test__/__snapshots__/openapi/uploadcare.json @@ -168,9 +168,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -189,9 +195,16 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string", + "format": "uri" + } + } } } }, @@ -202,9 +215,16 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string", + "format": "uri" + } + } } } }, @@ -774,9 +794,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -1219,9 +1245,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -1603,9 +1635,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -2131,9 +2169,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -2590,9 +2634,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -3049,9 +3099,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -3072,7 +3128,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -3423,9 +3480,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -3446,7 +3509,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -3866,9 +3930,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -4221,9 +4291,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -4365,7 +4441,7 @@ "responseBody": { "type": "json", "value": { - "status": "string" + "status": "in_progress" } }, "snippets": { @@ -4472,9 +4548,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -4827,9 +4909,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -4971,7 +5059,7 @@ "responseBody": { "type": "json", "value": { - "status": "string" + "status": "in_progress" } }, "snippets": { @@ -5078,9 +5166,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -5470,9 +5564,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -5614,7 +5714,7 @@ "responseBody": { "type": "json", "value": { - "status": "string" + "status": "in_progress" } }, "snippets": { @@ -5729,9 +5829,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -6254,9 +6360,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -6405,7 +6517,7 @@ "result": { "file_id": "test-uuid-replacement" }, - "status": "string" + "status": "in_progress" } }, "snippets": { @@ -6527,9 +6639,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -6801,9 +6919,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -7075,9 +7199,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -7419,9 +7549,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -7686,12 +7822,18 @@ { "key": "Accept", "valueShape": { - "type": "enum", - "values": [ - { - "value": "application/vnd.uploadcare-v0.7+json" + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "enum", + "values": [ + { + "value": "application/vnd.uploadcare-v0.7+json" + } + ] } - ] + } }, "description": "Version header." } @@ -7708,9 +7850,16 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string", + "format": "uri" + } + } } } }, @@ -7721,9 +7870,16 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string", + "format": "uri" + } + } } } }, @@ -8051,12 +8207,18 @@ { "key": "Accept", "valueShape": { - "type": "enum", - "values": [ - { - "value": "application/vnd.uploadcare-v0.7+json" + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "enum", + "values": [ + { + "value": "application/vnd.uploadcare-v0.7+json" + } + ] } - ] + } }, "description": "Version header." } @@ -8369,12 +8531,18 @@ { "key": "Accept", "valueShape": { - "type": "enum", - "values": [ - { - "value": "application/vnd.uploadcare-v0.7+json" + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "enum", + "values": [ + { + "value": "application/vnd.uploadcare-v0.7+json" + } + ] } - ] + } }, "description": "Version header." } @@ -8641,9 +8809,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -8892,9 +9066,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -9172,9 +9352,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -9807,9 +9993,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -10093,9 +10285,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -10380,9 +10578,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -10401,9 +10605,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -10759,9 +10969,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -11156,9 +11372,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -11201,9 +11423,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -11546,9 +11774,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -11958,9 +12192,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -12003,9 +12243,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -12388,7 +12634,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -12440,7 +12687,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -12490,9 +12738,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "datetime" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "datetime" + } + } } } }, @@ -12503,9 +12757,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "datetime" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "datetime" + } + } } } }, @@ -12568,9 +12828,16 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string", + "format": "uri" + } + } } } }, @@ -12592,13 +12859,8 @@ { "key": "size", "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "integer" - } - } + "type": "enum", + "values": [] }, "description": "File size in bytes." }, @@ -12609,7 +12871,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -12666,9 +12929,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "datetime" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "datetime" + } + } } } }, @@ -12679,9 +12948,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "datetime" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "datetime" + } + } } } }, @@ -12744,15 +13019,22 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" - } - } - }, - "description": "Publicly available file CDN URL. Available if a file is not deleted." - }, - { + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "description": "Publicly available file CDN URL. Available if a file is not deleted." + }, + { "key": "original_filename", "valueShape": { "type": "alias", @@ -12785,7 +13067,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -12823,9 +13106,15 @@ { "key": "variations", "valueShape": { - "type": "object", - "extends": [], - "properties": [] + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "object", + "extends": [], + "properties": [] + } + } }, "description": "Dictionary of other files that were created using this file as a source. It's used for video processing and document conversion jobs. E.g., `<conversion_path>: <uuid>`." }, @@ -12855,9 +13144,15 @@ "metadata": { "name": "metadata", "shape": { - "type": "object", - "extends": [], - "properties": [] + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "object", + "extends": [], + "properties": [] + } + } }, "description": "Arbitrary metadata associated with a file." }, @@ -12877,79 +13172,85 @@ "contentInfo": { "name": "contentInfo", "shape": { - "type": "object", - "extends": [], - "properties": [ - { - "key": "mime", - "valueShape": { - "type": "object", - "extends": [], - "properties": [ - { - "key": "mime", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "string" - } - } - }, - "description": "Full MIME type." - }, - { - "key": "type", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "string" - } + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "object", + "extends": [], + "properties": [ + { + "key": "mime", + "valueShape": { + "type": "object", + "extends": [], + "properties": [ + { + "key": "mime", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } + }, + "description": "Full MIME type." + }, + { + "key": "type", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } + }, + "description": "Type of MIME type." + }, + { + "key": "subtype", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } + }, + "description": "Subtype of MIME type." } - }, - "description": "Type of MIME type." + ] }, - { - "key": "subtype", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "string" - } - } - }, - "description": "Subtype of MIME type." + "description": "MIME type." + }, + { + "key": "image", + "valueShape": { + "type": "alias", + "value": { + "type": "id", + "id": "imageInfo" + } + } + }, + { + "key": "video", + "valueShape": { + "type": "alias", + "value": { + "type": "id", + "id": "videoInfo" + } } - ] - }, - "description": "MIME type." - }, - { - "key": "image", - "valueShape": { - "type": "alias", - "value": { - "type": "id", - "id": "imageInfo" - } - } - }, - { - "key": "video", - "valueShape": { - "type": "alias", - "value": { - "type": "id", - "id": "videoInfo" } - } + ] } - ] + } }, "description": "Information about file content." }, @@ -13012,11 +13313,17 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer", - "minimum": 0, - "maximum": 8 + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer", + "minimum": 0, + "maximum": 8 + } + } } } }, @@ -13077,36 +13384,42 @@ { "key": "geo_location", "valueShape": { - "type": "object", - "extends": [], - "properties": [ - { - "key": "latitude", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "double" - } - } - }, - "description": "Location latitude." - }, - { - "key": "longitude", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "double" - } + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "object", + "extends": [], + "properties": [ + { + "key": "latitude", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + }, + "description": "Location latitude." + }, + { + "key": "longitude", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + }, + "description": "Location longitude." } - }, - "description": "Location longitude." + ] } - ] + } }, "description": "Geo-location of image from EXIF." }, @@ -13115,9 +13428,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "datetime" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "datetime" + } + } } } }, @@ -13157,9 +13476,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } }, @@ -13183,9 +13508,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } }, @@ -13206,9 +13537,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } }, @@ -13219,9 +13556,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -13232,9 +13575,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } }, @@ -13245,9 +13594,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } }, @@ -13312,9 +13667,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "integer" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "integer" + } + } } } }, @@ -13325,9 +13686,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "string" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } } } }, @@ -13345,186 +13712,222 @@ "legacyVideoInfo": { "name": "legacyVideoInfo", "shape": { - "type": "object", - "extends": [], - "properties": [ - { - "key": "duration", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "double" - } - } - }, - "description": "Video file's duration in milliseconds." - }, - { - "key": "format", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "string" - } - } - }, - "description": "Video file's format." - }, - { - "key": "bitrate", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "double" - } - } - }, - "description": "Video file's bitrate." - }, - { - "key": "audio", - "valueShape": { - "type": "object", - "extends": [], - "properties": [ - { - "key": "bitrate", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "double" - } - } - }, - "description": "Audio stream's bitrate." - }, - { - "key": "codec", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "string" - } - } - }, - "description": "Audio stream's codec." - }, - { - "key": "sample_rate", - "valueShape": { - "type": "alias", + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "object", + "extends": [], + "properties": [ + { + "key": "duration", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", "value": { - "type": "primitive", - "value": { - "type": "double" - } + "type": "double" } - }, - "description": "Audio stream's sample rate." + } }, - { - "key": "channels", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "string" - } - } - }, - "description": "Audio stream's number of channels." - } - ] - }, - "description": "Audio stream's metadata." - }, - { - "key": "video", - "valueShape": { - "type": "object", - "extends": [], - "properties": [ - { - "key": "height", - "valueShape": { - "type": "alias", + "description": "Video file's duration in milliseconds." + }, + { + "key": "format", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", "value": { - "type": "primitive", - "value": { - "type": "double" - } + "type": "string" } - }, - "description": "Video stream's image height." + } }, - { - "key": "width", - "valueShape": { - "type": "alias", + "description": "Video file's format." + }, + { + "key": "bitrate", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", "value": { - "type": "primitive", - "value": { - "type": "double" - } + "type": "double" } - }, - "description": "Video stream's image width." + } }, - { - "key": "frame_rate", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "double" - } + "description": "Video file's bitrate." + }, + { + "key": "audio", + "valueShape": { + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "object", + "extends": [], + "properties": [ + { + "key": "bitrate", + "valueShape": { + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + } + } + }, + "description": "Audio stream's bitrate." + }, + { + "key": "codec", + "valueShape": { + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } + } + } + }, + "description": "Audio stream's codec." + }, + { + "key": "sample_rate", + "valueShape": { + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + } + } + }, + "description": "Audio stream's sample rate." + }, + { + "key": "channels", + "valueShape": { + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } + } + } + }, + "description": "Audio stream's number of channels." + } + ] } - }, - "description": "Video stream's frame rate." + } }, - { - "key": "bitrate", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "double" - } + "description": "Audio stream's metadata." + }, + { + "key": "video", + "valueShape": { + "type": "object", + "extends": [], + "properties": [ + { + "key": "height", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + }, + "description": "Video stream's image height." + }, + { + "key": "width", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + }, + "description": "Video stream's image width." + }, + { + "key": "frame_rate", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + }, + "description": "Video stream's frame rate." + }, + { + "key": "bitrate", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "double" + } + } + }, + "description": "Video stream's bitrate." + }, + { + "key": "codec", + "valueShape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "string" + } + } + }, + "description": "Video stream codec." } - }, - "description": "Video stream's bitrate." + ] }, - { - "key": "codec", - "valueShape": { - "type": "alias", - "value": { - "type": "primitive", - "value": { - "type": "string" - } - } - }, - "description": "Video stream codec." - } - ] - }, - "description": "Video stream's metadata." + "description": "Video stream's metadata." + } + ] } - ] + } }, "description": "Video metadata." }, @@ -13616,7 +14019,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -13629,7 +14033,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -13671,7 +14076,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "email" } } }, @@ -13808,7 +14214,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "uri" } } }, @@ -13859,7 +14266,8 @@ "value": { "type": "primitive", "value": { - "type": "string" + "type": "string", + "format": "password" } } }, @@ -14146,9 +14554,15 @@ "valueShape": { "type": "alias", "value": { - "type": "primitive", - "value": { - "type": "uuid" + "type": "nullable", + "shape": { + "type": "alias", + "value": { + "type": "primitive", + "value": { + "type": "uuid" + } + } } } }, @@ -14157,27 +14571,33 @@ { "key": "addon_name", "valueShape": { - "type": "enum", - "values": [ - { - "value": "aws_rekognition_detect_labels" - }, - { - "value": "aws_rekognition_detect_moderation_labels" - }, - { - "value": "uc_clamav_virus_scan" - }, - { - "value": "remove_bg" - }, - { - "value": "zamzar_convert_document" - }, - { - "value": "zencoder_convert_video" + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "enum", + "values": [ + { + "value": "aws_rekognition_detect_labels" + }, + { + "value": "aws_rekognition_detect_moderation_labels" + }, + { + "value": "uc_clamav_virus_scan" + }, + { + "value": "remove_bg" + }, + { + "value": "zamzar_convert_document" + }, + { + "value": "zencoder_convert_video" + } + ] } - ] + } }, "description": "Add-On name." }, @@ -15024,50 +15444,56 @@ "applicationDataObject": { "name": "applicationDataObject", "shape": { - "type": "object", - "extends": [], - "properties": [ - { - "key": "aws_rekognition_detect_labels", - "valueShape": { - "type": "alias", - "value": { - "type": "id", - "id": "awsRekognitionDetectLabels_v2016_06_27" - } - } - }, - { - "key": "aws_rekognition_detect_moderation_labels", - "valueShape": { - "type": "alias", - "value": { - "type": "id", - "id": "awsRekognitionDetectModerationLabels_v2016_06_27" - } - } - }, - { - "key": "remove_bg", - "valueShape": { - "type": "alias", - "value": { - "type": "id", - "id": "removeBg_v1_0" - } - } - }, - { - "key": "uc_clamav_virus_scan", - "valueShape": { - "type": "alias", - "value": { - "type": "id", - "id": "ucClamavVirusScan" + "type": "alias", + "value": { + "type": "nullable", + "shape": { + "type": "object", + "extends": [], + "properties": [ + { + "key": "aws_rekognition_detect_labels", + "valueShape": { + "type": "alias", + "value": { + "type": "id", + "id": "awsRekognitionDetectLabels_v2016_06_27" + } + } + }, + { + "key": "aws_rekognition_detect_moderation_labels", + "valueShape": { + "type": "alias", + "value": { + "type": "id", + "id": "awsRekognitionDetectModerationLabels_v2016_06_27" + } + } + }, + { + "key": "remove_bg", + "valueShape": { + "type": "alias", + "value": { + "type": "id", + "id": "removeBg_v1_0" + } + } + }, + { + "key": "uc_clamav_virus_scan", + "valueShape": { + "type": "alias", + "value": { + "type": "id", + "id": "ucClamavVirusScan" + } + } } - } + ] } - ] + } }, "description": "Dictionary of application names and data associated with these applications." }, diff --git a/packages/parsers/src/__test__/createSnapshots.test.ts b/packages/parsers/src/__test__/createSnapshots.test.ts index 6c4366b83c..5bdcf7947a 100644 --- a/packages/parsers/src/__test__/createSnapshots.test.ts +++ b/packages/parsers/src/__test__/createSnapshots.test.ts @@ -59,11 +59,11 @@ describe("OpenAPI snapshot tests", () => { // Create snapshot if (errors.length > 0) { - console.error("errors:", errors); + // console.error("errors:", errors); } // expect(errors).toHaveLength(0); if (warnings.length > 0) { - console.warn("warnings:", warnings); + // console.warn("warnings:", warnings); } converted.id = "test-uuid-replacement"; diff --git a/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/NullableType.ts b/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/NullableType.ts new file mode 100644 index 0000000000..de3af143a4 --- /dev/null +++ b/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/NullableType.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernRegistry from "../../../../../../../index"; + +export interface NullableType { + shape: FernRegistry.api.latest.TypeShape; +} diff --git a/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts b/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts index 5a0b72d115..75bb5909e2 100644 --- a/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts +++ b/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.ts @@ -8,6 +8,7 @@ export type TypeReference = | FernRegistry.api.latest.TypeReference.Id | FernRegistry.api.latest.TypeReference.Primitive | FernRegistry.api.latest.TypeReference.Optional + | FernRegistry.api.latest.TypeReference.Nullable | FernRegistry.api.latest.TypeReference.List | FernRegistry.api.latest.TypeReference.Set | FernRegistry.api.latest.TypeReference.Map @@ -28,6 +29,10 @@ export declare namespace TypeReference { type: "optional"; } + interface Nullable extends FernRegistry.api.latest.NullableType { + type: "nullable"; + } + interface List extends FernRegistry.api.latest.ListType { type: "list"; } diff --git a/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts b/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts index 7c3d80e6b6..79cdba3349 100644 --- a/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts +++ b/packages/parsers/src/client/generated/api/resources/api/resources/latest/resources/type/types/index.ts @@ -21,6 +21,7 @@ export * from "./FormDataField"; export * from "./FormDataProperty"; export * from "./FormDataFile"; export * from "./FormDataFiles"; +export * from "./NullableType"; export * from "./OptionalType"; export * from "./ListType"; export * from "./SetType"; diff --git a/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts b/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts index 8903b99b94..fbca354844 100644 --- a/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts +++ b/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.ts @@ -3,6 +3,7 @@ */ export interface StringType { + format: string | undefined; regex: string | undefined; minLength: number | undefined; maxLength: number | undefined; diff --git a/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts b/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts index 8903b99b94..fbca354844 100644 --- a/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts +++ b/packages/parsers/src/client/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.ts @@ -3,6 +3,7 @@ */ export interface StringType { + format: string | undefined; regex: string | undefined; minLength: number | undefined; maxLength: number | undefined; diff --git a/packages/parsers/src/openapi/3.1/guards/isNullableSchema.ts b/packages/parsers/src/openapi/3.1/guards/isNullableSchema.ts new file mode 100644 index 0000000000..2a3488290d --- /dev/null +++ b/packages/parsers/src/openapi/3.1/guards/isNullableSchema.ts @@ -0,0 +1,7 @@ +import { OpenAPIV3_1 } from "openapi-types"; + +export function isNullableSchema( + input: OpenAPIV3_1.NonArraySchemaObject +): input is OpenAPIV3_1.NonArraySchemaObject & { nullable: boolean } { + return "nullable" in input && typeof input.nullable === "boolean"; +} diff --git a/packages/parsers/src/openapi/3.1/paths/request/RequestBodyObjectConverter.node.ts b/packages/parsers/src/openapi/3.1/paths/request/RequestBodyObjectConverter.node.ts index 5281515aa0..16f8b7ae76 100644 --- a/packages/parsers/src/openapi/3.1/paths/request/RequestBodyObjectConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/paths/request/RequestBodyObjectConverter.node.ts @@ -6,6 +6,7 @@ import { BaseOpenApiV3_1ConverterNodeConstructorArgs, } from "../../../BaseOpenApiV3_1Converter.node"; import { resolveRequestReference } from "../../../utils/3.1/resolveRequestReference"; +import { maybeSingleValueToArray } from "../../../utils/maybeSingleValueToArray"; import { RequestMediaTypeObjectConverterNode } from "./RequestMediaTypeObjectConverter.node"; export class RequestBodyObjectConverterNode extends BaseOpenApiV3_1ConverterNode< @@ -64,17 +65,9 @@ export class RequestBodyObjectConverterNode extends BaseOpenApiV3_1ConverterNode convert(): FernRegistry.api.latest.HttpRequest[] { return Object.entries(this.requestBodiesByContentType ?? {}) .flatMap(([contentType, mediaTypeObject]) => { - let maybeBodies = mediaTypeObject.convert(); + const maybeBodies = maybeSingleValueToArray(mediaTypeObject.convert()); - if (maybeBodies == null) { - return undefined; - } - - if (!Array.isArray(maybeBodies)) { - maybeBodies = [maybeBodies]; - } - - return maybeBodies.map((body) => ({ + return maybeBodies?.map((body) => ({ description: this.description, contentType, body, diff --git a/packages/parsers/src/openapi/3.1/paths/request/RequestMediaTypeObjectConverter.node.ts b/packages/parsers/src/openapi/3.1/paths/request/RequestMediaTypeObjectConverter.node.ts index 3f4bc53d79..f471693401 100644 --- a/packages/parsers/src/openapi/3.1/paths/request/RequestMediaTypeObjectConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/paths/request/RequestMediaTypeObjectConverter.node.ts @@ -11,6 +11,7 @@ import { SUPPORTED_REQUEST_CONTENT_TYPES, } from "../../../types/format.types"; import { resolveReference } from "../../../utils/3.1/resolveReference"; +import { maybeSingleValueToArray } from "../../../utils/maybeSingleValueToArray"; import { MediaType } from "../../../utils/MediaType"; import { AvailabilityConverterNode } from "../../extensions/AvailabilityConverter.node"; import { isObjectSchema } from "../../guards/isObjectSchema"; @@ -188,25 +189,19 @@ export class RequestMediaTypeObjectConverterNode extends BaseOpenApiV3_1Converte }, ]; case "property": { - let maybeValueShapes = field.convert(); + const maybeValueShapes = maybeSingleValueToArray( + field.convert() + ); const type = field.multipartType; - if ( - !Array.isArray(maybeValueShapes) && - maybeValueShapes != null - ) { - maybeValueShapes = [maybeValueShapes]; - } - return maybeValueShapes?.map((valueShape) => { - return { - type, - key: FernRegistry.PropertyKey(key), - contentType: field.contentType, - valueShape, - description: field.description, - availability: field.availability?.convert(), - }; - }); + return maybeValueShapes?.map((valueShape) => ({ + type, + key: FernRegistry.PropertyKey(key), + contentType: field.contentType, + valueShape, + description: field.description, + availability: field.availability?.convert(), + })); } case undefined: return []; diff --git a/packages/parsers/src/openapi/3.1/paths/response/ResponseMediaTypeObjectConverter.node.ts b/packages/parsers/src/openapi/3.1/paths/response/ResponseMediaTypeObjectConverter.node.ts index 153fea4f70..96452bb337 100644 --- a/packages/parsers/src/openapi/3.1/paths/response/ResponseMediaTypeObjectConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/paths/response/ResponseMediaTypeObjectConverter.node.ts @@ -12,6 +12,7 @@ import { SUPPORTED_STREAMING_FORMATS, } from "../../../types/format.types"; import { resolveSchemaReference } from "../../../utils/3.1/resolveSchemaReference"; +import { maybeSingleValueToArray } from "../../../utils/maybeSingleValueToArray"; import { MediaType } from "../../../utils/MediaType"; import { RedocExampleConverterNode } from "../../extensions/examples/RedocExampleConverter.node"; import { SchemaConverterNode } from "../../schemas/SchemaConverter.node"; @@ -224,14 +225,9 @@ export class ResponseMediaTypeObjectConverterNode extends BaseOpenApiV3_1Convert | undefined { switch (this.streamingFormat) { case "json": { - let maybeShapes = this.schema?.convert(); - if (maybeShapes == null) { - return undefined; - } - if (!Array.isArray(maybeShapes)) { - maybeShapes = [maybeShapes]; - } - return maybeShapes.map((shape) => ({ + const maybeShapes = maybeSingleValueToArray(this.schema?.convert()); + + return maybeShapes?.map((shape) => ({ type: "stream", // TODO: Parse terminator (probably extension) terminator: "[DATA]", @@ -256,10 +252,8 @@ export class ResponseMediaTypeObjectConverterNode extends BaseOpenApiV3_1Convert switch (this.contentType) { case "application/json": if (this.streamingFormat == null) { - let maybeShapes = this.schema?.convert(); - if (!Array.isArray(maybeShapes) && maybeShapes != null) { - maybeShapes = [maybeShapes]; - } + const maybeShapes = maybeSingleValueToArray(this.schema?.convert()); + return maybeShapes ?.map((shape) => { if ( @@ -285,15 +279,10 @@ export class ResponseMediaTypeObjectConverterNode extends BaseOpenApiV3_1Convert return undefined; } } else if (this.unsupportedContentType != null) { - let maybeShapes = this.schema?.convert(); - if (maybeShapes == null) { - return undefined; - } - if (!Array.isArray(maybeShapes)) { - maybeShapes = [maybeShapes]; - } + const maybeShapes = maybeSingleValueToArray(this.schema?.convert()); + return maybeShapes - .map((shape) => { + ?.map((shape) => { const type = shape.type; switch (type) { case "alias": diff --git a/packages/parsers/src/openapi/3.1/paths/response/ResponsesObjectConverter.node.ts b/packages/parsers/src/openapi/3.1/paths/response/ResponsesObjectConverter.node.ts index c61239474b..3a64eb0d92 100644 --- a/packages/parsers/src/openapi/3.1/paths/response/ResponsesObjectConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/paths/response/ResponsesObjectConverter.node.ts @@ -5,6 +5,7 @@ import { BaseOpenApiV3_1ConverterNode, BaseOpenApiV3_1ConverterNodeConstructorArgs, } from "../../../BaseOpenApiV3_1Converter.node"; +import { maybeSingleValueToArray } from "../../../utils/maybeSingleValueToArray"; import { STATUS_CODE_MESSAGES } from "../../../utils/statusCodes"; import { RedocExampleConverterNode } from "../../extensions/examples/RedocExampleConverter.node"; import { convertOperationObjectProperties } from "../parameters/ParameterBaseObjectConverter.node"; @@ -110,21 +111,16 @@ export class ResponsesObjectConverterNode extends BaseOpenApiV3_1ConverterNode< convertResponseObjectToErrors(): FernRegistry.api.latest.ErrorResponse[] { return Object.entries(this.errorsByStatusCode ?? {}) .flatMap(([statusCode, response]) => { - // TODO: resolve reference here, if not done already return response.responses?.flatMap((res) => { const schema = res.schema; - let maybeShapes = schema?.convert(); + const maybeShapes = maybeSingleValueToArray(schema?.convert()); - if (maybeShapes == null || schema == null) { + if (schema == null) { return undefined; } - if (!Array.isArray(maybeShapes)) { - maybeShapes = [maybeShapes]; - } - return maybeShapes - .map((shape) => ({ + ?.map((shape) => ({ statusCode: parseInt(statusCode), shape, description: response.description ?? schema.description, diff --git a/packages/parsers/src/openapi/3.1/schemas/ArrayConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/ArrayConverter.node.ts index 80438de129..e764c0b572 100644 --- a/packages/parsers/src/openapi/3.1/schemas/ArrayConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/ArrayConverter.node.ts @@ -4,6 +4,7 @@ import { BaseOpenApiV3_1ConverterNodeConstructorArgs, BaseOpenApiV3_1ConverterNodeWithExample, } from "../../BaseOpenApiV3_1Converter.node"; +import { maybeSingleValueToArray } from "../../utils/maybeSingleValueToArray"; import { SchemaConverterNode } from "./SchemaConverter.node"; export declare namespace ArrayConverterNode { @@ -46,17 +47,9 @@ export class ArrayConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample< } convert(): ArrayConverterNode.Output[] | undefined { - let maybeItemShapes = this.item?.convert(); + const maybeItemShapes = maybeSingleValueToArray(this.item?.convert()); - if (maybeItemShapes == null) { - return undefined; - } - - if (!Array.isArray(maybeItemShapes)) { - maybeItemShapes = [maybeItemShapes]; - } - - return maybeItemShapes.map((itemShape) => ({ + return maybeItemShapes?.map((itemShape) => ({ type: "alias", value: { type: "list", diff --git a/packages/parsers/src/openapi/3.1/schemas/ComponentsConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/ComponentsConverter.node.ts index b2952a5d4f..20a6bbdb49 100644 --- a/packages/parsers/src/openapi/3.1/schemas/ComponentsConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/ComponentsConverter.node.ts @@ -5,6 +5,7 @@ import { BaseOpenApiV3_1ConverterNode, BaseOpenApiV3_1ConverterNodeConstructorArgs, } from "../../BaseOpenApiV3_1Converter.node"; +import { maybeSingleValueToArray } from "../../utils/maybeSingleValueToArray"; import { SchemaConverterNode } from "./SchemaConverter.node"; export class ComponentsConverterNode extends BaseOpenApiV3_1ConverterNode< @@ -52,16 +53,12 @@ export class ComponentsConverterNode extends BaseOpenApiV3_1ConverterNode< Object.entries(this.typeSchemas) .map(([key, value]) => { const name = value.name ?? key; - let maybeShapes = value.convert(); + const maybeShapes = maybeSingleValueToArray(value.convert()); if (maybeShapes == null) { return [key, undefined]; } - if (!Array.isArray(maybeShapes)) { - maybeShapes = [maybeShapes]; - } - return [ FernRegistry.TypeId(key), { diff --git a/packages/parsers/src/openapi/3.1/schemas/MixedSchemaConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/MixedSchemaConverter.node.ts index 6dce90dfb8..073b3a8039 100644 --- a/packages/parsers/src/openapi/3.1/schemas/MixedSchemaConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/MixedSchemaConverter.node.ts @@ -5,6 +5,7 @@ import { BaseOpenApiV3_1ConverterNodeConstructorArgs, BaseOpenApiV3_1ConverterNodeWithExample, } from "../../BaseOpenApiV3_1Converter.node"; +import { maybeSingleValueToArray } from "../../utils/maybeSingleValueToArray"; import { SchemaConverterNode } from "./SchemaConverter.node"; export declare namespace MixedSchemaConverterNode { @@ -59,16 +60,9 @@ export class MixedSchemaConverterNode extends BaseOpenApiV3_1ConverterNodeWithEx const concreteTypeNodes: FernRegistry.api.latest.UndiscriminatedUnionVariant[][] = this.typeNodes .map((typeNode) => { - let maybeShapes = typeNode.convert(); - if (maybeShapes == null) { - return undefined; - } + const maybeShapes = maybeSingleValueToArray(typeNode.convert()); - if (!Array.isArray(maybeShapes)) { - maybeShapes = [maybeShapes]; - } - - return maybeShapes.map((shape) => ({ + return maybeShapes?.map((shape) => ({ displayName: typeNode.name, shape, description: typeNode.description, @@ -92,12 +86,11 @@ export class MixedSchemaConverterNode extends BaseOpenApiV3_1ConverterNodeWithEx variants, })); - // TODO: right now, this is handled as an optional, but we should handle it as nullable return this.nullable ? unions.map((union) => ({ type: "alias" as const, value: { - type: "optional" as const, + type: "nullable" as const, default: union.variants[0], shape: union, }, diff --git a/packages/parsers/src/openapi/3.1/schemas/ObjectConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/ObjectConverter.node.ts index b025b87a54..441d22785f 100644 --- a/packages/parsers/src/openapi/3.1/schemas/ObjectConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/ObjectConverter.node.ts @@ -8,6 +8,7 @@ import { import { convertToObjectProperties } from "../../utils/3.1/convertToObjectProperties"; import { getSchemaIdFromReference } from "../../utils/3.1/getSchemaIdFromReference"; import { resolveSchemaReference } from "../../utils/3.1/resolveSchemaReference"; +import { maybeSingleValueToArray } from "../../utils/maybeSingleValueToArray"; import { isReferenceObject } from "../guards/isReferenceObject"; import { SchemaConverterNode } from "./SchemaConverter.node"; @@ -125,18 +126,12 @@ export class ObjectConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample ]; } - let maybeConvertedShapes = this.extraProperties.convert(); - - if (!Array.isArray(maybeConvertedShapes) && maybeConvertedShapes != null) { - maybeConvertedShapes = [maybeConvertedShapes]; - } - - if (maybeConvertedShapes == null) { - return undefined; - } + const maybeConvertedShapes = maybeSingleValueToArray( + this.extraProperties.convert() + ); return maybeConvertedShapes - .map((shape) => (shape.type === "alias" ? shape.value : undefined)) + ?.map((shape) => (shape.type === "alias" ? shape.value : undefined)) .filter(isNonNullish); } diff --git a/packages/parsers/src/openapi/3.1/schemas/OneOfConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/OneOfConverter.node.ts index 1d4e3e3f29..6975161dfa 100644 --- a/packages/parsers/src/openapi/3.1/schemas/OneOfConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/OneOfConverter.node.ts @@ -6,6 +6,7 @@ import { BaseOpenApiV3_1ConverterNodeWithExample, } from "../../BaseOpenApiV3_1Converter.node"; import { resolveSchemaReference } from "../../utils/3.1/resolveSchemaReference"; +import { maybeSingleValueToArray } from "../../utils/maybeSingleValueToArray"; import { SchemaConverterNode } from "./SchemaConverter.node"; export class OneOfConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample< @@ -112,14 +113,9 @@ export class OneOfConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample< discriminant: FernRegistry.PropertyKey(this.discriminant), variants: Object.entries(this.discriminatedMapping) .flatMap(([key, node]) => { - let convertedShape: - | FernRegistry.api.latest.TypeShape - | FernRegistry.api.latest.TypeShape[] - | undefined = node.convert(); - if (!Array.isArray(convertedShape) && convertedShape != null) { - convertedShape = [convertedShape]; - } - return convertedShape + const convertedShapes = maybeSingleValueToArray(node.convert()); + + return convertedShapes ?.map((shape) => { if (shape == null || shape.type !== "object") { return undefined; @@ -143,17 +139,11 @@ export class OneOfConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample< type: "undiscriminatedUnion", variants: this.undiscriminatedMapping .flatMap((node) => { - let convertedShape: - | FernRegistry.api.latest.TypeShape - | FernRegistry.api.latest.TypeShape[] - | undefined = node.convert(); - if ( - !Array.isArray(convertedShape) && - convertedShape != null - ) { - convertedShape = [convertedShape]; - } - return convertedShape + const convertedShapes = maybeSingleValueToArray( + node.convert() + ); + + return convertedShapes ?.map((shape) => { if (shape == null || shape.type !== "object") { return undefined; diff --git a/packages/parsers/src/openapi/3.1/schemas/SchemaConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/SchemaConverter.node.ts index cab65547a5..5178683a78 100644 --- a/packages/parsers/src/openapi/3.1/schemas/SchemaConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/SchemaConverter.node.ts @@ -5,12 +5,14 @@ import { BaseOpenApiV3_1ConverterNodeConstructorArgs, BaseOpenApiV3_1ConverterNodeWithExample, } from "../../BaseOpenApiV3_1Converter.node"; +import { maybeSingleValueToArray } from "../../utils/maybeSingleValueToArray"; import { AvailabilityConverterNode } from "../extensions/AvailabilityConverter.node"; import { isArraySchema } from "../guards/isArraySchema"; import { isBooleanSchema } from "../guards/isBooleanSchema"; import { isIntegerSchema } from "../guards/isIntegerSchema"; import { isMixedSchema } from "../guards/isMixedSchema"; import { isNonArraySchema } from "../guards/isNonArraySchema"; +import { isNullableSchema } from "../guards/isNullableSchema"; import { isNullSchema } from "../guards/isNullSchema"; import { isNumberSchema } from "../guards/isNumberSchema"; import { isObjectSchema } from "../guards/isObjectSchema"; @@ -21,13 +23,13 @@ import { ConstConverterNode } from "./ConstConverter.node"; import { MixedSchemaConverterNode } from "./MixedSchemaConverter.node"; import { ObjectConverterNode } from "./ObjectConverter.node"; import { OneOfConverterNode } from "./OneOfConverter.node"; -import { ReferenceConverterNode } from "./ReferenceConverter.node"; import { BooleanConverterNode } from "./primitives/BooleanConverter.node"; import { EnumConverterNode } from "./primitives/EnumConverter.node"; import { IntegerConverterNode } from "./primitives/IntegerConverter.node"; import { NullConverterNode } from "./primitives/NullConverter.node"; import { NumberConverterNode } from "./primitives/NumberConverter.node"; import { StringConverterNode } from "./primitives/StringConverter.node"; +import { ReferenceConverterNode } from "./ReferenceConverter.node"; export type PrimitiveType = | NumberConverterNode.Input @@ -49,7 +51,7 @@ export class SchemaConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample | undefined > | undefined; - + nullable: boolean | undefined; description: string | undefined; name: string | undefined; examples: unknown | undefined; @@ -72,6 +74,10 @@ export class SchemaConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample accessPath: this.accessPath, pathId: "x-fern-availability", }); + this.nullable = + isNonArraySchema(this.input) && isNullableSchema(this.input) + ? this.input.nullable + : undefined; // Check if the input is a reference object if (isReferenceObject(this.input)) { @@ -126,9 +132,8 @@ export class SchemaConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample pathId: this.pathId, }); } - // We assume that if one of is defined, it is an object node - if (typeof this.input.type === "string") { + else if (typeof this.input.type === "string") { switch (this.input.type) { case "object": if (isObjectSchema(this.input)) { @@ -226,7 +231,26 @@ export class SchemaConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample | FernRegistry.api.latest.TypeShape | FernRegistry.api.latest.TypeShape[] | undefined { - return this.typeShapeNode?.convert(); + const maybeShapes = this.typeShapeNode?.convert(); + const mappedShapes = maybeSingleValueToArray(maybeShapes)?.map((shape) => + this.nullable + ? { + type: "alias" as const, + value: { + type: "nullable" as const, + shape, + }, + } + : shape + ); + + if (maybeShapes == null) { + return undefined; + } + + return Array.isArray(maybeShapes) && maybeShapes.length > 1 + ? mappedShapes + : mappedShapes?.[0]; } example(): unknown | undefined { diff --git a/packages/parsers/src/openapi/3.1/schemas/__test__/MixedSchemaConverter.node.test.ts b/packages/parsers/src/openapi/3.1/schemas/__test__/MixedSchemaConverter.node.test.ts index 66135f37d6..8960b8c440 100644 --- a/packages/parsers/src/openapi/3.1/schemas/__test__/MixedSchemaConverter.node.test.ts +++ b/packages/parsers/src/openapi/3.1/schemas/__test__/MixedSchemaConverter.node.test.ts @@ -85,7 +85,7 @@ describe("MixedSchemaConverterNode", () => { expect(result?.type).toBe("alias"); expect( (result as FernRegistry.api.latest.TypeShape.Alias)?.value?.type - ).toBe("optional"); + ).toBe("nullable"); }); it("should return undefined when typeNodes is null", () => { diff --git a/packages/parsers/src/openapi/3.1/schemas/primitives/NullConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/primitives/NullConverter.node.ts index 253b3da6e9..470c78fb71 100644 --- a/packages/parsers/src/openapi/3.1/schemas/primitives/NullConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/primitives/NullConverter.node.ts @@ -4,6 +4,7 @@ import { BaseOpenApiV3_1ConverterNodeConstructorArgs, BaseOpenApiV3_1ConverterNodeWithExample, } from "../../../BaseOpenApiV3_1Converter.node"; +import { SchemaConverterNode } from "../SchemaConverter.node"; export declare namespace NullConverterNode { export interface Input extends OpenAPIV3_1.NonArraySchemaObject { @@ -12,7 +13,9 @@ export declare namespace NullConverterNode { export interface Output extends FernRegistry.api.latest.TypeShape.Alias { type: "alias"; - value: FernRegistry.api.latest.TypeReference.Unknown; + value: + | FernRegistry.api.latest.TypeReference.Nullable + | FernRegistry.api.latest.TypeReference.Unknown; } } @@ -21,6 +24,7 @@ export class NullConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample< NullConverterNode.Output > { displayName: string | undefined; + shape: SchemaConverterNode | undefined; constructor( args: BaseOpenApiV3_1ConverterNodeConstructorArgs<NullConverterNode.Input> @@ -37,8 +41,14 @@ export class NullConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample< return { type: "alias", value: { - type: "unknown", - displayName: this.displayName, + type: "nullable", + shape: { + type: "alias", + value: { + type: "unknown", + displayName: this.displayName, + }, + }, }, }; } diff --git a/packages/parsers/src/openapi/3.1/schemas/primitives/StringConverter.node.ts b/packages/parsers/src/openapi/3.1/schemas/primitives/StringConverter.node.ts index bff35d6ee0..2b2dd76ce6 100644 --- a/packages/parsers/src/openapi/3.1/schemas/primitives/StringConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/schemas/primitives/StringConverter.node.ts @@ -152,6 +152,7 @@ export class StringConverterNode extends BaseOpenApiV3_1ConverterNodeWithExample type: "primitive", value: { type, + format: type === "string" ? this.format : undefined, regex: this.regex, minLength: this.minLength, maxLength: this.maxLength, diff --git a/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/NullConverter.node.test.ts b/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/NullConverter.node.test.ts index 80565ff33d..647fd82e1f 100644 --- a/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/NullConverter.node.test.ts +++ b/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/NullConverter.node.test.ts @@ -20,8 +20,14 @@ describe("NullConverterNode", () => { expect(result).toEqual({ type: "alias", value: { - type: "unknown", - displayName: undefined, + type: "nullable", + shape: { + type: "alias", + value: { + type: "unknown", + displayName: undefined, + }, + }, }, }); }); @@ -42,8 +48,14 @@ describe("NullConverterNode", () => { expect(result).toEqual({ type: "alias", value: { - type: "unknown", - displayName: "NullType", + type: "nullable", + shape: { + type: "alias", + value: { + type: "unknown", + displayName: "NullType", + }, + }, }, }); }); diff --git a/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/StringConverter.node.test.ts b/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/StringConverter.node.test.ts index da839d1423..8320fefc17 100644 --- a/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/StringConverter.node.test.ts +++ b/packages/parsers/src/openapi/3.1/schemas/primitives/__test__/StringConverter.node.test.ts @@ -72,9 +72,6 @@ describe("StringConverterNode", () => { type: "primitive", value: { type: "uuid", - regex: undefined, - minLength: undefined, - maxLength: undefined, default: "test-default", }, }, diff --git a/packages/parsers/src/openapi/utils/3.1/convertToObjectProperties.ts b/packages/parsers/src/openapi/utils/3.1/convertToObjectProperties.ts index 6ca81b957b..e61013c728 100644 --- a/packages/parsers/src/openapi/utils/3.1/convertToObjectProperties.ts +++ b/packages/parsers/src/openapi/utils/3.1/convertToObjectProperties.ts @@ -4,6 +4,7 @@ import { ParameterBaseObjectConverterNode, SchemaConverterNode, } from "../../3.1"; +import { maybeSingleValueToArray } from "../maybeSingleValueToArray"; export function convertToObjectProperties( properties: @@ -17,17 +18,10 @@ export function convertToObjectProperties( const rawProperties = Object.entries(properties) .map(([key, node]) => { - let maybeValueShapes = node.convert(); - if (maybeValueShapes == null) { - return undefined; - } - - if (!Array.isArray(maybeValueShapes)) { - maybeValueShapes = [maybeValueShapes]; - } + const maybeValueShapes = maybeSingleValueToArray(node.convert()); return maybeValueShapes - .map((valueShape) => { + ?.map((valueShape) => { if (requiredProperties != null && !requiredProperties.includes(key)) { valueShape = { type: "alias", diff --git a/packages/parsers/src/openapi/utils/maybeSingleValueToArray.ts b/packages/parsers/src/openapi/utils/maybeSingleValueToArray.ts new file mode 100644 index 0000000000..b4914afcc5 --- /dev/null +++ b/packages/parsers/src/openapi/utils/maybeSingleValueToArray.ts @@ -0,0 +1,8 @@ +export function maybeSingleValueToArray<T>( + value: T | T[] | undefined +): T[] | undefined { + if (value == null) { + return undefined; + } + return Array.isArray(value) ? value : [value]; +} diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/NullableType.d.ts b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/NullableType.d.ts new file mode 100644 index 0000000000..d9843bceee --- /dev/null +++ b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/NullableType.d.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +import * as FernRegistry from "../../../../../../../index"; +export interface NullableType { + shape: FernRegistry.api.latest.TypeShape; +} diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/NullableType.js b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/NullableType.js new file mode 100644 index 0000000000..0b46289f5b --- /dev/null +++ b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/NullableType.js @@ -0,0 +1,4 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +export {}; diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.d.ts b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.d.ts index e6f29c406a..6556b3727b 100644 --- a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.d.ts +++ b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/TypeReference.d.ts @@ -2,7 +2,7 @@ * This file was auto-generated by Fern from our API Definition. */ import * as FernRegistry from "../../../../../../../index"; -export declare type TypeReference = FernRegistry.api.latest.TypeReference.Id | FernRegistry.api.latest.TypeReference.Primitive | FernRegistry.api.latest.TypeReference.Optional | FernRegistry.api.latest.TypeReference.List | FernRegistry.api.latest.TypeReference.Set | FernRegistry.api.latest.TypeReference.Map | FernRegistry.api.latest.TypeReference.Literal | FernRegistry.api.latest.TypeReference.Unknown; +export declare type TypeReference = FernRegistry.api.latest.TypeReference.Id | FernRegistry.api.latest.TypeReference.Primitive | FernRegistry.api.latest.TypeReference.Optional | FernRegistry.api.latest.TypeReference.Nullable | FernRegistry.api.latest.TypeReference.List | FernRegistry.api.latest.TypeReference.Set | FernRegistry.api.latest.TypeReference.Map | FernRegistry.api.latest.TypeReference.Literal | FernRegistry.api.latest.TypeReference.Unknown; export declare namespace TypeReference { interface Id extends FernRegistry.api.latest.TypeReferenceId { type: "id"; @@ -14,6 +14,9 @@ export declare namespace TypeReference { interface Optional extends FernRegistry.api.latest.OptionalType { type: "optional"; } + interface Nullable extends FernRegistry.api.latest.NullableType { + type: "nullable"; + } interface List extends FernRegistry.api.latest.ListType { type: "list"; } diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.d.ts b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.d.ts index 7c3d80e6b6..79cdba3349 100644 --- a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.d.ts +++ b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.d.ts @@ -21,6 +21,7 @@ export * from "./FormDataField"; export * from "./FormDataProperty"; export * from "./FormDataFile"; export * from "./FormDataFiles"; +export * from "./NullableType"; export * from "./OptionalType"; export * from "./ListType"; export * from "./SetType"; diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.js b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.js index 7c3d80e6b6..79cdba3349 100644 --- a/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.js +++ b/servers/fdr/src/api/generated/api/resources/api/resources/latest/resources/type/types/index.js @@ -21,6 +21,7 @@ export * from "./FormDataField"; export * from "./FormDataProperty"; export * from "./FormDataFile"; export * from "./FormDataFiles"; +export * from "./NullableType"; export * from "./OptionalType"; export * from "./ListType"; export * from "./SetType"; diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.d.ts b/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.d.ts index b3083c6aa9..d435d177a7 100644 --- a/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.d.ts +++ b/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/read/resources/type/types/StringType.d.ts @@ -2,6 +2,7 @@ * This file was auto-generated by Fern from our API Definition. */ export interface StringType { + format: string | undefined; regex: string | undefined; minLength: number | undefined; maxLength: number | undefined; diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.d.ts b/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.d.ts index b3083c6aa9..d435d177a7 100644 --- a/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.d.ts +++ b/servers/fdr/src/api/generated/api/resources/api/resources/v1/resources/register/resources/type/types/StringType.d.ts @@ -2,6 +2,7 @@ * This file was auto-generated by Fern from our API Definition. */ export interface StringType { + format: string | undefined; regex: string | undefined; minLength: number | undefined; maxLength: number | undefined;