diff --git a/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/index.js b/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/index.js new file mode 100644 index 000000000..3adec306a --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/index.js @@ -0,0 +1,7 @@ +export function defineConfig(config) { + return config; +} + +export const defaultPlugins = [ + "@hey-api/typescript", "@hey-api/sdk" +] diff --git a/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/package.json b/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/package.json new file mode 100644 index 000000000..a04dea762 --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/package.json @@ -0,0 +1,5 @@ +{ + "name": "@hey-api/openapi-ts", + "main": "index.js", + "types": "types.ts" +} diff --git a/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/types.ts b/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/types.ts new file mode 100644 index 000000000..9eb00e5c7 --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/node_modules/@hey-api/openapi-ts/types.ts @@ -0,0 +1,4 @@ +declare const defineConfig: (config: Record) => Record; +declare const defaultPlugins: string[]; + +export { defineConfig, defaultPlugins }; diff --git a/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.cjs b/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.cjs new file mode 100644 index 000000000..335861d0b --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.cjs @@ -0,0 +1,8 @@ +/** @type {import('@hey-api/openapi-ts').UserConfig} */ +module.exports = { + input: 'https://get.heyapi.dev/hey-api/backend', + output: { + path: 'src/client2', + }, + plugins: ['@hey-api/client-fetch'], +}; diff --git a/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.mjs b/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.mjs new file mode 100644 index 000000000..96232cd32 --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.mjs @@ -0,0 +1,6 @@ +/** @type {import('@hey-api/openapi-ts').UserConfig} */ +export default { + input: 'https://get.heyapi.dev/hey-api/backend', + output: 'src/client', + plugins: ['@hey-api/client-fetch'], +}; diff --git a/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.ts b/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.ts new file mode 100644 index 000000000..fa45b34d9 --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/openapi-ts.config.ts @@ -0,0 +1,14 @@ +import { defineConfig, defaultPlugins } from '@hey-api/openapi-ts'; + +export default defineConfig({ + input: 'https://get.heyapi.dev/hey-api/backend', + output: 'src/client', + plugins: [ + ...defaultPlugins, + '@hey-api/client-fetch', + { + name: 'custom-plugin', + _dependencies: ['@hey-api/typescript'], + }, + ], +}); diff --git a/packages/knip/fixtures/plugins/hey-api/package.json b/packages/knip/fixtures/plugins/hey-api/package.json new file mode 100644 index 000000000..a7ccc1aba --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/package.json @@ -0,0 +1,8 @@ +{ + "name": "@plugins/hey-api", + "dependencies": { + "@hey-api/openapi-ts": "*", + "@hey-api/client-fetch": "*", + "@hey-api/typescript": "*" + } +} diff --git a/packages/knip/fixtures/plugins/hey-api/src/client/sdk.gen.ts b/packages/knip/fixtures/plugins/hey-api/src/client/sdk.gen.ts new file mode 100644 index 000000000..ddafa8112 --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/src/client/sdk.gen.ts @@ -0,0 +1 @@ +export const getData = () => 0; diff --git a/packages/knip/fixtures/plugins/hey-api/src/client2/sdk.gen.ts b/packages/knip/fixtures/plugins/hey-api/src/client2/sdk.gen.ts new file mode 100644 index 000000000..ddafa8112 --- /dev/null +++ b/packages/knip/fixtures/plugins/hey-api/src/client2/sdk.gen.ts @@ -0,0 +1 @@ +export const getData = () => 0; diff --git a/packages/knip/schema.json b/packages/knip/schema.json index bffa709e1..5fbac9d98 100644 --- a/packages/knip/schema.json +++ b/packages/knip/schema.json @@ -419,6 +419,10 @@ "title": "hardhat plugin configuration (https://knip.dev/reference/plugins/hardhat)", "$ref": "#/definitions/plugin" }, + "hey-api": { + "title": "hey-api plugin configuration (https://knip.dev/reference/plugins/hey-api)", + "$ref": "#/definitions/plugin" + }, "husky": { "title": "husky plugin configuration (https://knip.dev/reference/plugins/husky)", "$ref": "#/definitions/plugin" diff --git a/packages/knip/src/plugins/hey-api/index.ts b/packages/knip/src/plugins/hey-api/index.ts new file mode 100644 index 000000000..da22c483f --- /dev/null +++ b/packages/knip/src/plugins/hey-api/index.ts @@ -0,0 +1,36 @@ +import type { IsPluginEnabled, Plugin, ResolveConfig } from '../../types/config.js'; +import { type Input, toDependency, toEntry, toIgnore } from '../../util/input.js'; +import { hasDependency } from '../../util/plugin.js'; +import type { PluginConfig } from './types.js'; + +// https://heyapi.dev/openapi-ts/get-started + +const title = 'Hey API'; + +const enablers = ['@hey-api/openapi-ts']; + +const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); + +const config: string[] = ['openapi-ts.config.@(js|ts|cjs|mjs)']; + +const resolveConfig: ResolveConfig = async ({ plugins = [], output }): Promise => { + const defaultPlugins = ['@hey-api/typescript', '@hey-api/sdk']; + const pluginNames = plugins.reduce((acc, p) => { + const add = typeof p === 'string' ? [p] : (p._dependencies ?? []); + return acc.concat(add); + }, []); + const pluginInputs = pluginNames.map(name => + defaultPlugins.includes(name) ? toIgnore(name, 'unlisted') : toDependency(name) + ); + const outPath = typeof output === 'string' ? output : output.path; + const entries = outPath ? [toEntry(`./${outPath}/**`)] : []; + return [...pluginInputs, ...entries]; +}; + +export default { + title, + enablers, + isEnabled, + config, + resolveConfig, +} satisfies Plugin; diff --git a/packages/knip/src/plugins/hey-api/types.ts b/packages/knip/src/plugins/hey-api/types.ts new file mode 100644 index 000000000..94a5db039 --- /dev/null +++ b/packages/knip/src/plugins/hey-api/types.ts @@ -0,0 +1,4 @@ +export type PluginConfig = { + output: string | { path: string }; + plugins?: (string | { name: string; _dependencies?: string[] })[]; +}; diff --git a/packages/knip/src/plugins/index.ts b/packages/knip/src/plugins/index.ts index b2379326e..795d6ebd2 100644 --- a/packages/knip/src/plugins/index.ts +++ b/packages/knip/src/plugins/index.ts @@ -30,6 +30,7 @@ import { default as githubActions } from './github-actions/index.js'; import { default as glob } from './glob/index.js'; import { default as graphqlCodegen } from './graphql-codegen/index.js'; import { default as hardhat } from './hardhat/index.js'; +import { default as heyApi } from './hey-api/index.js'; import { default as husky } from './husky/index.js'; import { default as i18nextParser } from './i18next-parser/index.js'; import { default as jest } from './jest/index.js'; @@ -141,6 +142,7 @@ export const Plugins = { glob, 'graphql-codegen': graphqlCodegen, hardhat, + 'hey-api': heyApi, husky, 'i18next-parser': i18nextParser, jest, diff --git a/packages/knip/src/schema/plugins.ts b/packages/knip/src/schema/plugins.ts index e79a5e7c3..a61380e27 100644 --- a/packages/knip/src/schema/plugins.ts +++ b/packages/knip/src/schema/plugins.ts @@ -44,6 +44,7 @@ export const pluginsSchema = z.object({ glob: pluginSchema, 'graphql-codegen': pluginSchema, hardhat: pluginSchema, + 'hey-api': pluginSchema, husky: pluginSchema, 'i18next-parser': pluginSchema, jest: pluginSchema, diff --git a/packages/knip/src/types/PluginNames.ts b/packages/knip/src/types/PluginNames.ts index ee45e4b84..22ae6a270 100644 --- a/packages/knip/src/types/PluginNames.ts +++ b/packages/knip/src/types/PluginNames.ts @@ -31,6 +31,7 @@ export type PluginName = | 'glob' | 'graphql-codegen' | 'hardhat' + | 'hey-api' | 'husky' | 'i18next-parser' | 'jest' @@ -142,6 +143,7 @@ export const pluginNames = [ 'glob', 'graphql-codegen', 'hardhat', + 'hey-api', 'husky', 'i18next-parser', 'jest', diff --git a/packages/knip/test/plugins/hey-api.test.ts b/packages/knip/test/plugins/hey-api.test.ts new file mode 100644 index 000000000..882e0fcaa --- /dev/null +++ b/packages/knip/test/plugins/hey-api.test.ts @@ -0,0 +1,21 @@ +import { test } from 'bun:test'; +import assert from 'node:assert/strict'; +import { main } from '../../src/index.js'; +import { resolve } from '../../src/util/path.js'; +import baseArguments from '../helpers/baseArguments.js'; +import baseCounters from '../helpers/baseCounters.js'; + +const cwd = resolve('fixtures/plugins/hey-api'); + +test('Find dependencies with the hey-api plugin', async () => { + const { counters } = await main({ + ...baseArguments, + cwd, + }); + + assert.deepEqual(counters, { + ...baseCounters, + processed: 5, + total: 5, + }); +});