diff --git a/packages/apicraft/apicraft.config.ts b/packages/apicraft/apicraft.config.ts index b3993b7..26aafd8 100644 --- a/packages/apicraft/apicraft.config.ts +++ b/packages/apicraft/apicraft.config.ts @@ -11,7 +11,8 @@ const apicraftConfig = apicraft([ instance: 'axios', baseUrl: '/api', nameBy: 'path', - groupBy: 'class' + groupBy: 'paths', + plugins: ['reatom', 'tanstack'] }, { input: 'example-apiV1.yaml', diff --git a/packages/apicraft/bin/generate.ts b/packages/apicraft/bin/generate.ts index cb3a022..bac72b1 100644 --- a/packages/apicraft/bin/generate.ts +++ b/packages/apicraft/bin/generate.ts @@ -13,6 +13,7 @@ import type { ApicraftOption, GenerateApicraftOption, InstanceName } from './sch import { defineAxiosPlugin } from './plugins/axios'; import { defineFetchesPlugin } from './plugins/fetches'; import { defineOfetchPlugin } from './plugins/ofetch'; +import { defineReatomPlugin } from './plugins/reatom'; import { defineTanstackPlugin } from './plugins/tanstack'; import { apicraftConfigSchema, apicraftOptionSchema } from './schemas'; @@ -123,6 +124,22 @@ export const generate = { ); } + const reatomPlugin = plugins.find( + (plugin) => plugin === 'reatom' || plugin.name === 'reatom' + ); + if (reatomPlugin) { + dependencies.add('@reatom/core'); + plugins.push( + defineReatomPlugin({ + generateOutput, + exportFromIndex: true, + nameBy: option.nameBy, + groupBy: option.groupBy, + baseUrl: option.baseUrl + }) + ); + } + await installDependencies(Array.from(dependencies)); await createClient({ diff --git a/packages/apicraft/bin/helpers/installDependencies.ts b/packages/apicraft/bin/helpers/installDependencies.ts index f65a32d..71c8a02 100644 --- a/packages/apicraft/bin/helpers/installDependencies.ts +++ b/packages/apicraft/bin/helpers/installDependencies.ts @@ -1,11 +1,17 @@ import * as prompts from '@clack/prompts'; import { isPackageExists } from 'local-pkg'; -export type Dependency = '@siberiacancode/fetches' | '@tanstack/react-query' | 'axios' | 'ofetch'; +export type Dependency = + | '@reatom/core' + | '@siberiacancode/fetches' + | '@tanstack/react-query' + | 'axios' + | 'ofetch'; export const dependencyVersionsMap: Record = { axios: '^1.13.6', ofetch: '^1.5.1', + '@reatom/core': '^1000.15.1', '@siberiacancode/fetches': '^1.14.1', '@tanstack/react-query': '^5.90.21' }; diff --git a/packages/apicraft/bin/plugins/helpers/removeRequestsBaseUrl.ts b/packages/apicraft/bin/plugins/helpers/removeRequestsBaseUrl.ts index 4c53696..d56ec46 100644 --- a/packages/apicraft/bin/plugins/helpers/removeRequestsBaseUrl.ts +++ b/packages/apicraft/bin/plugins/helpers/removeRequestsBaseUrl.ts @@ -20,7 +20,7 @@ export const removeRequestsBaseUrl = (plugin: DefinePlugin['Instance'], baseUrl: ...([ ...events, (event: WalkEvent) => { - // eslint-disable-next-line ts/no-unnecessary-condition + if (event.type === 'operation') { const newPath = event.operation.path.replace(new RegExp(`^${baseUrl}`), ''); event.operation.path = newPath.startsWith('/') diff --git a/packages/apicraft/bin/plugins/reatom/class/plugin.ts b/packages/apicraft/bin/plugins/reatom/class/plugin.ts new file mode 100644 index 0000000..12c2a7b --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/class/plugin.ts @@ -0,0 +1,68 @@ +import type ts from 'typescript'; + +import { + capitalize, + generateRequestName, + getApicraftTypeImport, + getImportInstance, + getImportRequest +} from '@/bin/plugins/helpers'; + +import type { ReatomPlugin } from '../types'; + +import { getReatomAsync, getReatomAsyncData, getReatomImport } from '../helpers'; + +export const classHandler: ReatomPlugin['Handler'] = ({ plugin }) => { + const reatomFile = plugin.createFile({ + id: 'reatom', + path: `${plugin.output}/reatom` + }); + + const requestParamsTypeNames: string[] = []; + const functions: ts.VariableStatement[] = []; + + plugin.forEach('operation', (event) => { + const request = event.operation; + const requestName = generateRequestName(request, plugin.config.nameBy); + const requestParamsTypeName = `${capitalize(requestName)}RequestParams`; + requestParamsTypeNames.push(requestParamsTypeName); + + functions.push( + getReatomAsyncData({ + plugin, + request, + requestName, + requestParamsTypeName + }), + getReatomAsync({ + plugin, + requestName, + requestParamsTypeName + }) + ); + }); + + const imports: ts.ImportDeclaration[] = [ + // import type { ReatomAsyncDataSettings, ReatomAsyncSettings } from '@siberiacancode/apicraft'; + getApicraftTypeImport(['ReatomAsyncDataSettings', 'ReatomAsyncSettings']), + // import { action, computed, wrap, withAsync, withAsyncData } from '@reatom/core'; + getReatomImport(['action', 'computed', 'wrap', 'withAsync', 'withAsyncData']), + // import { RequestNameRequestParams } from './instance.gen'; + getImportRequest({ + folderPath: plugin.output, + requestFilePath: `${plugin.output}/instance`, + requestName: requestParamsTypeNames, + generateOutput: plugin.config.generateOutput + }), + // import { instance } from './instance.gen'; + getImportInstance({ + output: plugin.output, + folderPath: plugin.output, + generateOutput: plugin.config.generateOutput + }) + ]; + + reatomFile.add(...imports); + // export const requestNameAsyncData / requestNameAsync + reatomFile.add(...functions); +}; diff --git a/packages/apicraft/bin/plugins/reatom/composed/helpers/generateReatomFile.ts b/packages/apicraft/bin/plugins/reatom/composed/helpers/generateReatomFile.ts new file mode 100644 index 0000000..8cbd3d1 --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/composed/helpers/generateReatomFile.ts @@ -0,0 +1,77 @@ +import type { IR } from '@hey-api/openapi-ts'; + +import * as nodePath from 'node:path'; + +import { capitalize, getApicraftTypeImport, getImportRequest } from '@/bin/plugins/helpers'; + +import type { ReatomPlugin } from '../../types'; + +import { getReatomAsync, getReatomAsyncData, getReatomImport } from '../../helpers'; + +interface GenerateReatomFileParams { + plugin: ReatomPlugin['Instance']; + request: IR.OperationObject; + requestFilePath: string; + requestName: string; +} + +export const generateReatomFile = ({ + plugin, + request, + requestName, + requestFilePath +}: GenerateReatomFileParams) => { + const reatomFilePath = `${nodePath.dirname(requestFilePath).replace('requests', 'reatom')}/${requestName}`; + const reatomFolderPath = nodePath.dirname(`${plugin.config.generateOutput}/${reatomFilePath}`); + const requestParamsTypeName = `${capitalize(requestName)}RequestParams`; + + const reatomFile = plugin.createFile({ + id: requestName, + path: reatomFilePath + }); + + // import type { ReatomAsyncDataSettings, ReatomAsyncSettings } from '@siberiacancode/apicraft'; + reatomFile.add(getApicraftTypeImport(['ReatomAsyncDataSettings', 'ReatomAsyncSettings'])); + + // import { action, computed, wrap, withAsync, withAsyncData } from '@reatom/core'; + reatomFile.add(getReatomImport(['action', 'computed', 'wrap', 'withAsync', 'withAsyncData'])); + + // import { requestName } from './requestName.gen'; + reatomFile.add( + getImportRequest({ + folderPath: reatomFolderPath, + requestFilePath, + requestName, + generateOutput: plugin.config.generateOutput + }) + ); + + // import { RequestNameRequestParams } from './requestName.gen'; + reatomFile.add( + getImportRequest({ + folderPath: reatomFolderPath, + requestFilePath, + requestName: requestParamsTypeName, + generateOutput: plugin.config.generateOutput + }) + ); + + // export const requestNameAsyncData = (...) => computed(...).extend(withAsyncData(...)); + reatomFile.add( + getReatomAsyncData({ + plugin, + request, + requestName, + requestParamsTypeName + }) + ); + + // export const requestNameAsync = (...) => action(...).extend(withAsync(...)); + reatomFile.add( + getReatomAsync({ + plugin, + requestName, + requestParamsTypeName + }) + ); +}; diff --git a/packages/apicraft/bin/plugins/reatom/composed/helpers/index.ts b/packages/apicraft/bin/plugins/reatom/composed/helpers/index.ts new file mode 100644 index 0000000..29003fb --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/composed/helpers/index.ts @@ -0,0 +1 @@ +export { generateReatomFile } from './generateReatomFile'; diff --git a/packages/apicraft/bin/plugins/reatom/composed/plugin.ts b/packages/apicraft/bin/plugins/reatom/composed/plugin.ts new file mode 100644 index 0000000..ebf6067 --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/composed/plugin.ts @@ -0,0 +1,20 @@ +import { generateRequestName, getRequestFilePath } from '@/bin/plugins/helpers'; + +import type { ReatomPlugin } from '../types'; + +import { generateReatomFile } from './helpers'; + +export const composedHandler: ReatomPlugin['Handler'] = ({ plugin }) => + plugin.forEach('operation', (event) => { + const request = event.operation; + const requestName = generateRequestName(request, plugin.config.nameBy); + + const requestFilePath = getRequestFilePath({ + groupBy: plugin.config.groupBy, + output: plugin.output, + requestName, + request + }); + + generateReatomFile({ plugin, request, requestFilePath, requestName }); + }); diff --git a/packages/apicraft/bin/plugins/reatom/config.ts b/packages/apicraft/bin/plugins/reatom/config.ts new file mode 100644 index 0000000..81494e4 --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/config.ts @@ -0,0 +1,18 @@ +import { definePluginConfig } from '@hey-api/openapi-ts'; + +import type { ReatomPlugin } from './types'; + +import { handler } from './plugin'; + +export const defaultConfig: ReatomPlugin['Config'] = { + config: { + generateOutput: '', + exportFromIndex: true + }, + dependencies: ['@hey-api/typescript'], + handler, + name: 'reatom', + output: '.' +}; + +export const defineReatomPlugin = definePluginConfig(defaultConfig); diff --git a/packages/apicraft/bin/plugins/reatom/helpers/getReatomAsync.ts b/packages/apicraft/bin/plugins/reatom/helpers/getReatomAsync.ts new file mode 100644 index 0000000..f1ee98e --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/helpers/getReatomAsync.ts @@ -0,0 +1,149 @@ +import ts from 'typescript'; + +import type { ReatomPlugin } from '../types'; + +interface GetReatomAsyncParams { + plugin: ReatomPlugin['Instance']; + requestName: string; + requestParamsTypeName: string; +} + +export const getReatomAsync = ({ + plugin, + requestName, + requestParamsTypeName +}: GetReatomAsyncParams) => { + const asyncName = `${requestName}Async`; + + const requestCall = + plugin.config.groupBy === 'class' + ? ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('instance'), + ts.factory.createIdentifier(requestName) + ), + undefined, + [ + ts.factory.createObjectLiteralExpression( + [ + ts.factory.createSpreadAssignment( + ts.factory.createPropertyAccessChain( + ts.factory.createIdentifier('settings'), + ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), + ts.factory.createIdentifier('request') + ) + ), + ts.factory.createSpreadAssignment(ts.factory.createIdentifier('payload')) + ], + false + ) + ] + ) + : ts.factory.createCallExpression(ts.factory.createIdentifier(requestName), undefined, [ + ts.factory.createObjectLiteralExpression( + [ + ts.factory.createSpreadAssignment( + ts.factory.createPropertyAccessChain( + ts.factory.createIdentifier('settings'), + ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), + ts.factory.createIdentifier('request') + ) + ), + ts.factory.createSpreadAssignment(ts.factory.createIdentifier('payload')) + ], + false + ) + ]); + + const requestTypeNode = + plugin.config.groupBy === 'class' + ? ts.factory.createTypeQueryNode( + ts.factory.createQualifiedName( + ts.factory.createIdentifier('instance'), + ts.factory.createIdentifier(requestName) + ) + ) + : ts.factory.createTypeQueryNode(ts.factory.createIdentifier(requestName)); + + const actionCall = ts.factory.createCallExpression( + ts.factory.createIdentifier('action'), + undefined, + [ + ts.factory.createArrowFunction( + [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)], + undefined, + [ + ts.factory.createParameterDeclaration( + undefined, + undefined, + ts.factory.createIdentifier('payload'), + undefined, + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier(requestParamsTypeName), + undefined + ) + ) + ], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createAwaitExpression( + ts.factory.createCallExpression(ts.factory.createIdentifier('wrap'), undefined, [ + requestCall + ]) + ) + ), + ts.factory.createStringLiteral(asyncName) + ] + ); + + const extendCall = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(actionCall, ts.factory.createIdentifier('extend')), + undefined, + [ + ts.factory.createCallExpression(ts.factory.createIdentifier('withAsync'), undefined, [ + ts.factory.createBinaryExpression( + ts.factory.createPropertyAccessChain( + ts.factory.createIdentifier('settings'), + ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), + ts.factory.createIdentifier('params') + ), + ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), + ts.factory.createObjectLiteralExpression([], false) + ) + ]) + ] + ); + + return ts.factory.createVariableStatement( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(asyncName), + undefined, + undefined, + ts.factory.createArrowFunction( + undefined, + undefined, + [ + ts.factory.createParameterDeclaration( + undefined, + undefined, + ts.factory.createIdentifier('settings'), + ts.factory.createToken(ts.SyntaxKind.QuestionToken), + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier('ReatomAsyncSettings'), + [requestTypeNode] + ) + ) + ], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + extendCall + ) + ) + ], + ts.NodeFlags.Const + ) + ); +}; diff --git a/packages/apicraft/bin/plugins/reatom/helpers/getReatomAsyncData.ts b/packages/apicraft/bin/plugins/reatom/helpers/getReatomAsyncData.ts new file mode 100644 index 0000000..4451066 --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/helpers/getReatomAsyncData.ts @@ -0,0 +1,332 @@ +import type { IR } from '@hey-api/openapi-ts'; + +import ts from 'typescript'; + +import { getRequestInfo } from '@/bin/plugins/helpers'; + +import type { ReatomPlugin } from '../types'; + +interface GetReatomAsyncDataParams { + plugin: ReatomPlugin['Instance']; + request: IR.OperationObject; + requestName: string; + requestParamsTypeName: string; +} + +export const getReatomAsyncData = ({ + plugin, + request, + requestName, + requestParamsTypeName +}: GetReatomAsyncDataParams) => { + const requestInfo = getRequestInfo(request); + const asyncDataName = `${requestName}AsyncData`; + + const requestTypeNode = + plugin.config.groupBy === 'class' + ? ts.factory.createTypeQueryNode( + ts.factory.createQualifiedName( + ts.factory.createIdentifier('instance'), + ts.factory.createIdentifier(requestName) + ) + ) + : ts.factory.createTypeQueryNode(ts.factory.createIdentifier(requestName)); + + const requestCall = + plugin.config.groupBy === 'class' + ? ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('instance'), + ts.factory.createIdentifier(requestName) + ), + undefined, + [ts.factory.createIdentifier('normalizedRequest')] + ) + : ts.factory.createCallExpression(ts.factory.createIdentifier(requestName), undefined, [ + ts.factory.createIdentifier('normalizedRequest') + ]); + + // const unwrap = (value: unknown): unknown => { ... } + const unwrapHelper = ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + ts.factory.createIdentifier('unwrap'), + undefined, + undefined, + ts.factory.createArrowFunction( + undefined, + undefined, + [ + ts.factory.createParameterDeclaration( + undefined, + undefined, + ts.factory.createIdentifier('value'), + undefined, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword) + ) + ], + ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword), + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [ + ts.factory.createIfStatement( + ts.factory.createBinaryExpression( + ts.factory.createTypeOfExpression(ts.factory.createIdentifier('value')), + ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), + ts.factory.createStringLiteral('function') + ), + ts.factory.createBlock( + [ + ts.factory.createReturnStatement( + ts.factory.createCallExpression( + ts.factory.createIdentifier('value'), + undefined, + [] + ) + ) + ], + true + ) + ), + ts.factory.createIfStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('Array'), + ts.factory.createIdentifier('isArray') + ), + undefined, + [ts.factory.createIdentifier('value')] + ), + ts.factory.createBlock( + [ + ts.factory.createReturnStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('value'), + ts.factory.createIdentifier('map') + ), + undefined, + [ + ts.factory.createArrowFunction( + undefined, + undefined, + [ts.factory.createParameterDeclaration(undefined, undefined, 'item')], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createCallExpression( + ts.factory.createIdentifier('unwrap'), + undefined, + [ts.factory.createIdentifier('item')] + ) + ) + ] + ) + ) + ], + true + ) + ), + ts.factory.createIfStatement( + ts.factory.createBinaryExpression( + ts.factory.createIdentifier('value'), + ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), + ts.factory.createBinaryExpression( + ts.factory.createTypeOfExpression(ts.factory.createIdentifier('value')), + ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), + ts.factory.createStringLiteral('object') + ) + ), + ts.factory.createBlock( + [ + ts.factory.createReturnStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('Object'), + ts.factory.createIdentifier('fromEntries') + ), + undefined, + [ + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('Object'), + ts.factory.createIdentifier('entries') + ), + undefined, + [ts.factory.createIdentifier('value')] + ), + ts.factory.createIdentifier('map') + ), + undefined, + [ + ts.factory.createArrowFunction( + undefined, + undefined, + [ + ts.factory.createParameterDeclaration( + undefined, + undefined, + ts.factory.createArrayBindingPattern([ + ts.factory.createBindingElement( + undefined, + undefined, + 'key' + ), + ts.factory.createBindingElement( + undefined, + undefined, + 'entry' + ) + ]) + ) + ], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createArrayLiteralExpression( + [ + ts.factory.createIdentifier('key'), + ts.factory.createCallExpression( + ts.factory.createIdentifier('unwrap'), + undefined, + [ts.factory.createIdentifier('entry')] + ) + ], + false + ) + ) + ] + ) + ] + ) + ) + ], + true + ) + ), + ts.factory.createReturnStatement(ts.factory.createIdentifier('value')) + ], + true + ) + ) + ) + ], + ts.NodeFlags.Const + ) + ); + + const requestAccess = requestInfo.hasRequiredParam + ? ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('settings'), + ts.factory.createIdentifier('request') + ) + : ts.factory.createPropertyAccessChain( + ts.factory.createIdentifier('settings'), + ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), + ts.factory.createIdentifier('request') + ); + + // const normalizedRequest = unwrap(settings.request ?? {}) as RequestParams; + const normalizedRequestVariable = ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + ts.factory.createIdentifier('normalizedRequest'), + undefined, + ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(requestParamsTypeName)), + ts.factory.createAsExpression( + ts.factory.createCallExpression(ts.factory.createIdentifier('unwrap'), undefined, [ + ts.factory.createBinaryExpression( + requestAccess, + ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), + ts.factory.createObjectLiteralExpression([], false) + ) + ]), + ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(requestParamsTypeName)) + ) + ) + ], + ts.NodeFlags.Const + ) + ); + + const computedBody: ts.Statement[] = [ + unwrapHelper, + normalizedRequestVariable, + // return wrap(requestName(normalizedRequest)); + ts.factory.createReturnStatement( + ts.factory.createCallExpression(ts.factory.createIdentifier('wrap'), undefined, [requestCall]) + ) + ]; + + const computedCall = ts.factory.createCallExpression( + ts.factory.createIdentifier('computed'), + undefined, + [ + ts.factory.createArrowFunction( + [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)], + undefined, + [], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock(computedBody, true) + ) + ] + ); + + const extendCall = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(computedCall, ts.factory.createIdentifier('extend')), + undefined, + [ + ts.factory.createCallExpression(ts.factory.createIdentifier('withAsyncData'), undefined, [ + ts.factory.createBinaryExpression( + ts.factory.createPropertyAccessChain( + ts.factory.createIdentifier('settings'), + ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), + ts.factory.createIdentifier('params') + ), + ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), + ts.factory.createObjectLiteralExpression([], false) + ) + ]) + ] + ); + + return ts.factory.createVariableStatement( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(asyncDataName), + undefined, + undefined, + ts.factory.createArrowFunction( + undefined, + undefined, + [ + ts.factory.createParameterDeclaration( + undefined, + undefined, + ts.factory.createIdentifier('settings'), + !requestInfo.hasRequiredParam + ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) + : undefined, + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier('ReatomAsyncDataSettings'), + [requestTypeNode] + ) + ) + ], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + extendCall + ) + ) + ], + ts.NodeFlags.Const + ) + ); +}; diff --git a/packages/apicraft/bin/plugins/reatom/helpers/getReatomImport.ts b/packages/apicraft/bin/plugins/reatom/helpers/getReatomImport.ts new file mode 100644 index 0000000..42a91a4 --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/helpers/getReatomImport.ts @@ -0,0 +1,17 @@ +import ts from 'typescript'; + +// import { name } from '@reatom/core'; +export const getReatomImport = (name: string | string[]) => + ts.factory.createImportDeclaration( + undefined, + ts.factory.createImportClause( + false, + undefined, + ts.factory.createNamedImports( + (Array.isArray(name) ? name : [name]).map((name) => + ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(name)) + ) + ) + ), + ts.factory.createStringLiteral('@reatom/core') + ); diff --git a/packages/apicraft/bin/plugins/reatom/helpers/index.ts b/packages/apicraft/bin/plugins/reatom/helpers/index.ts new file mode 100644 index 0000000..df2e7ca --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/helpers/index.ts @@ -0,0 +1,3 @@ +export * from './getReatomAsync'; +export * from './getReatomAsyncData'; +export * from './getReatomImport'; diff --git a/packages/apicraft/bin/plugins/reatom/index.ts b/packages/apicraft/bin/plugins/reatom/index.ts new file mode 100644 index 0000000..35c0807 --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/index.ts @@ -0,0 +1,2 @@ +export { defineReatomPlugin } from './config'; +export type { ReatomPlugin } from './types'; diff --git a/packages/apicraft/bin/plugins/reatom/plugin.ts b/packages/apicraft/bin/plugins/reatom/plugin.ts new file mode 100644 index 0000000..9f27aab --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/plugin.ts @@ -0,0 +1,21 @@ +import { removeRequestsBaseUrl } from '@/bin/plugins/helpers'; + +import type { ReatomPlugin } from './types'; + +import { classHandler } from './class/plugin'; +import { composedHandler } from './composed/plugin'; +import { standaloneHandler } from './standalone/plugin'; + +export const handler: ReatomPlugin['Handler'] = ({ plugin }) => { + if (plugin.config.baseUrl) removeRequestsBaseUrl(plugin, plugin.config.baseUrl); + + if (plugin.config.groupBy === 'class') { + classHandler({ plugin }); + } + if (plugin.config.groupBy === 'standalone') { + standaloneHandler({ plugin }); + } + if (plugin.config.groupBy === 'paths' || plugin.config.groupBy === 'tags') { + composedHandler({ plugin }); + } +}; diff --git a/packages/apicraft/bin/plugins/reatom/standalone/plugin.ts b/packages/apicraft/bin/plugins/reatom/standalone/plugin.ts new file mode 100644 index 0000000..d1107cf --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/standalone/plugin.ts @@ -0,0 +1,70 @@ +import type ts from 'typescript'; + +import { + capitalize, + generateRequestName, + getApicraftTypeImport, + getImportRequest +} from '@/bin/plugins/helpers'; + +import type { ReatomPlugin } from '../types'; + +import { getReatomAsync, getReatomAsyncData, getReatomImport } from '../helpers'; + +export const standaloneHandler: ReatomPlugin['Handler'] = ({ plugin }) => { + const reatomFile = plugin.createFile({ + id: 'reatom', + path: `${plugin.output}/reatom` + }); + + const requestImportNames: string[] = []; + const requestParamsTypeNames: string[] = []; + const functions: ts.VariableStatement[] = []; + + plugin.forEach('operation', (event) => { + const request = event.operation; + const requestName = generateRequestName(request, plugin.config.nameBy); + const requestParamsTypeName = `${capitalize(requestName)}RequestParams`; + + requestImportNames.push(requestName); + requestParamsTypeNames.push(requestParamsTypeName); + functions.push( + getReatomAsyncData({ + plugin, + request, + requestName, + requestParamsTypeName + }), + getReatomAsync({ + plugin, + requestName, + requestParamsTypeName + }) + ); + }); + + const imports: ts.ImportDeclaration[] = [ + // import type { ReatomAsyncDataSettings, ReatomAsyncSettings } from '@siberiacancode/apicraft'; + getApicraftTypeImport(['ReatomAsyncDataSettings', 'ReatomAsyncSettings']), + // import { action, computed, wrap, withAsync, withAsyncData } from '@reatom/core'; + getReatomImport(['action', 'computed', 'wrap', 'withAsync', 'withAsyncData']), + // import { requestName1, requestName2 } from './requests.gen'; + getImportRequest({ + folderPath: plugin.config.generateOutput, + requestFilePath: `${plugin.output}/requests`, + requestName: requestImportNames, + generateOutput: plugin.config.generateOutput + }), + // import { RequestNameRequestParams } from './requests.gen'; + getImportRequest({ + folderPath: plugin.config.generateOutput, + requestFilePath: `${plugin.output}/requests`, + requestName: requestParamsTypeNames, + generateOutput: plugin.config.generateOutput + }) + ]; + + reatomFile.add(...imports); + // export const requestNameAsyncData / requestNameAsync + reatomFile.add(...functions); +}; diff --git a/packages/apicraft/bin/plugins/reatom/types.d.ts b/packages/apicraft/bin/plugins/reatom/types.d.ts new file mode 100644 index 0000000..29e9062 --- /dev/null +++ b/packages/apicraft/bin/plugins/reatom/types.d.ts @@ -0,0 +1,15 @@ +import type { DefinePlugin } from '@hey-api/openapi-ts'; + +import type { ApicraftOption } from '@/bin/schemas'; + +export interface ReatomPluginConfig { + baseUrl?: ApicraftOption['baseUrl']; + exportFromIndex: boolean; + generateOutput: string; + groupBy?: ApicraftOption['groupBy']; + name: 'reatom'; + nameBy?: ApicraftOption['nameBy']; + output?: string; +} + +export type ReatomPlugin = DefinePlugin; diff --git a/packages/apicraft/bin/schemas/index.ts b/packages/apicraft/bin/schemas/index.ts index 655eb75..3dcdd6d 100644 --- a/packages/apicraft/bin/schemas/index.ts +++ b/packages/apicraft/bin/schemas/index.ts @@ -107,6 +107,7 @@ const pluginNameSchema = z.enum([ 'fastify', 'valibot', 'tanstack', + 'reatom', 'zod' ]); diff --git a/packages/apicraft/package.json b/packages/apicraft/package.json index 0fd828f..264985f 100644 --- a/packages/apicraft/package.json +++ b/packages/apicraft/package.json @@ -57,12 +57,17 @@ "pretty": "pnpm type && pnpm lint && pnpm format", "e2e-test": "pnpm build && vitest -c tests/vitest.config.ts" }, + "peerDependencies": { + "@reatom/core": "^1000", + "@siberiacancode/fetches": "^1", + "@tanstack/react-query": "^5", + "axios": "^1", + "ofetch": "^1 || ^2" + }, "dependencies": { "@antfu/install-pkg": "^1.1.0", "@clack/prompts": "^1.2.0", "@hey-api/openapi-ts": "0.82.5", - "@tanstack/react-query": "^5.90.21", - "axios": "^1.13.6", "cosmiconfig": "^9.0.1", "local-pkg": "^1.1.2", "typescript": "^5.9.3", @@ -70,6 +75,7 @@ "zod": "^4.3.6" }, "devDependencies": { + "@reatom/core": "^1000.15.1", "@siberiacancode/eslint": "*", "@siberiacancode/fetches": "^1.14.1", "@siberiacancode/prettier": "*", @@ -81,12 +87,6 @@ "axios": "^1.13.6", "ofetch": "^1.5.1" }, - "peerDependencies": { - "@siberiacancode/fetches": "^1", - "@tanstack/react-query": "^5", - "axios": "^1", - "ofetch": "^1 || ^2" - }, "lint-staged": { "*.{js,ts}": [ "prettier --write", diff --git a/packages/apicraft/src/types.ts b/packages/apicraft/src/types.ts index 7ba7a02..b74b156 100644 --- a/packages/apicraft/src/types.ts +++ b/packages/apicraft/src/types.ts @@ -1,3 +1,4 @@ +import type { AsyncDataOptions, AsyncOptions } from '@reatom/core'; import type { FetchesResponse, RequestConfig } from '@siberiacancode/fetches'; import type { UseMutationOptions, @@ -39,6 +40,39 @@ export interface TanstackMutationSettings Prom request?: NonNullable[0]>; } +export type ReatomAtom = (() => TValue) | TValue; +export type ReatomDeepAtomized = + | ([NonNullable] extends [readonly (infer Item)[]] + ? ReatomAtom> | ReatomDeepAtomized[] + : [NonNullable] extends [object] + ? + | ReatomAtom> + | { + [Key in keyof NonNullable]: ReatomDeepAtomized[Key]>; + } + : ReatomAtom>) + | Extract; + +export interface ReatomAsyncDataSettings Promise> { + params?: AsyncDataOptions< + Awaited>, + Parameters, + Awaited>, + Error, + undefined + >; + request?: Partial<{ + [Key in keyof NonNullable[0]>]: ReatomDeepAtomized< + NonNullable[0]>[Key] + >; + }>; +} + +export interface ReatomAsyncSettings Promise> { + params?: AsyncOptions; + request?: NonNullable[0]>; +} + export type ApicraftAxiosResponse = AxiosResponse; export type ApicraftFetchesResponse = FetchesResponse; export type ApicraftOfetchResponse = Data | Error; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dae3723..7d41581 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,12 +41,6 @@ importers: '@hey-api/openapi-ts': specifier: 0.82.5 version: 0.82.5(typescript@5.9.3) - '@tanstack/react-query': - specifier: ^5.90.21 - version: 5.90.21(react@19.2.4) - axios: - specifier: ^1.13.6 - version: 1.13.6 cosmiconfig: specifier: ^9.0.1 version: 9.0.1(typescript@5.9.3) @@ -63,9 +57,12 @@ importers: specifier: ^4.3.6 version: 4.3.6 devDependencies: + '@reatom/core': + specifier: ^1000.15.1 + version: 1000.15.2 '@siberiacancode/eslint': specifier: '*' - version: 2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@5.9.3)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + version: 2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@5.9.3)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) '@siberiacancode/fetches': specifier: ^1.14.1 version: 1.14.1 @@ -77,13 +74,19 @@ importers: version: 1.1.0(typescript@5.9.3) '@siberiacancode/vitest': specifier: '*' - version: 2.4.1(jsdom@27.3.0)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + version: 2.4.1(jsdom@28.1.0)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) + '@tanstack/react-query': + specifier: ^5.90.21 + version: 5.90.21(react@19.2.4) '@types/node': specifier: ^25.3.3 version: 25.3.5 '@types/yargs': specifier: ^17.0.35 version: 17.0.35 + axios: + specifier: ^1.13.6 + version: 1.13.6 ofetch: specifier: ^1.5.1 version: 1.5.1 @@ -92,16 +95,16 @@ importers: devDependencies: '@siberiacancode/eslint': specifier: '*' - version: 2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + version: 2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) '@siberiacancode/prettier': specifier: '*' version: 1.6.1(prettier@3.8.1) '@siberiacancode/vitest': specifier: '*' - version: 2.4.1(jsdom@27.3.0)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + version: 2.4.1(jsdom@28.1.0)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) vitest: specifier: 4.0.16 - version: 4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2) + version: 4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2) packages/yandex-metrika: devDependencies: @@ -351,9 +354,6 @@ packages: '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - '@asamuzakjp/css-color@4.1.2': - resolution: {integrity: sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==} - '@asamuzakjp/css-color@5.0.1': resolution: {integrity: sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -507,14 +507,6 @@ packages: '@csstools/css-syntax-patches-for-csstree@1.1.0': resolution: {integrity: sha512-H4tuz2nhWgNKLt1inYpoVCfbJbMwX/lQKp3g69rrrIMIYlFD9+zTykOKhNR8uGrAmbS/kT9n6hTFkmDkxLgeTA==} - '@csstools/css-syntax-patches-for-csstree@1.1.2': - resolution: {integrity: sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA==} - peerDependencies: - css-tree: ^3.2.1 - peerDependenciesMeta: - css-tree: - optional: true - '@csstools/css-tokenizer@3.0.4': resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} @@ -953,6 +945,9 @@ packages: '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + '@reatom/core@1000.15.2': + resolution: {integrity: sha512-ychH11wZaVHHYsfPuPQvgGr8YyonURggwQwiaTxy+164nRfDnXXgbvuaWePjim7K3FR3LfI6ydYNoqJnDh88Bg==} + '@rolldown/binding-android-arm64@1.0.0-rc.9': resolution: {integrity: sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -988,42 +983,36 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.9': resolution: {integrity: sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9': resolution: {integrity: sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9': resolution: {integrity: sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.9': resolution: {integrity: sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-rc.9': resolution: {integrity: sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-rc.9': resolution: {integrity: sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==} @@ -1085,79 +1074,66 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} @@ -1793,10 +1769,6 @@ packages: engines: {node: '>=4'} hasBin: true - cssstyle@5.3.7: - resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} - engines: {node: '>=20'} - cssstyle@6.2.0: resolution: {integrity: sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==} engines: {node: '>=20'} @@ -1807,10 +1779,6 @@ packages: damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - data-urls@6.0.1: - resolution: {integrity: sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==} - engines: {node: '>=20'} - data-urls@7.0.0: resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -2613,10 +2581,6 @@ packages: hookified@1.15.1: resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} - html-encoding-sniffer@4.0.0: - resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} - engines: {node: '>=18'} - html-encoding-sniffer@6.0.0: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -2641,9 +2605,8 @@ packages: engines: {node: '>=18'} hasBin: true - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} + idb-keyval@6.2.2: + resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==} ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} @@ -2851,15 +2814,6 @@ packages: resolution: {integrity: sha512-/2uqY7x6bsrpi3i9LVU6J89352C0rpMk0as8trXxCtvd4kPk1ke/Eyif6wqfSLvoNJqcDG9Vk4UsXgygzCt2xA==} engines: {node: '>=20.0.0'} - jsdom@27.3.0: - resolution: {integrity: sha512-GtldT42B8+jefDUC4yUKAvsaOrH7PDHmZxZXNgF2xMmymjUbRYJvpAybZAKEmXDGTM0mCsz8duOa4vTm5AY2Kg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - jsdom@28.1.0: resolution: {integrity: sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -2970,10 +2924,6 @@ packages: resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==} engines: {node: 20 || >=22} - lru-cache@11.2.7: - resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==} - engines: {node: 20 || >=22} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3555,9 +3505,6 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -3880,17 +3827,10 @@ packages: tldts-core@7.0.25: resolution: {integrity: sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==} - tldts-core@7.0.27: - resolution: {integrity: sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==} - tldts@7.0.25: resolution: {integrity: sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==} hasBin: true - tldts@7.0.27: - resolution: {integrity: sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg==} - hasBin: true - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3907,10 +3847,6 @@ packages: resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} engines: {node: '>=16'} - tough-cookie@6.0.1: - resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} - engines: {node: '>=16'} - tr46@6.0.0: resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} engines: {node: '>=20'} @@ -4188,23 +4124,10 @@ packages: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} engines: {node: '>=20'} - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation - - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - whatwg-mimetype@5.0.0: resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} engines: {node: '>=20'} - whatwg-url@15.1.0: - resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} - engines: {node: '>=20'} - whatwg-url@16.0.1: resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -4257,18 +4180,6 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ws@8.20.0: - resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -4327,7 +4238,7 @@ snapshots: '@acemir/cssom@0.9.31': {} - '@antfu/eslint-config@7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2))': + '@antfu/eslint-config@7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 1.2.0 @@ -4336,7 +4247,7 @@ snapshots: '@stylistic/eslint-plugin': 5.10.0(eslint@10.0.2(jiti@2.6.1)) '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@vitest/eslint-plugin': 1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + '@vitest/eslint-plugin': 1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) ansis: 4.2.0 cac: 6.7.14 eslint: 10.0.2(jiti@2.6.1) @@ -4382,7 +4293,7 @@ snapshots: - typescript - vitest - '@antfu/eslint-config@7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2))': + '@antfu/eslint-config@7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 1.2.0 @@ -4391,7 +4302,7 @@ snapshots: '@stylistic/eslint-plugin': 5.10.0(eslint@10.0.2(jiti@2.6.1)) '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2))(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2) '@typescript-eslint/parser': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2) - '@vitest/eslint-plugin': 1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + '@vitest/eslint-plugin': 1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) ansis: 4.2.0 cac: 6.7.14 eslint: 10.0.2(jiti@2.6.1) @@ -4553,14 +4464,6 @@ snapshots: package-manager-detector: 1.6.0 tinyexec: 1.0.4 - '@asamuzakjp/css-color@4.1.2': - dependencies: - '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 - lru-cache: 11.2.7 - '@asamuzakjp/css-color@5.0.1': dependencies: '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) @@ -4762,10 +4665,6 @@ snapshots: '@csstools/css-syntax-patches-for-csstree@1.1.0': {} - '@csstools/css-syntax-patches-for-csstree@1.1.2(css-tree@3.2.1)': - optionalDependencies: - css-tree: 3.2.1 - '@csstools/css-tokenizer@3.0.4': {} '@csstools/css-tokenizer@4.0.0': {} @@ -5345,6 +5244,12 @@ snapshots: dependencies: quansync: 1.0.0 + '@reatom/core@1000.15.2': + dependencies: + '@standard-schema/spec': 1.1.0 + optionalDependencies: + idb-keyval: 6.2.2 + '@rolldown/binding-android-arm64@1.0.0-rc.9': optional: true @@ -5469,9 +5374,9 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.59.0': optional: true - '@siberiacancode/eslint@2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@5.9.3)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2))': + '@siberiacancode/eslint@2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@5.9.3)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': dependencies: - '@antfu/eslint-config': 7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + '@antfu/eslint-config': 7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3))(@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) '@eslint-react/eslint-plugin': 2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) '@eslint/css': 0.14.1 '@next/eslint-plugin-next': 16.1.6 @@ -5510,9 +5415,9 @@ snapshots: - typescript - vitest - '@siberiacancode/eslint@2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2))': + '@siberiacancode/eslint@2.16.5(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(jiti@2.6.1)(tailwindcss@4.2.1)(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': dependencies: - '@antfu/eslint-config': 7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2)) + '@antfu/eslint-config': 7.4.3(@eslint-react/eslint-plugin@2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2))(@next/eslint-plugin-next@16.1.6)(@typescript-eslint/rule-tester@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.2))(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.29)(eslint-plugin-jsx-a11y@6.10.2(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2)) '@eslint-react/eslint-plugin': 2.13.0(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2) '@eslint/css': 0.14.1 '@next/eslint-plugin-next': 16.1.6 @@ -5606,10 +5511,15 @@ snapshots: dependencies: typescript: 6.0.2 - '@siberiacancode/vitest@2.4.1(jsdom@27.3.0)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2))': + '@siberiacancode/vitest@2.4.1(jsdom@28.1.0)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': dependencies: - jsdom: 27.3.0 - vitest: 4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2) + jsdom: 28.1.0 + vitest: 4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2) + + '@siberiacancode/vitest@2.4.1(jsdom@28.1.0)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': + dependencies: + jsdom: 28.1.0 + vitest: 4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2) '@sindresorhus/base62@1.0.0': {} @@ -5952,25 +5862,25 @@ snapshots: dependencies: valibot: 1.2.0(typescript@6.0.2) - '@vitest/eslint-plugin@1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2))': + '@vitest/eslint-plugin@1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': dependencies: '@typescript-eslint/scope-manager': 8.56.1 '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) eslint: 10.0.2(jiti@2.6.1) optionalDependencies: typescript: 5.9.3 - vitest: 4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2) + vitest: 4.0.18(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2))': + '@vitest/eslint-plugin@1.6.9(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2)(vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2))': dependencies: '@typescript-eslint/scope-manager': 8.56.1 '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@6.0.2) eslint: 10.0.2(jiti@2.6.1) optionalDependencies: typescript: 6.0.2 - vitest: 4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -6474,13 +6384,6 @@ snapshots: cssesc@3.0.0: {} - cssstyle@5.3.7: - dependencies: - '@asamuzakjp/css-color': 4.1.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.2(css-tree@3.2.1) - css-tree: 3.2.1 - lru-cache: 11.2.7 - cssstyle@6.2.0: dependencies: '@asamuzakjp/css-color': 5.0.1 @@ -6492,11 +6395,6 @@ snapshots: damerau-levenshtein@1.0.8: {} - data-urls@6.0.1: - dependencies: - whatwg-mimetype: 5.0.0 - whatwg-url: 15.1.0 - data-urls@7.0.0: dependencies: whatwg-mimetype: 5.0.0 @@ -8080,10 +7978,6 @@ snapshots: hookified@1.15.1: {} - html-encoding-sniffer@4.0.0: - dependencies: - whatwg-encoding: 3.1.1 - html-encoding-sniffer@6.0.0: dependencies: '@exodus/bytes': 1.15.0 @@ -8110,9 +8004,8 @@ snapshots: husky@9.1.7: {} - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 + idb-keyval@6.2.2: + optional: true ignore@5.3.2: {} @@ -8323,33 +8216,6 @@ snapshots: jsdoc-type-pratt-parser@7.1.1: {} - jsdom@27.3.0: - dependencies: - '@acemir/cssom': 0.9.31 - '@asamuzakjp/dom-selector': 6.8.1 - cssstyle: 5.3.7 - data-urls: 6.0.1 - decimal.js: 10.6.0 - html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-potential-custom-element-name: 1.0.1 - parse5: 8.0.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 6.0.1 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 8.0.1 - whatwg-encoding: 3.1.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 15.1.0 - ws: 8.20.0 - xml-name-validator: 5.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - jsdom@28.1.0: dependencies: '@acemir/cssom': 0.9.31 @@ -8482,8 +8348,6 @@ snapshots: lru-cache@11.2.6: {} - lru-cache@11.2.7: {} - lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -9266,8 +9130,6 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 - safer-buffer@2.1.2: {} - saxes@6.0.0: dependencies: xmlchars: 2.2.0 @@ -9633,16 +9495,10 @@ snapshots: tldts-core@7.0.25: {} - tldts-core@7.0.27: {} - tldts@7.0.25: dependencies: tldts-core: 7.0.25 - tldts@7.0.27: - dependencies: - tldts-core: 7.0.27 - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -9660,10 +9516,6 @@ snapshots: dependencies: tldts: 7.0.25 - tough-cookie@6.0.1: - dependencies: - tldts: 7.0.27 - tr46@6.0.0: dependencies: punycode: 2.3.1 @@ -9854,7 +9706,7 @@ snapshots: jiti: 2.6.1 yaml: 2.8.2 - vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@27.3.0)(yaml@2.8.2): + vitest@4.0.16(@types/node@25.3.5)(jiti@2.6.1)(jsdom@28.1.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.16 '@vitest/mocker': 4.0.16(vite@7.3.1(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2)) @@ -9878,7 +9730,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.3.5 - jsdom: 27.3.0 + jsdom: 28.1.0 transitivePeerDependencies: - jiti - less @@ -9960,19 +9812,8 @@ snapshots: webidl-conversions@8.0.1: {} - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - - whatwg-mimetype@4.0.0: {} - whatwg-mimetype@5.0.0: {} - whatwg-url@15.1.0: - dependencies: - tr46: 6.0.0 - webidl-conversions: 8.0.1 - whatwg-url@16.0.1: dependencies: '@exodus/bytes': 1.15.0 @@ -10052,8 +9893,6 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 - ws@8.20.0: {} - xml-name-validator@4.0.0: {} xml-name-validator@5.0.0: {} diff --git a/tools/eslint/eslint.config.js b/tools/eslint/eslint.config.js index 2d6f1ff..9dc1af7 100644 --- a/tools/eslint/eslint.config.js +++ b/tools/eslint/eslint.config.js @@ -1,5 +1,6 @@ import { eslint } from '@siberiacancode/eslint'; export default eslint({ - typescript: 'engine' + typescript: 'engine', + ignores: ['**/rules/**'] }); diff --git a/tools/eslint/src/plugin/rules/function-component-definition.ts b/tools/eslint/src/plugin/rules/function-component-definition.ts index c91be17..9d0cbf3 100644 --- a/tools/eslint/src/plugin/rules/function-component-definition.ts +++ b/tools/eslint/src/plugin/rules/function-component-definition.ts @@ -60,8 +60,7 @@ const getParams = ( if (node.params.length === 0) return undefined; const first = node.params[0]; const last = node.params[node.params.length - 1]; - if (first == null || last == null || !('range' in first) || !('range' in last)) - return undefined; + if (first == null || last == null || !('range' in first) || !('range' in last)) return undefined; return sourceCode.getText({ range: [first.range![0], last.range![1]] } as ESTree.Node & { range: [number, number] }); @@ -142,12 +141,7 @@ const walk = (node: ASTNode, visit: (n: ASTNode) => void): void => { if (value !== null && value !== undefined && typeof value === 'object') { if (Array.isArray(value)) value.forEach((child: unknown) => { - if ( - child !== null && - child !== undefined && - typeof child === 'object' && - 'type' in child - ) + if (child !== null && child !== undefined && typeof child === 'object' && 'type' in child) walk(child as ASTNode, visit); }); else if (