Skip to content

Commit aa0bfaa

Browse files
authored
Merge pull request #1680 from josh-hemphill/main
feat: add @pinia-colada/sdk plugin
2 parents 6184a27 + 714e8f9 commit aa0bfaa

File tree

12 files changed

+817
-1
lines changed

12 files changed

+817
-1
lines changed

.changeset/smooth-ties-brush.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hey-api/openapi-ts': patch
3+
---
4+
5+
feat(plugin): add `@pinia/colada` plugin

packages/openapi-ts-tests/main/test/plugins.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,15 @@ for (const version of versions) {
363363
description:
364364
'generate Fetch API client with TanStack Vue Query plugin with custom names',
365365
},
366+
// TODO: add Pinia Colada snapshots
367+
// {
368+
// config: createConfig({
369+
// output: 'fetch',
370+
// plugins: ['@pinia/colada', '@hey-api/client-fetch'],
371+
// }),
372+
// description:
373+
// 'generate Fetch API client with Pinia Colada plugin',
374+
// },
366375
{
367376
config: createConfig({
368377
output: 'default',

packages/openapi-ts/src/plugins/@hey-api/typescript/operation.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import { schemaToType } from './plugin';
99
import { typesId } from './ref';
1010
import type { HeyApiTypeScriptPlugin, PluginState } from './types';
1111

12-
const irParametersToIrSchema = ({
12+
// TODO: exported just for @pinia/colada, remove export once that plugin does not depend on it
13+
export const irParametersToIrSchema = ({
1314
parameters,
1415
}: {
1516
parameters: Record<string, IR.ParameterObject>;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { definePluginConfig } from '../../shared/utils/config';
2+
import { handler } from './plugin';
3+
import type { PiniaColadaPlugin } from './types';
4+
5+
export const defaultConfig: PiniaColadaPlugin['Config'] = {
6+
config: {
7+
enablePaginationOnKey: undefined,
8+
errorHandling: 'specific',
9+
exportFromIndex: false,
10+
groupByTag: false,
11+
importPath: '@pinia/colada',
12+
includeTypes: true,
13+
prefixUse: true,
14+
suffixQueryMutation: true,
15+
useInfiniteQueries: false,
16+
},
17+
dependencies: ['@hey-api/typescript'],
18+
handler: handler as PiniaColadaPlugin['Handler'],
19+
name: '@pinia/colada',
20+
output: '@pinia/colada',
21+
};
22+
23+
/**
24+
* Type helper for `@pinia/colada` plugin, returns {@link Plugin.Config} object
25+
*/
26+
export const defineConfig = definePluginConfig(defaultConfig);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { defaultConfig, defineConfig } from './config';
2+
export type { PiniaColadaPlugin } from './types';
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { GeneratedFile } from '../../../generate/file';
2+
import type { IR } from '../../../ir/types';
3+
import type { PiniaColadaPlugin } from './types';
4+
import { createComposable } from './utils';
5+
6+
/**
7+
* Creates a mutation function for an operation
8+
*/
9+
export const createMutationFunction = ({
10+
context,
11+
file,
12+
operation,
13+
plugin,
14+
}: {
15+
context: IR.Context;
16+
file: GeneratedFile;
17+
operation: IR.OperationObject;
18+
plugin: PiniaColadaPlugin['Instance'];
19+
}) => {
20+
// Allow hooks to customize or skip mutation generation
21+
if (
22+
plugin.config.onMutation &&
23+
plugin.config.onMutation(operation) === false
24+
) {
25+
return;
26+
}
27+
28+
createComposable({ context, file, isQuery: false, operation, plugin });
29+
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { clientId } from '../../@hey-api/client-core/utils';
2+
import { createMutationFunction } from './mutation';
3+
import { createQueryFunction } from './query';
4+
import type { PiniaColadaPlugin } from './types';
5+
import { isQuery } from './utils';
6+
7+
export const handler: PiniaColadaPlugin['Handler'] = ({ plugin }) => {
8+
if (!plugin.config.groupByTag) {
9+
plugin.createFile({
10+
id: plugin.name,
11+
path: plugin.output,
12+
});
13+
}
14+
15+
// Create files based on grouping strategy
16+
const getFile = (tag: string) => {
17+
if (!plugin.config.groupByTag) {
18+
return (
19+
plugin.context.file({ id: plugin.name }) ??
20+
plugin.createFile({
21+
id: plugin.name,
22+
path: plugin.output,
23+
})
24+
);
25+
}
26+
27+
const fileId = `${plugin.name}/${tag}`;
28+
return (
29+
plugin.context.file({ id: fileId }) ??
30+
plugin.createFile({
31+
id: fileId,
32+
path: `${plugin.output}/${tag}`,
33+
})
34+
);
35+
};
36+
37+
plugin.forEach('operation', ({ operation }) => {
38+
const file = getFile(operation.tags?.[0] || 'default');
39+
40+
// Determine if the operation should be a query or mutation
41+
if (isQuery(operation, plugin)) {
42+
createQueryFunction({ context: plugin.context, file, operation, plugin });
43+
} else {
44+
createMutationFunction({
45+
context: plugin.context,
46+
file,
47+
operation,
48+
plugin,
49+
});
50+
}
51+
});
52+
53+
// Add client import to all generated files
54+
Object.entries(plugin.context.files).forEach(([fileId, file]) => {
55+
if (fileId.startsWith(plugin.name)) {
56+
// Make sure we have a client import
57+
file.import({
58+
alias: '_heyApiClient',
59+
module: file.relativePathToFile({
60+
context: plugin.context,
61+
id: clientId,
62+
}),
63+
name: 'client',
64+
});
65+
}
66+
});
67+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { GeneratedFile } from '../../../generate/file';
2+
import type { IR } from '../../../ir/types';
3+
import type { PiniaColadaPlugin } from './types';
4+
import { createComposable } from './utils';
5+
6+
/**
7+
* Creates a query function for an operation
8+
*/
9+
export const createQueryFunction = ({
10+
context,
11+
file,
12+
operation,
13+
plugin,
14+
}: {
15+
context: IR.Context;
16+
file: GeneratedFile;
17+
operation: IR.OperationObject;
18+
plugin: PiniaColadaPlugin['Instance'];
19+
}) => {
20+
if (plugin.config.onQuery && plugin.config.onQuery(operation) === false) {
21+
return;
22+
}
23+
24+
createComposable({ context, file, isQuery: true, operation, plugin });
25+
};

0 commit comments

Comments
 (0)