@kubb/plugin-oas
Version:
OpenAPI Specification (OAS) plugin for Kubb, providing core functionality for parsing and processing OpenAPI/Swagger schemas for code generation.
128 lines (110 loc) • 4.05 kB
text/typescript
import { camelCase, isValidVarName } from '@internals/utils'
import type { FunctionParamsAST } from '@kubb/core'
import type { OasTypes } from '@kubb/oas'
import type { Params } from '@kubb/react-fabric/types'
import type { OperationSchema } from '../types.ts'
/**
*
* @deprecated
* TODO move to operationManager hook
*/
export function getASTParams(
operationSchema: OperationSchema | undefined,
{
typed = false,
casing,
override,
}: {
typed?: boolean
casing?: 'camelcase'
override?: (data: FunctionParamsAST) => FunctionParamsAST
} = {},
): FunctionParamsAST[] {
if (!operationSchema || !operationSchema.schema.properties || !operationSchema.name) {
return []
}
const requiredFields = Array.isArray(operationSchema.schema.required) ? operationSchema.schema.required : []
return Object.entries(operationSchema.schema.properties).map(([name]: [string, OasTypes.SchemaObject]) => {
// Use camelCase name for indexed access if casing is enabled
const accessName = casing === 'camelcase' ? camelCase(name) : name
const data: FunctionParamsAST = {
name,
enabled: !!name,
required: requiredFields.includes(name),
type: typed ? `${operationSchema.name}["${accessName}"]` : undefined,
}
return override ? override(data) : data
})
}
export function getPathParams(
operationSchema: OperationSchema | undefined,
options: {
typed?: boolean
casing?: 'camelcase'
override?: (data: FunctionParamsAST) => FunctionParamsAST
} = {},
) {
return getASTParams(operationSchema, options).reduce((acc, curr) => {
if (curr.name && curr.enabled) {
let name = curr.name
// Only transform to camelCase if explicitly requested
if (options.casing === 'camelcase') {
name = camelCase(name)
} else if (!isValidVarName(name)) {
// If not valid variable name and casing not set, still need to make it valid
name = camelCase(name)
}
acc[name] = {
default: curr.default,
type: curr.type,
optional: !curr.required,
}
}
return acc
}, {} as Params)
}
/**
* Get a mapping of camelCase parameter names to their original names
* Used for mapping function parameters to backend parameter names
*/
export function getParamsMapping(
operationSchema: OperationSchema | undefined,
options: {
casing?: 'camelcase'
} = {},
): Record<string, string> | undefined {
if (!operationSchema || !operationSchema.schema.properties) {
return undefined
}
const allEntries: Array<[string, string]> = []
let hasTransformation = false
Object.entries(operationSchema.schema.properties).forEach(([originalName]) => {
let transformedName = originalName
// Only transform to camelCase if explicitly requested
if (options.casing === 'camelcase') {
transformedName = camelCase(originalName)
} else if (!isValidVarName(originalName)) {
// If not valid variable name and casing not set, still need to make it valid
transformedName = camelCase(originalName)
}
allEntries.push([originalName, transformedName])
if (transformedName !== originalName) {
hasTransformation = true
}
})
// When using explicit casing and there are transformations, include ALL params so that
// mappedParams contains every parameter (not just the ones whose names changed).
// This prevents params with already-camelCase names (e.g. 'page', 'search') from being
// silently dropped when other params in the same schema do need transformation.
if (options.casing === 'camelcase' && hasTransformation) {
return Object.fromEntries(allEntries)
}
// When casing is not specified or no transformations are needed, only return changed entries
const mapping: Record<string, string> = {}
allEntries.forEach(([originalName, transformedName]) => {
if (transformedName !== originalName) {
mapping[originalName] = transformedName
}
})
return Object.keys(mapping).length > 0 ? mapping : undefined
}