Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/consolidate-url-template-into-kubb-kit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@kubb/plugin-cypress": patch
"@kubb/plugin-msw": patch
---

Consume the `Url` path-template helper from `kubb/kit` instead of a locally duplicated copy in `@internals/utils`, now that kubb core exposes `Url.toSafeTemplate` and `Url.toGroupedTemplateString` alongside its existing `toPath`/`toTemplateString`/`toObject`. Requires `kubb`/`@kubb/kit` 5.0.0-beta.98 or later.
4 changes: 2 additions & 2 deletions internals/client/src/builders/sdkMethod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { buildOperationComments } from '@internals/shared'
import { buildJSDoc, Url } from '@internals/utils'
import { buildJSDoc } from '@internals/utils'
import { ast } from 'kubb/kit'
import type { ResolverTs } from '@kubb/plugin-ts'
import type { ResolverZod } from '@kubb/plugin-zod'
Expand Down Expand Up @@ -35,7 +35,7 @@ function buildCallConfig({

return `{ ${[
`method: '${node.method.toUpperCase()}'`,
`url: '${Url.toSafeTemplate(node.path)}'`,
`url: '${node.path}'`,
securityLiteral ? `security: ${securityLiteral}` : null,
validatorLiteral,
'...config',
Expand Down
3 changes: 1 addition & 2 deletions internals/client/src/components/Operation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { buildOperationComments, getContentTypeInfo, getResponseContentTypeInfo, getResponseType, isEventStream } from '@internals/shared'
import { Url } from '@internals/utils'
import { ast } from 'kubb/kit'
import type { ResolverTs } from '@kubb/plugin-ts'
import type { ResolverZod } from '@kubb/plugin-zod'
Expand Down Expand Up @@ -82,7 +81,7 @@ export function Operation({ name, node, tsResolver, zodResolver, validator, secu

const callConfig = `{ ${[
`method: '${node.method.toUpperCase()}'`,
`url: '${Url.toSafeTemplate(node.path)}'`,
`url: '${node.path}'`,
securityLiteral ? `security: ${securityLiteral}` : null,
stylesLiteral ? `styles: ${stylesLiteral}` : null,
validatorLiteral,
Expand Down
6 changes: 3 additions & 3 deletions internals/shared/src/operation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ describe('response status helpers', () => {
})

describe('getOperationParameters', () => {
test('groups parameters by location, sanitizing only path names into valid identifiers', () => {
test('groups parameters by location, keeping every name exactly as in the OpenAPI spec', () => {
const node = ast.factory.createOperation({
operationId: 'showPet',
method: 'GET',
Expand All @@ -263,7 +263,7 @@ describe('getOperationParameters', () => {

const grouped = getOperationParameters(node)

expect(grouped.path.map((param) => param.name)).toStrictEqual(['petId'])
expect(grouped.path.map((param) => param.name)).toStrictEqual(['pet-id'])
expect(grouped.query.map((param) => param.name)).toStrictEqual(['page-size'])
expect(grouped.header.map((param) => param.name)).toStrictEqual(['x-api-key'])
expect(grouped.cookie.map((param) => param.name)).toStrictEqual(['session-id'])
Expand Down Expand Up @@ -291,7 +291,7 @@ describe('resolveOperationTypeNames', () => {
})

expect(resolveOperationTypeNames(node, resolver, { exclude: ['Status200'] })).toStrictEqual([
'petIdPathParams',
'pet-idPathParams',
'page-sizeQueryParams',
'x-api-keyHeaderParams',
'showPetData',
Expand Down
15 changes: 3 additions & 12 deletions internals/shared/src/operation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { camelCase, isValidVarName, Url } from '@internals/utils'
import { ast, type ResolverFileParams } from 'kubb/kit'
import { type ast, type ResolverFileParams, Url } from 'kubb/kit'
import { dedupeParams } from './params.ts'

/**
Expand Down Expand Up @@ -147,11 +146,7 @@ function getOperationLink(node: ast.OperationNode, link: OperationCommentLink):
return link(node) ?? null
}

if (link === 'urlPath') {
return node.path ? `{@link ${Url.toPath(node.path)}}` : null
}

return node.path ? `{@link ${node.path.replaceAll('{', ':').replaceAll('}', '')}}` : null
return node.path ? `{@link ${Url.toPath(node.path)}}` : null
}

/**
Expand Down Expand Up @@ -405,12 +400,8 @@ export function buildOperationComments(node: ast.OperationNode, options: BuildOp
}

export function getOperationParameters(node: ast.OperationNode): OperationParameterGroups {
const path = node.parameters
.filter((param) => param.in === 'path')
.map((param) => (isValidVarName(param.name) ? param : { ...param, name: camelCase(param.name) }))

return {
path: dedupeParams(path),
path: dedupeParams(node.parameters.filter((param) => param.in === 'path')),
query: dedupeParams(node.parameters.filter((param) => param.in === 'query')),
header: dedupeParams(node.parameters.filter((param) => param.in === 'header')),
cookie: dedupeParams(node.parameters.filter((param) => param.in === 'cookie')),
Expand Down
3 changes: 1 addition & 2 deletions internals/tanstack-query/src/components/MutationKey.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Url } from '@internals/utils'
import type { ast } from 'kubb/kit'
import { type ast, Url } from 'kubb/kit'
import { createFunctionParameters, functionPrinter } from '@kubb/plugin-ts'
import { File, Function } from 'kubb/jsx'
import type { KubbReactNode } from 'kubb/jsx'
Expand Down
3 changes: 1 addition & 2 deletions internals/tanstack-query/src/components/QueryKey.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getOperationParameters } from '@internals/shared'
import { Url } from '@internals/utils'
import type { ast } from 'kubb/kit'
import { type ast, Url } from 'kubb/kit'
import type { PluginTs } from '@kubb/plugin-ts'
import { functionPrinter } from '@kubb/plugin-ts'
import { File, Function, Type } from 'kubb/jsx'
Expand Down
1 change: 0 additions & 1 deletion internals/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ export { getRelativePath, toFilePath } from './fs.ts'
export { aliasConflictingImports, filterUsedImports, rewriteAliasedImports, type ImportEntry, type ImportName } from './imports.ts'
export { ensureValidVarName, isIdentifier, isValidVarName } from './reserved.ts'
export { getNestedAccessor, jsStringEscape, singleQuote, stringify, stringifyObject, toRegExpString, trimQuotes } from './strings.ts'
export { Url } from './url.ts'
63 changes: 0 additions & 63 deletions internals/utils/src/url.test.ts

This file was deleted.

84 changes: 0 additions & 84 deletions internals/utils/src/url.ts

This file was deleted.

6 changes: 2 additions & 4 deletions packages/plugin-cypress/src/components/Request.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { buildRequestParamsSignature } from '@internals/shared'
import { Url } from '@internals/utils'
import { ast } from 'kubb/kit'
import { ast, Url } from 'kubb/kit'
import type { ResolverTs } from '@kubb/plugin-ts'
import { File, Function } from 'kubb/jsx'
import type { KubbReactNode } from 'kubb/jsx'
Expand Down Expand Up @@ -30,8 +29,7 @@ export function Request({ baseURL = '', name, resolver, node }: Props): KubbReac
const responseType = resolver.response.response(node)
const returnType = `Cypress.Chainable<${responseType}>`

// Reference the path object straight in the URL with the sanitized placeholders shared with the
// generated `path` type.
// Bracket-access the path object with the raw OpenAPI param names, matching the generated `path` type's keys.
const urlTemplate = Url.toGroupedTemplateString(node.path, { prefix: baseURL })

const requestOptions: Array<string> = [`method: '${node.method}'`, `url: ${urlTemplate}`]
Expand Down
7 changes: 3 additions & 4 deletions packages/plugin-msw/src/components/Mock.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { getPrimarySuccessResponse } from '@internals/shared'
import { Url } from '@internals/utils'
import type { ast } from 'kubb/kit'
import { ast, Url } from 'kubb/kit'
import { createFunctionParameter, createFunctionParameters, functionPrinter } from '@kubb/plugin-ts'
import { File, Function } from 'kubb/jsx'
import type { KubbReactNode } from 'kubb/jsx'
import { getContentType, getMswMethod, getMswUrl, hasResponseSchema } from '../utils.ts'
import { getContentType, getMswMethod, hasResponseSchema } from '../utils.ts'

type Props = {
name: string
Expand All @@ -22,7 +21,7 @@ export function Mock({ baseURL = '', name, fakerName, typeName, requestTypeName,
const successResponse = getPrimarySuccessResponse(node)
const statusCode = successResponse ? Number(successResponse.statusCode) : 200
const contentType = getContentType(successResponse)
const url = Url.toPath(getMswUrl(node))
const url = ast.isHttpOperationNode(node) ? Url.toPath(node.path) : ''

const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean)
const responseHasSchema = hasResponseSchema(successResponse)
Expand Down
7 changes: 0 additions & 7 deletions packages/plugin-msw/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ export function getMswMethod(node: ast.OperationNode): string {
return ast.isHttpOperationNode(node) ? node.method.toLowerCase() : ''
}

/**
* Converts an OpenAPI-style path to an Express/MSW-style path by replacing `{param}` with `:param`.
*/
export function getMswUrl(node: ast.OperationNode): string {
return ast.isHttpOperationNode(node) ? node.path.replaceAll('{', ':').replaceAll('}', '') : ''
}

/**
* Resolves faker metadata for an MSW operation, including response name and file path.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ts/src/printers/operationParams.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ describe('createOperationParams', () => {
})

const pathParam = params.params[0]
expect(pathParam?.name).toBe('storeName')
expect(pathParam?.name).toBe('store-name')
})
})

Expand Down
Loading
Loading