Skip to content

Commit 5b476eb

Browse files
authored
chore: make changes to satisfy eslint rules (#2517)
* add type:module to sample packages * chore: make changes to satisfy eslint rules * ci: run linting in selected packages * fixed failed zod tests * reverted some changes where the type were misleading * fix typo
1 parent 2f6fbcb commit 5b476eb

File tree

43 files changed

+353
-310
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+353
-310
lines changed

.github/workflows/tests.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ jobs:
3333
run: yarn
3434
- name: build
3535
run: yarn build
36+
- name: lint
37+
# not all packages pass linting yet - ongoing work
38+
run: |
39+
yarn workspace @orval/angular lint
40+
yarn workspace @orval/axios lint
41+
yarn workspace @orval/fetch lint
42+
yarn workspace @orval/hono lint
43+
yarn workspace @orval/mcp lint
44+
yarn workspace @orval/swr lint
3645
- name: samples up to date
3746
uses: nickcharlton/[email protected]
3847
with:

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
{
22
"cSpell.words": [
3+
"axios",
34
"Emptyish",
5+
"hono",
46
"listitem",
57
"openapi",
68
"Orval",
79
"Petstore",
8-
"tanstack"
10+
"tanstack",
11+
"zods"
912
],
1013
"files.associations": {
1114
"turbo.json": "jsonc"

eslint.config.mjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,28 @@ export default defineConfig(
3737
'no-case-declarations': 'warn',
3838
'no-prototype-builtins': 'warn',
3939
'unicorn/prevent-abbreviations': 'off',
40+
'unicorn/consistent-function-scoping': [
41+
'error',
42+
{ checkArrowFunctions: false },
43+
],
44+
'@typescript-eslint/restrict-template-expressions': [
45+
'error',
46+
// default (not strict) settings
47+
// consider tightening these in the future
48+
{
49+
allow: [{ name: ['Error', 'URL', 'URLSearchParams'], from: 'lib' }],
50+
allowAny: true,
51+
allowBoolean: true,
52+
allowNullish: true,
53+
allowNumber: true,
54+
allowRegExp: true,
55+
},
56+
],
4057

4158
// enable these in the future
59+
'unicorn/no-null': 'warn',
4260
'unicorn/prefer-at': 'off',
61+
'unicorn/no-array-reduce': 'warn',
4362
'@typescript-eslint/no-unused-vars': 'warn',
4463
'@typescript-eslint/ban-ts-comment': 'warn',
4564
'@typescript-eslint/no-explicit-any': 'warn',

packages/angular/src/index.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ export const generateAngularFooter: ClientFooterBuilder = ({
118118

119119
for (const operationName of operationNames) {
120120
if (returnTypesToWrite.has(operationName)) {
121+
// Map.has ensures Map.get will not return undefined, but TS still complains
122+
// bug https://github.com/microsoft/TypeScript/issues/13086
123+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
121124
footer += returnTypesToWrite.get(operationName) + '\n';
122125
}
123126
}
@@ -142,9 +145,9 @@ const generateImplementation = (
142145
}: GeneratorVerbOptions,
143146
{ route, context }: GeneratorOptions,
144147
) => {
145-
const isRequestOptions = override?.requestOptions !== false;
146-
const isFormData = !override?.formData.disabled;
147-
const isFormUrlEncoded = override?.formUrlEncoded !== false;
148+
const isRequestOptions = override.requestOptions !== false;
149+
const isFormData = !override.formData.disabled;
150+
const isFormUrlEncoded = override.formUrlEncoded !== false;
148151
const isExactOptionalPropertyTypes =
149152
!!context.output.tsconfig?.compilerOptions?.exactOptionalPropertyTypes;
150153
const bodyForm = generateFormDataAndUrlEncodedFunction({
@@ -180,7 +183,7 @@ const generateImplementation = (
180183

181184
const requestOptions = isRequestOptions
182185
? generateMutatorRequestOptions(
183-
override?.requestOptions,
186+
override.requestOptions,
184187
mutator.hasThirdArg,
185188
)
186189
: '';
@@ -213,11 +216,11 @@ const generateImplementation = (
213216
queryParams,
214217
response,
215218
verb,
216-
requestOptions: override?.requestOptions,
219+
requestOptions: override.requestOptions,
217220
isFormData,
218221
isFormUrlEncoded,
219222
paramsSerializer,
220-
paramsSerializerOptions: override?.paramsSerializerOptions,
223+
paramsSerializerOptions: override.paramsSerializerOptions,
221224
isAngular: true,
222225
isExactOptionalPropertyTypes,
223226
hasSignal: false,

packages/axios/src/index.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ const generateAxiosImplementation = (
7676
}: GeneratorVerbOptions,
7777
{ route, context }: GeneratorOptions,
7878
) => {
79-
const isRequestOptions = override?.requestOptions !== false;
80-
const isFormData = !override?.formData.disabled;
81-
const isFormUrlEncoded = override?.formUrlEncoded !== false;
79+
const isRequestOptions = override.requestOptions !== false;
80+
const isFormData = !override.formData.disabled;
81+
const isFormUrlEncoded = override.formUrlEncoded !== false;
8282
const isExactOptionalPropertyTypes =
8383
!!context.output.tsconfig?.compilerOptions?.exactOptionalPropertyTypes;
8484

@@ -110,7 +110,7 @@ const generateAxiosImplementation = (
110110

111111
const requestOptions = isRequestOptions
112112
? generateMutatorRequestOptions(
113-
override?.requestOptions,
113+
override.requestOptions,
114114
mutator.hasSecondArg,
115115
)
116116
: '';
@@ -154,11 +154,11 @@ const generateAxiosImplementation = (
154154
queryParams,
155155
response,
156156
verb,
157-
requestOptions: override?.requestOptions,
157+
requestOptions: override.requestOptions,
158158
isFormData,
159159
isFormUrlEncoded,
160160
paramsSerializer,
161-
paramsSerializerOptions: override?.paramsSerializerOptions,
161+
paramsSerializerOptions: override.paramsSerializerOptions,
162162
isExactOptionalPropertyTypes,
163163
hasSignal: false,
164164
});
@@ -222,6 +222,9 @@ export const generateAxiosFooter: ClientFooterBuilder = ({
222222

223223
for (const operationName of operationNames) {
224224
if (returnTypesToWrite.has(operationName)) {
225+
// Map.has ensures Map.get will not return undefined, but TS still complains
226+
// bug https://github.com/microsoft/TypeScript/issues/13086
227+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
225228
const func = returnTypesToWrite.get(operationName)!;
226229
footer += func(noFunction ? undefined : title) + '\n';
227230
}
@@ -240,10 +243,7 @@ export const generateAxios = (
240243
return { implementation, imports };
241244
};
242245

243-
export const generateAxiosFunctions: ClientBuilder = async (
244-
verbOptions,
245-
options,
246-
) => {
246+
export const generateAxiosFunctions: ClientBuilder = (verbOptions, options) => {
247247
const { implementation, imports } = generateAxios(verbOptions, options);
248248

249249
return {

packages/core/src/types.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface NormalizedOptions {
3838

3939
export type NormalizedOutputOptions = {
4040
workspace?: string;
41-
target?: string;
41+
target: string;
4242
schemas?: string;
4343
namingConvention: NamingConvention;
4444
fileExtension: string;
@@ -71,8 +71,8 @@ export type NormalizedOverrideOutput = {
7171
title?: (title: string) => string;
7272
transformer?: OutputTransformer;
7373
mutator?: NormalizedMutator;
74-
operations: Record<string, NormalizedOperationOptions>;
75-
tags: Record<string, NormalizedOperationOptions>;
74+
operations: Record<string, NormalizedOperationOptions | undefined>;
75+
tags: Record<string, NormalizedOperationOptions | undefined>;
7676
mock?: OverrideMockOptions;
7777
contentType?: OverrideOutputContentType;
7878
header: false | ((info: InfoObject) => string[] | string);
@@ -208,7 +208,7 @@ export type EnumGeneration =
208208

209209
export type OutputOptions = {
210210
workspace?: string;
211-
target?: string;
211+
target: string;
212212
schemas?: string;
213213
namingConvention?: NamingConvention;
214214
fileExtension?: string;
@@ -546,7 +546,7 @@ export type NormalizedZodOptions = {
546546
body: boolean | ZodCoerceType[];
547547
response: boolean | ZodCoerceType[];
548548
};
549-
preprocess: {
549+
preprocess?: {
550550
param?: NormalizedMutator;
551551
query?: NormalizedMutator;
552552
header?: NormalizedMutator;
@@ -616,9 +616,9 @@ export type AngularOptions = {
616616
export type SwrOptions = {
617617
useInfinite?: boolean;
618618
useSWRMutationForGet?: boolean;
619-
swrOptions?: any;
620-
swrMutationOptions?: any;
621-
swrInfiniteOptions?: any;
619+
swrOptions?: unknown;
620+
swrMutationOptions?: unknown;
621+
swrInfiniteOptions?: unknown;
622622
};
623623

624624
export type NormalizedFetchOptions = {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Type safe way to get arbitrary property from an object.
3+
*
4+
* @param obj - The object from which to retrieve the property.
5+
* @param propertyName - The name of the property to retrieve.
6+
* @returns Object with `hasProperty: true` and `value` of the property if it exists; otherwise `hasProperty: false` and undefined.
7+
*
8+
* @remarks Until TypeScript adds type-narrowing for Object.hasOwn we have to use this workaround
9+
*/
10+
export function getPropertySafe<T extends object, K extends keyof T>(
11+
obj: T,
12+
propertyName: K | string,
13+
):
14+
| { hasProperty: true; value: T[K] }
15+
| { hasProperty: false; value: undefined } {
16+
if (Object.hasOwn(obj, propertyName)) {
17+
// safe to cast here because of the above check
18+
return { hasProperty: true, value: obj[propertyName as K] };
19+
}
20+
21+
return { hasProperty: false, value: undefined };
22+
}

packages/core/src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './dynamic-import';
99
export * from './extension';
1010
export * from './file';
1111
export * from './file-extensions';
12+
export * from './get-property-safe';
1213
export * from './is-body-verb';
1314
export * from './logger';
1415
export * from './merge-deep';

packages/fetch/src/index.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ export const generateRequestFunction = (
3939
}: GeneratorVerbOptions,
4040
{ route, context, pathRoute }: GeneratorOptions,
4141
) => {
42-
const isRequestOptions = override?.requestOptions !== false;
43-
const isFormData = !override?.formData.disabled;
44-
const isFormUrlEncoded = override?.formUrlEncoded !== false;
42+
const isRequestOptions = override.requestOptions !== false;
43+
const isFormData = !override.formData.disabled;
44+
const isFormUrlEncoded = override.formUrlEncoded !== false;
4545

4646
const getUrlFnName = camel(`get-${operationName}-url`);
4747
const getUrlFnProps = toObjectString(
@@ -58,7 +58,7 @@ export const generateRequestFunction = (
5858
| PathItemObject
5959
| undefined;
6060
const parameters =
61-
spec?.[verb]?.parameters || ([] as (ParameterObject | ReferenceObject)[]);
61+
spec?.[verb]?.parameters ?? ([] as (ParameterObject | ReferenceObject)[]);
6262

6363
const explodeParameters = parameters.filter((parameter) => {
6464
const { schema } = resolveRef<ParameterObject>(parameter, context);
@@ -129,9 +129,11 @@ ${
129129
contentType === 'application/nd-json' ||
130130
contentType === 'application/x-ndjson';
131131

132-
const isNdJson = response.contentTypes.some(isContentTypeNdJson);
132+
const isNdJson = response.contentTypes.some((contentType) =>
133+
isContentTypeNdJson(contentType),
134+
);
133135
const responseTypeName = fetchResponseTypeName(
134-
override.fetch?.includeHttpResponseReturnType,
136+
override.fetch.includeHttpResponseReturnType,
135137
isNdJson ? 'Response' : response.definition.success,
136138
operationName,
137139
);
@@ -230,8 +232,8 @@ ${override.fetch.forceSuccessResponse && hasSuccess ? '' : `export type ${respon
230232
? `Promise<${successName}>`
231233
: `Promise<${responseTypeName}>`;
232234

233-
const globalFetchOptions = isObject(override?.requestOptions)
234-
? `${stringify(override?.requestOptions)?.slice(1, -1)?.trim()}`
235+
const globalFetchOptions = isObject(override.requestOptions)
236+
? stringify(override.requestOptions)?.slice(1, -1).trim()
235237
: '';
236238
const fetchMethodOption = `method: '${verb.toUpperCase()}'`;
237239
const ignoreContentTypes = ['multipart/form-data'];

0 commit comments

Comments
 (0)