Skip to content

Commit

Permalink
Fix Query parameters reactivity in Vue (orval-labs#931)
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim-Mazurok authored Nov 29, 2023
1 parent 80bb6ca commit 1335879
Show file tree
Hide file tree
Showing 40 changed files with 2,475 additions and 565 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ jobs:
os: [ubuntu-latest, windows-latest]
node-version: [18.x]
steps:
- name: Set git to use LF (instead of CRLF on Windows)
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
Expand All @@ -25,6 +29,8 @@ jobs:
run: yarn
- name: build
run: yarn build
- name: formatting
run: yarn format:check
- name: unit tests
run: yarn test:ci
- name: tests install
Expand Down
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ node_modules

# Build
.next
**/dist
3 changes: 2 additions & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"trailingComma": "all"
"trailingComma": "all",
"endOfLine": "lf"
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"private": true,
"scripts": {
"format": "prettier --write .",
"format:check": "prettier --check .",
"format:staged": "pretty-quick --staged",
"prerelease": "yarn build && cd ./tests && yarn generate && yarn build",
"release": "dotenv release-it",
Expand All @@ -18,7 +19,8 @@
"update-samples": "zx ./scripts/update-samples.mjs",
"build": "turbo run build",
"test": "turbo run test",
"test:ci": "turbo run test -- --run",
"test:ci": "yarn test -- -- --run && yarn test:vue-query --run",
"test:vue-query": "cd ./samples/vue-query && yarn && yarn test",
"lint": "turbo run lint",
"dev": "turbo run dev"
},
Expand Down
21 changes: 19 additions & 2 deletions packages/core/src/generators/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const generateAxiosOptions = ({
headers,
requestOptions,
hasSignal,
isVue,
paramsSerializer,
paramsSerializerOptions,
}: {
Expand All @@ -46,6 +47,7 @@ export const generateAxiosOptions = ({
headers?: GeneratorSchema;
requestOptions?: object | boolean;
hasSignal: boolean;
isVue: boolean;
paramsSerializer?: GeneratorMutator;
paramsSerializerOptions?: ParamsSerializerOptions;
}) => {
Expand Down Expand Up @@ -96,7 +98,11 @@ export const generateAxiosOptions = ({
value += '\n ...options,';

if (queryParams) {
value += '\n params: {...params, ...options?.params},';
if (isVue) {
value += '\n params: {...unref(params), ...options?.params},';
} else {
value += '\n params: {...params, ...options?.params},';
}
}

if (headers) {
Expand Down Expand Up @@ -130,6 +136,7 @@ export const generateOptions = ({
isAngular,
isExactOptionalPropertyTypes,
hasSignal,
isVue,
paramsSerializer,
paramsSerializerOptions,
}: {
Expand All @@ -145,6 +152,7 @@ export const generateOptions = ({
isAngular?: boolean;
isExactOptionalPropertyTypes: boolean;
hasSignal: boolean;
isVue?: boolean;
paramsSerializer?: GeneratorMutator;
paramsSerializerOptions?: ParamsSerializerOptions;
}) => {
Expand All @@ -160,6 +168,7 @@ export const generateOptions = ({
requestOptions,
isExactOptionalPropertyTypes,
hasSignal,
isVue: isVue ?? false,
paramsSerializer,
paramsSerializerOptions,
});
Expand Down Expand Up @@ -207,6 +216,7 @@ export const generateBodyMutatorConfig = (

export const generateQueryParamsAxiosConfig = (
response: GetterResponse,
isVue: boolean,
queryParams?: GetterQueryParam,
) => {
if (!queryParams && !response.isBlob) {
Expand All @@ -216,7 +226,11 @@ export const generateQueryParamsAxiosConfig = (
let value = '';

if (queryParams) {
value += ',\n params';
if (isVue) {
value += ',\n params: unref(params)';
} else {
value += ',\n params';
}
}

if (response.isBlob) {
Expand All @@ -238,6 +252,7 @@ export const generateMutatorConfig = ({
isBodyVerb,
hasSignal,
isExactOptionalPropertyTypes,
isVue,
}: {
route: string;
body: GetterBody;
Expand All @@ -250,13 +265,15 @@ export const generateMutatorConfig = ({
isBodyVerb: boolean;
hasSignal: boolean;
isExactOptionalPropertyTypes: boolean;
isVue?: boolean;
}) => {
const bodyOptions = isBodyVerb
? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded)
: '';

const queryParamsOptions = generateQueryParamsAxiosConfig(
response,
isVue ?? false,
queryParams,
);

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/getters/discriminators.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SchemasObject } from 'openapi3-ts';
import { ContextSpecs } from '../types';
import { getRefInfo } from './ref';
import { pascal } from "../utils";
import { pascal } from '../utils';

export const resolveDiscriminators = (
schemas: SchemasObject,
Expand All @@ -19,7 +19,7 @@ export const resolveDiscriminators = (
try {
const { originalName } = getRefInfo(mappingValue, context);
// name from getRefInfo may contain a suffix, which we don't want
const name = pascal(originalName)
const name = pascal(originalName);
subTypeSchema = transformedSchemas[name];
} catch (e) {
subTypeSchema = transformedSchemas[mappingValue];
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/getters/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,9 @@ export const getObject = ({
}

return {
value: (item.type === 'object' ? '{ [key: string]: any }' : 'unknown') + nullable,
value:
(item.type === 'object' ? '{ [key: string]: any }' : 'unknown') +
nullable,
imports: [],
schemas: [],
isEnum: false,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/writers/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export const writeSchemas = async ({
if (indexFiles) {
const schemaFilePath = upath.join(schemaPath, '/index.ts');
await fs.ensureFile(schemaFilePath);

// Ensure separate files are used for parallel schema writing.
// Throw an exception, which list all duplicates, before attempting
// multiple writes on the same file.
Expand All @@ -134,7 +134,7 @@ export const writeSchemas = async ({
.join('\n'),
);
}

try {
const data = await fs.readFile(schemaFilePath);

Expand Down
6 changes: 4 additions & 2 deletions packages/query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
"scripts": {
"build": "tsup ./src/index.ts --target node12 --clean --dts",
"dev": "tsup ./src/index.ts --target node12 --clean --watch src",
"lint": "eslint src/**/*.ts"
"lint": "eslint src/**/*.ts",
"test": "vitest"
},
"dependencies": {
"@orval/core": "6.21.0",
"lodash.omitby": "^4.6.0"
"lodash.omitby": "^4.6.0",
"vitest": "^0.34.6"
},
"devDependencies": {
"@types/lodash.omitby": "^4.6.7"
Expand Down
36 changes: 36 additions & 0 deletions packages/query/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { it, expect, describe } from 'vitest';
import { builder } from './index';
import {
GeneratorOptions,
GeneratorVerbOptions,
NormalizedOverrideOutput,
} from '@orval/core';

describe('throws when trying to use named parameters with vue-query client', () => {
it('vue-query builder type', () => {
expect(() =>
builder({ type: 'vue-query' })().client(
{} as GeneratorVerbOptions,
{
override: { useNamedParameters: true } as NormalizedOverrideOutput,
} as GeneratorOptions,
'axios',
),
).toThrowErrorMatchingInlineSnapshot(
'"vue-query client does not support named parameters, and had broken reactivity previously, please set useNamedParameters to false; See for context: https://github.com/anymaniax/orval/pull/931#issuecomment-1752355686"',
);
});
it('vue-query output client', () => {
expect(() =>
builder()().client(
{} as GeneratorVerbOptions,
{
override: { useNamedParameters: true } as NormalizedOverrideOutput,
} as GeneratorOptions,
'vue-query',
),
).toThrowErrorMatchingInlineSnapshot(
'"vue-query client does not support named parameters, and had broken reactivity previously, please set useNamedParameters to false; See for context: https://github.com/anymaniax/orval/pull/931#issuecomment-1752355686"',
);
});
});
18 changes: 16 additions & 2 deletions packages/query/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
jsDoc,
GetterQueryParam,
compareVersions,
getRouteAsArray,
} from '@orval/core';
import omitBy from 'lodash.omitby';
import {
Expand Down Expand Up @@ -401,6 +402,7 @@ const generateQueryRequestFunction = (
isBodyVerb,
hasSignal,
isExactOptionalPropertyTypes,
isVue: isVue(outputClient),
});

let bodyDefinition = body.definition.replace('[]', '\\[\\]');
Expand Down Expand Up @@ -468,6 +470,7 @@ const generateQueryRequestFunction = (
paramsSerializerOptions: override?.paramsSerializerOptions,
isExactOptionalPropertyTypes,
hasSignal,
isVue: isVue(outputClient),
});

const optionsArgs = generateRequestOptionsArguments({
Expand Down Expand Up @@ -1208,10 +1211,12 @@ const generateQueryHook = async (
'implementation',
);

const routeString = `\`${route}\``;
const routeString = isVue(outputClient)
? getRouteAsArray(route) // Note: this is required for reactivity to work, we will lose it if route params are converted into string, only as array they will be tracked // TODO: add tests for this
: `\`${route}\``;

// Note: do not unref() params in Vue - this will make key lose reactivity
const queryKeyFn = `export const ${queryKeyFnName} = (${queryKeyProps}) => {
${isVue(outputClient) ? vueUnRefParams(props) : ''}
return [${routeString}${queryParams ? ', ...(params ? [params]: [])' : ''}${
body.implementation ? `, ${body.implementation}` : ''
}] as const;
Expand Down Expand Up @@ -1496,6 +1501,15 @@ export const builder =
} = {}) =>
() => {
const client: ClientBuilder = (verbOptions, options, outputClient) => {
if (
options.override.useNamedParameters &&
(type === 'vue-query' || outputClient === 'vue-query')
) {
throw new Error(
`vue-query client does not support named parameters, and had broken reactivity previously, please set useNamedParameters to false; See for context: https://github.com/anymaniax/orval/pull/931#issuecomment-1752355686`,
);
}

if (queryOptions) {
const normalizedQueryOptions = normalizeQueryOptions(
queryOptions,
Expand Down
4 changes: 2 additions & 2 deletions samples/react-app-with-swr/src/mock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { setupWorker } from 'msw/browser';
import { getSwaggerPetstoreMSW } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';
import { getSwaggerPetstoreMock } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';

const worker = setupWorker(...getSwaggerPetstoreMSW());
const worker = setupWorker(...getSwaggerPetstoreMock());

worker.start();
4 changes: 2 additions & 2 deletions samples/react-app/src/mock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { setupWorker } from 'msw/browser';
import { getSwaggerPetstoreMSW } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';
import { getSwaggerPetstoreMock } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';

const worker = setupWorker(...getSwaggerPetstoreMSW());
const worker = setupWorker(...getSwaggerPetstoreMock());

worker.start();
4 changes: 2 additions & 2 deletions samples/react-query/basic/src/mock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { setupWorker } from 'msw/browser';
import { getSwaggerPetstoreMSW } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';
import { getSwaggerPetstoreMock } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';

const worker = setupWorker(...getSwaggerPetstoreMSW());
const worker = setupWorker(...getSwaggerPetstoreMock());

worker.start();
4 changes: 2 additions & 2 deletions samples/react-query/custom-client/src/mock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { setupWorker } from 'msw/browser';
import { getSwaggerPetstoreMSW } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';
import { getSwaggerPetstoreMock } from './api/endpoints/petstoreFromFileSpecWithTransformer.msw';

const worker = setupWorker(...getSwaggerPetstoreMSW());
const worker = setupWorker(...getSwaggerPetstoreMock());

worker.start();
Loading

0 comments on commit 1335879

Please sign in to comment.