Skip to content
Open
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
3 changes: 2 additions & 1 deletion packages/apicraft/apicraft.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const apicraftConfig = apicraft([
instance: 'axios',
baseUrl: '/api',
nameBy: 'path',
groupBy: 'class'
groupBy: 'paths',
plugins: ['reatom', 'tanstack']
},
{
input: 'example-apiV1.yaml',
Expand Down
17 changes: 17 additions & 0 deletions packages/apicraft/bin/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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({
Expand Down
8 changes: 7 additions & 1 deletion packages/apicraft/bin/helpers/installDependencies.ts
Original file line number Diff line number Diff line change
@@ -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<Dependency, string> = {
axios: '^1.13.6',
ofetch: '^1.5.1',
'@reatom/core': '^1000.15.1',
'@siberiacancode/fetches': '^1.14.1',
'@tanstack/react-query': '^5.90.21'
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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('/')
Expand Down
68 changes: 68 additions & 0 deletions packages/apicraft/bin/plugins/reatom/class/plugin.ts
Original file line number Diff line number Diff line change
@@ -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);
};
Original file line number Diff line number Diff line change
@@ -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
})
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { generateReatomFile } from './generateReatomFile';
20 changes: 20 additions & 0 deletions packages/apicraft/bin/plugins/reatom/composed/plugin.ts
Original file line number Diff line number Diff line change
@@ -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 });
});
18 changes: 18 additions & 0 deletions packages/apicraft/bin/plugins/reatom/config.ts
Original file line number Diff line number Diff line change
@@ -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);
Loading