diff --git a/gen/apiGen.ts b/gen/apiGen.ts index 569f3058..e755bac1 100644 --- a/gen/apiGen.ts +++ b/gen/apiGen.ts @@ -447,6 +447,10 @@ export default async function apiGen(lookup: Record) { // No-op: Handlebars template handles optional params signature. const importedTypes: string[] = [] + // When response schemas are complex (e.g., objects with index signatures) + // we may want to explicitly override the computed return type. + // If set, this takes precedence over the union of importedTypes. + let returnTypeOverride: string | undefined let pagerItemTypeName: string | undefined if (!isWebSocket) { Object.values(operation.specSection?.responses).forEach( @@ -534,18 +538,57 @@ export default async function apiGen(lookup: Record) { schema.type === 'object' && 'additionalProperties' in schema ) { - schema.additionalProperties - const addProps = - schema.additionalProperties as OpenAPIV3.SchemaObject - if (addProps.type === 'array' && '$ref' in addProps.items) { - const typeReference = lookup[addProps.items.$ref] - if ( - typeReference && - typeReference !== 'Error' && - !importedTypes.includes(typeReference + '[]') + const addProps = schema.additionalProperties as + | OpenAPIV3.ReferenceObject + | OpenAPIV3.SchemaObject + + // Handle maps (index signatures) properly. Previously we + // collapsed `{ [k: string]: T[] }` into just `T[]`, which + // dropped the object shape. Build a Record type + // and import the inner model type when applicable. + if (isRef(addProps)) { + const t = lookup[addProps.$ref] + if (t && t !== 'Error' && !importedTypes.includes(t)) + importedTypes.push(t) + returnTypeOverride = `Record` + } else if (isArraySchema(addProps as OpenAPIV3.SchemaObject)) { + const items = (addProps as OpenAPIV3.ArraySchemaObject).items + if (isRef(items)) { + const t = lookup[items.$ref] + if (t && t !== 'Error' && !importedTypes.includes(t)) + importedTypes.push(t) + returnTypeOverride = `Record` + } else if ( + (items as OpenAPIV3.SchemaObject)?.type === 'string' ) { - importedTypes.push(typeReference + '[]') + returnTypeOverride = 'Record' + } else if ( + (items as OpenAPIV3.SchemaObject)?.type === 'number' || + (items as OpenAPIV3.SchemaObject)?.type === 'integer' + ) { + returnTypeOverride = 'Record' + } else if ( + (items as OpenAPIV3.SchemaObject)?.type === 'boolean' + ) { + returnTypeOverride = 'Record' + } else { + returnTypeOverride = 'Record' } + } else if ( + (addProps as OpenAPIV3.SchemaObject)?.type === 'string' + ) { + returnTypeOverride = 'Record' + } else if ( + (addProps as OpenAPIV3.SchemaObject)?.type === 'number' || + (addProps as OpenAPIV3.SchemaObject)?.type === 'integer' + ) { + returnTypeOverride = 'Record' + } else if ( + (addProps as OpenAPIV3.SchemaObject)?.type === 'boolean' + ) { + returnTypeOverride = 'Record' + } else { + returnTypeOverride = 'Record' } } else { // Fallback: accept unknown for unhandled response shapes @@ -582,9 +625,11 @@ export default async function apiGen(lookup: Record) { const returnTyping = `type ${pascalName}Return = ${ has204 ? 'void' - : importedTypes.length - ? importedTypes.join(' | ') - : 'unknown' + : returnTypeOverride + ? returnTypeOverride + : importedTypes.length + ? importedTypes.join(' | ') + : 'unknown' }` const paramsInterfaceName = `${pascalName}Input` const returnTypeName = `${pascalName}Return` diff --git a/package.json b/package.json index c5ba5813..88afcc9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kittycad/lib", - "version": "3.0.3", + "version": "3.0.4", "description": "Javascript library for KittyCAD API", "type": "module", "keywords": [ diff --git a/src/api/meta/get_pricing_subscriptions.ts b/src/api/meta/get_pricing_subscriptions.ts index 310cbfd0..8c8eb984 100644 --- a/src/api/meta/get_pricing_subscriptions.ts +++ b/src/api/meta/get_pricing_subscriptions.ts @@ -7,7 +7,7 @@ interface GetPricingSubscriptionsInput { client?: Client } -type GetPricingSubscriptionsReturn = ZooProductSubscription[] +type GetPricingSubscriptionsReturn = Record /** * Get the pricing for our subscriptions. @@ -20,7 +20,7 @@ type GetPricingSubscriptionsReturn = ZooProductSubscription[] * @property {Client} [client] Optional client with auth token. * @returns {Promise} successful operation * - * Possible return types: ZooProductSubscription[] + * Possible return types: ZooProductSubscription */ export default async function get_pricing_subscriptions( { client }: GetPricingSubscriptionsInput = {} as GetPricingSubscriptionsInput