Skip to content

Commit bace2e0

Browse files
committed
fix: remove duplicate generation of hook options
1 parent 191ada9 commit bace2e0

File tree

4 files changed

+46
-95
lines changed

4 files changed

+46
-95
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6161

6262
- **All wrapped hook exports** are now marked as `@deprecated`
6363
- `use{MethodName}()` - query hooks
64-
- `useSuspense{MethodName}()` - suspense query hooks
64+
- `useSuspense{MethodName}()` - suspense query hooks
6565
- `useInfinite{MethodName}()` - infinite query hooks
6666
- `useSuspenseInfinite{MethodName}()` - suspense infinite query hooks
6767
- Hooks remain functional for backward compatibility but display deprecation warnings

src/hook-file.ts

Lines changed: 40 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,18 @@ export class HookFile extends ModuleBuilder {
6767
];
6868

6969
*body(): Iterable<string> {
70+
// === QUERY/MUTATION OPTIONS EXPORTS (React Query v5) ===
71+
yield '// Query and mutation options exports for React Query v5';
72+
yield '';
73+
74+
for (const method of this.int.methods) {
75+
const httpMethod = getHttpMethodByName(this.service, method.name.value);
76+
const httpRoute = this.getHttpRoute(httpMethod);
77+
yield* this.generateAllOptionsExports(method, httpMethod, httpRoute);
78+
}
79+
7080
// === LEGACY HOOKS (deprecated) ===
81+
yield '';
7182
yield '// Legacy hooks - deprecated, use query/mutation options exports instead';
7283
yield '';
7384

@@ -116,10 +127,6 @@ export class HookFile extends ModuleBuilder {
116127

117128
const isGet = httpMethod?.verb.value === 'get' && !!httpRoute;
118129

119-
if (isGet) {
120-
yield* this.generateQueryOptions(method, httpRoute);
121-
}
122-
123130
if (isGet) {
124131
const queryOptionsName = buildQueryOptionsName(method);
125132
const paramsCallsite = method.parameters.length ? 'params' : '';
@@ -128,7 +135,8 @@ export class HookFile extends ModuleBuilder {
128135

129136
const optionsExpression = `options?: Omit<${UndefinedInitialDataOptions()}<${genericTypes}>,'queryKey' | 'queryFn' | 'select'>`;
130137

131-
yield* buildDescription(method.description, true);
138+
// NOTE: We are manually setting a deprecation message
139+
yield* buildDescription(method.description, false);
132140
yield `/** @deprecated Use ${queryOptionsName} with useQuery instead */`;
133141
yield `export function ${name}(${[
134142
paramsExpression,
@@ -138,7 +146,8 @@ export class HookFile extends ModuleBuilder {
138146
yield ` return ${useQuery()}({...defaultOptions, ...options});`;
139147
yield `}`;
140148
yield '';
141-
yield* buildDescription(method.description, true);
149+
// NOTE: We are manually setting a deprecation message
150+
yield* buildDescription(method.description, false);
142151
yield `/** @deprecated Use ${queryOptionsName} with useSuspenseQuery instead */`;
143152
yield `export function ${suspenseName}(${[
144153
paramsExpression,
@@ -159,7 +168,8 @@ export class HookFile extends ModuleBuilder {
159168

160169
const optionsExpression = `options?: Omit<${mutationOptions()}, 'mutationFn'>`;
161170

162-
yield* buildDescription(method.description, true);
171+
// NOTE: We are manually setting a deprecation message
172+
yield* buildDescription(method.description, false);
163173
yield `/** @deprecated Use ${buildMutationOptionsName(
164174
method,
165175
)} with useMutation instead */`;
@@ -222,14 +232,16 @@ export class HookFile extends ModuleBuilder {
222232
yield ` return res;`;
223233
yield ` },`;
224234
yield* this.buildInfiniteSelectFn(method);
225-
yield ` initialPageParam: ${getInitialPageParam()}(params${q ? '?? {}' : ''
226-
}),`;
235+
yield ` initialPageParam: ${getInitialPageParam()}(params${
236+
q ? '?? {}' : ''
237+
}),`;
227238
yield ` ${getNextPageParam()},`;
228239
yield ` ${getPreviousPageParam()},`;
229240
yield ` };`;
230241
yield `}`;
231242

232-
yield* buildDescription(method.description, true);
243+
// NOTE: We are manually setting a deprecation message
244+
yield* buildDescription(method.description, false);
233245
yield `/** @deprecated Use ${buildInfiniteQueryOptionsName(
234246
method,
235247
)} with useInfiniteQuery instead */`;
@@ -241,7 +253,8 @@ export class HookFile extends ModuleBuilder {
241253
yield ` return ${useInfiniteQuery()}(options);`;
242254
yield `}`;
243255

244-
yield* buildDescription(method.description, true);
256+
// NOTE: We are manually setting a deprecation message
257+
yield* buildDescription(method.description, false);
245258
yield `/** @deprecated Use ${buildInfiniteQueryOptionsName(
246259
method,
247260
)} with useSuspenseInfiniteQuery instead */`;
@@ -256,17 +269,6 @@ export class HookFile extends ModuleBuilder {
256269

257270
yield '';
258271
}
259-
260-
// === NEW QUERY/MUTATION OPTIONS EXPORTS ===
261-
yield '';
262-
yield '// Query and mutation options exports for React Query v5';
263-
yield '';
264-
265-
for (const method of this.int.methods) {
266-
const httpMethod = getHttpMethodByName(this.service, method.name.value);
267-
const httpRoute = this.getHttpRoute(httpMethod);
268-
yield* this.generateAllOptionsExports(method, httpMethod, httpRoute);
269-
}
270272
}
271273

272274
private buildMutationOptionsType(method: Method): () => string {
@@ -345,8 +347,9 @@ export class HookFile extends ModuleBuilder {
345347

346348
yield ` select: (data: ${InfiniteData()}<${type(
347349
returnTypeName,
348-
)}, string | undefined>) => data.pages.flatMap((page) => page.data${optional ? ' ?? []' : ''
349-
}),`;
350+
)}, string | undefined>) => data.pages.flatMap((page) => page.data${
351+
optional ? ' ?? []' : ''
352+
}),`;
350353
}
351354

352355
private buildQueryOptions(method: Method): () => string {
@@ -375,58 +378,6 @@ export class HookFile extends ModuleBuilder {
375378
return genericTypes;
376379
}
377380

378-
private *generateQueryOptions(
379-
method: Method,
380-
httpRoute: HttpRoute,
381-
): Iterable<string> {
382-
const queryOptions = this.buildQueryOptions(method);
383-
const QueryError = () => this.runtime.type('QueryError');
384-
const assert = () => this.runtime.fn('assert');
385-
const type = (t: string) => this.types.type(t);
386-
387-
const serviceName = buildServiceName(this.int);
388-
const serviceHookName = buildServiceHookName(this.int);
389-
const name = buildQueryOptionsName(method);
390-
const paramsType = from(buildParamsType(method));
391-
const q = method.parameters.every((param) => !isRequired(param.value))
392-
? '?'
393-
: '';
394-
const paramsExpression = method.parameters.length
395-
? `params${q}: ${type(paramsType)}`
396-
: '';
397-
const paramsCallsite = method.parameters.length ? 'params' : '';
398-
399-
const { skipSelect, dataProp } = this.xxxx(method);
400-
401-
const guard = () => this.runtime.fn('guard');
402-
403-
yield `const ${name} = (${paramsExpression}) => {`;
404-
yield ` const ${serviceName} = ${this.context.fn(serviceHookName)}()`;
405-
yield ` return ${queryOptions()}({`;
406-
yield ` queryKey: ${this.buildQueryKey(method)},`;
407-
yield ` queryFn: async () => {`;
408-
yield ` const res = await ${guard()}(${serviceName}.${camel(
409-
method.name.value,
410-
)}(${paramsCallsite}));`;
411-
yield ` if (res.errors.length) {`;
412-
yield ` const handled: ${QueryError()}<${type(
413-
'Error',
414-
)}[]> = { kind: 'handled', payload: res.errors };`;
415-
yield ` throw handled`;
416-
yield ` }`;
417-
yield ` return res;`;
418-
yield ` },`;
419-
if (!skipSelect) {
420-
if (dataProp && !isRequired(dataProp.value)) {
421-
yield ` select: (data) => { ${assert()}(data.data); return data.data},`;
422-
} else {
423-
yield ` select: (data) => data.data,`;
424-
}
425-
}
426-
yield ` });`;
427-
yield `};`;
428-
}
429-
430381
private getHttpRoute(
431382
httpMethod: HttpMethod | undefined,
432383
): HttpRoute | undefined {
@@ -462,21 +413,21 @@ export class HookFile extends ModuleBuilder {
462413
const dataProp =
463414
returnType.kind === 'Type'
464415
? returnType.properties.find(
465-
(p) =>
466-
p.name.value.toLocaleLowerCase() === 'data' ||
467-
p.name.value.toLocaleLowerCase() === 'value' ||
468-
p.name.value.toLocaleLowerCase() === 'values',
469-
)
416+
(p) =>
417+
p.name.value.toLocaleLowerCase() === 'data' ||
418+
p.name.value.toLocaleLowerCase() === 'value' ||
419+
p.name.value.toLocaleLowerCase() === 'values',
420+
)
470421
: undefined;
471422
if (!dataProp) return { envelope: undefined, returnType };
472423

473424
const errorProp =
474425
returnType.kind === 'Type'
475426
? returnType.properties.find(
476-
(p) =>
477-
p.name.value.toLocaleLowerCase() === 'error' ||
478-
p.name.value.toLocaleLowerCase() === 'errors',
479-
)
427+
(p) =>
428+
p.name.value.toLocaleLowerCase() === 'error' ||
429+
p.name.value.toLocaleLowerCase() === 'errors',
430+
)
480431
: undefined;
481432
if (!errorProp) return { envelope: undefined, returnType };
482433

@@ -600,7 +551,7 @@ export class HookFile extends ModuleBuilder {
600551
yield ` mutationFn: async (${paramsExpression}) => {`;
601552
yield ` const res = await ${guard()}(${serviceName}.${camel(
602553
method.name.value,
603-
)}(${paramsCallsite});`;
554+
)}(${paramsCallsite}));`;
604555
yield ` if (res.errors.length) {`;
605556
yield ` const handled: ${QueryError()}<${type(
606557
'Error',
@@ -666,8 +617,9 @@ export class HookFile extends ModuleBuilder {
666617
yield ` return res;`;
667618
yield ` },`;
668619
yield* this.buildInfiniteSelectFn(method);
669-
yield ` initialPageParam: ${getInitialPageParam()}(params${q ? '?? {}' : ''
670-
}),`;
620+
yield ` initialPageParam: ${getInitialPageParam()}(params${
621+
q ? '?? {}' : ''
622+
}),`;
671623
yield ` ${getNextPageParam()},`;
672624
yield ` ${getPreviousPageParam()},`;
673625
yield ` });`;

src/name-helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export function buildHookName(
5151
) {
5252
// Query Hook
5353
return camel(
54-
`use_${options?.suspense ? 'suspense_' : ''}${options?.infinite ? 'infinite_' : ''
54+
`use_${options?.suspense ? 'suspense_' : ''}${
55+
options?.infinite ? 'infinite_' : ''
5556
}${name.slice(3)}`,
5657
);
5758
}

src/snapshot/test-utils.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,17 @@ export async function* generateFiles(): AsyncIterable<File> {
1111

1212
const options: NamespacedReactQueryOptions = {};
1313

14-
const parser = require('@basketry/ir');
15-
1614
const { engines } = await NodeEngine.load({
1715
sourcePath: 'source/path.ext',
1816
sourceContent: JSON.stringify(service),
19-
parser: parser.parse,
17+
parser: (x) => ({ service: JSON.parse(x), violations: [] }),
2018
generators: [generateHooks],
2119
options,
2220
});
2321

2422
for (const engine of engines) {
25-
engine.runParser();
26-
engine.runGenerators();
23+
await engine.runParser();
24+
await engine.runGenerators();
2725

2826
for (const file of engine.files) {
2927
if (file.path[0] !== '.gitattributes') {

0 commit comments

Comments
 (0)