typedapi-client-helpers 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Builds a typed query object from filter form values, pagination, and sorting.
2
+ * Builds a typed query object from filter form values without adding pagination or sorting.
3
3
  *
4
4
  * Empty filter values are ignored.
5
5
  * List filters are converted item by item.
6
6
  * `OptionValue` lists send their `value` fields instead of the display names.
7
7
  */
8
- export function buildQuery(filters, page = 1, pageSize = 100, sortBy = null, sortDirection) {
9
- const query = filters.reduce((queryResult, filter) => {
8
+ export function buildFilterQuery(filters) {
9
+ return filters.reduce((queryResult, filter) => {
10
10
  const { filterName, filterNameMax, type, value, maxValue, isAList } = filter;
11
11
  if (isEmptyValue(value) && isEmptyValue(maxValue)) {
12
12
  return queryResult;
@@ -28,11 +28,22 @@ export function buildQuery(filters, page = 1, pageSize = 100, sortBy = null, sor
28
28
  if (filterNameMax && !isEmptyValue(maxValue)) {
29
29
  const convertedMaxValue = convertType(type, maxValue);
30
30
  if (convertedMaxValue !== null) {
31
- queryResult[filterNameMax] = convertedMaxValue;
31
+ queryResult[filterNameMax] =
32
+ convertedMaxValue;
32
33
  }
33
34
  }
34
35
  return queryResult;
35
36
  }, {});
37
+ }
38
+ /**
39
+ * Builds a typed query object from filter form values, pagination, and sorting.
40
+ *
41
+ * Empty filter values are ignored.
42
+ * List filters are converted item by item.
43
+ * `OptionValue` lists send their `value` fields instead of the display names.
44
+ */
45
+ export function buildQuery(filters, page = 1, pageSize = 100, sortBy = null, sortDirection) {
46
+ const query = buildFilterQuery(filters);
36
47
  query.pageNumber = page;
37
48
  if (pageSize > 0) {
38
49
  query.pageSize = pageSize;
@@ -1 +1 @@
1
- {"version":3,"file":"buildQuery.js","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"buildQuery.js","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,14 @@ import { FilterFormValues } from "../interfaces/Filter";
5
5
  * APIs often expose sort direction as either a string enum or numeric enum, so both are supported.
6
6
  */
7
7
  export type SortDirection = number | string;
8
+ /**
9
+ * Builds a typed query object from filter form values without adding pagination or sorting.
10
+ *
11
+ * Empty filter values are ignored.
12
+ * List filters are converted item by item.
13
+ * `OptionValue` lists send their `value` fields instead of the display names.
14
+ */
15
+ export declare function buildFilterQuery<TQuery>(filters: FilterFormValues<TQuery>[]): Partial<TQuery>;
8
16
  /**
9
17
  * Builds a typed query object from filter form values, pagination, and sorting.
10
18
  *
@@ -1 +1 @@
1
- {"version":3,"file":"buildQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EACpD,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,EACnC,IAAI,SAAI,EACR,QAAQ,SAAM,EACd,MAAM,GAAE,MAAM,UAAU,GAAG,IAAW,EACtC,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,MAAM,CAAC,CAwDjB"}
1
+ {"version":3,"file":"buildQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EACrC,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,GAClC,OAAO,CAAC,MAAM,CAAC,CAyCjB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EACpD,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,EACnC,IAAI,SAAI,EACR,QAAQ,SAAM,EACd,MAAM,GAAE,MAAM,UAAU,GAAG,IAAW,EACtC,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typedapi-client-helpers",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Reusable typed OpenAPI client helpers.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -19,7 +19,7 @@ export async function generateApi(options) {
19
19
  const source = fs.readFileSync(inputPath, "utf8");
20
20
  const openApi = JSON.parse(source);
21
21
 
22
- validateOpenApiDocument(openApi, { supportedContractVersion: 1 });
22
+ validateOpenApiDocument(openApi, { supportedContractVersion: 2 });
23
23
  const operations = collectOperations(openApi, {
24
24
  generateMissingOperationIds: Boolean(options.generateMissingOperationIds),
25
25
  methodNameStyle: options.methodNameStyle ?? "operationId",
@@ -9,22 +9,38 @@ function createImport(names, from, typeOnly = false) {
9
9
  const cleanNames = unique(names).sort((a, b) => a.localeCompare(b));
10
10
  if (cleanNames.length === 0) return "";
11
11
  const keyword = typeOnly ? "import type" : "import";
12
- if (cleanNames.length <= 3) return `${keyword} { ${cleanNames.join(", ")} } from ${JSON.stringify(from)};`;
12
+ if (cleanNames.length <= 3)
13
+ return `${keyword} { ${cleanNames.join(", ")} } from ${JSON.stringify(from)};`;
13
14
  return `${keyword} {\n${cleanNames.map((name) => ` ${name},`).join("\n")}\n} from ${JSON.stringify(from)};`;
14
15
  }
15
16
 
16
17
  function isPrimitiveType(type) {
17
- return /^(void|any|unknown|string|number|boolean|Blob|File|Record<)/.test(type);
18
+ return /^(void|any|unknown|string|number|boolean|Blob|File|Record<)/.test(
19
+ type,
20
+ );
18
21
  }
19
22
 
20
23
  function extractTopLevelTypeNames(type) {
21
- const withoutLiterals = String(type ?? "").replace(/"(?:\\.|[^"])*"|'(?:\\.|[^'])*'/g, "");
24
+ const withoutLiterals = String(type ?? "").replace(
25
+ /"(?:\\.|[^"])*"|'(?:\\.|[^'])*'/g,
26
+ "",
27
+ );
22
28
  const matches = withoutLiterals.match(/\b[A-Z][A-Za-z0-9_]*\b/g) ?? [];
23
29
  return matches.filter(
24
- (name) => ![
25
- "Array", "Record", "Promise", "HttpResponse", "Blob", "File", "ApiResult",
26
- "RequestParams", "FormData", "ApiClientError", "ApiHttpError",
27
- ].includes(name),
30
+ (name) =>
31
+ ![
32
+ "Array",
33
+ "Record",
34
+ "Promise",
35
+ "HttpResponse",
36
+ "Blob",
37
+ "File",
38
+ "ApiResult",
39
+ "RequestParams",
40
+ "FormData",
41
+ "ApiClientError",
42
+ "ApiHttpError",
43
+ ].includes(name),
28
44
  );
29
45
  }
30
46
 
@@ -38,10 +54,11 @@ function parameterValueExpression(sourceExpression, parameter) {
38
54
 
39
55
  function parameterObjectExpression(sourceExpression, parameters) {
40
56
  const properties = parameters.map(
41
- (parameter) => `${JSON.stringify(parameter.name)}: ${parameterValueExpression(
42
- sourceExpression,
43
- parameter,
44
- )}`,
57
+ (parameter) =>
58
+ `${JSON.stringify(parameter.name)}: ${parameterValueExpression(
59
+ sourceExpression,
60
+ parameter,
61
+ )}`,
45
62
  );
46
63
  return properties.length <= 2
47
64
  ? `{ ${properties.join(", ")} }`
@@ -73,7 +90,9 @@ function pathExpression(routePath, pathParams, inputName = "input") {
73
90
  if (parts.length === 0) return JSON.stringify(routePath);
74
91
 
75
92
  return parts
76
- .map((part) => /^"/.test(part) ? part.slice(1, -1).replace(/`/g, "\\`") : `\${${part}}`)
93
+ .map((part) =>
94
+ /^"/.test(part) ? part.slice(1, -1).replace(/`/g, "\\`") : `\${${part}}`,
95
+ )
77
96
  .join("")
78
97
  .replace(/^/, "`")
79
98
  .replace(/$/, "`");
@@ -83,22 +102,31 @@ function requestFormat(responseContentType, responseType) {
83
102
  if (responseType === "void" || !responseContentType) return undefined;
84
103
  if (responseContentType.includes("json")) return "json";
85
104
  if (responseContentType.startsWith("text/")) return "text";
86
- if (responseContentType === "application/octet-stream" || responseType === "Blob") return "blob";
105
+ if (
106
+ responseContentType === "application/octet-stream" ||
107
+ responseType === "Blob"
108
+ )
109
+ return "blob";
87
110
  return undefined;
88
111
  }
89
112
 
90
113
  function contentTypeEnum(contentType) {
91
114
  switch (contentType) {
92
- case "application/json": return "ContentType.Json";
93
- case "application/vnd.api+json": return "ContentType.JsonApi";
94
- case "multipart/form-data": return "ContentType.FormData";
95
- case "application/x-www-form-urlencoded": return "ContentType.UrlEncoded";
96
- case "text/plain": return "ContentType.Text";
97
- default: return contentType?.includes("json") ? "ContentType.Json" : undefined;
115
+ case "application/json":
116
+ return "ContentType.Json";
117
+ case "application/vnd.api+json":
118
+ return "ContentType.JsonApi";
119
+ case "multipart/form-data":
120
+ return "ContentType.FormData";
121
+ case "application/x-www-form-urlencoded":
122
+ return "ContentType.UrlEncoded";
123
+ case "text/plain":
124
+ return "ContentType.Text";
125
+ default:
126
+ return contentType?.includes("json") ? "ContentType.Json" : undefined;
98
127
  }
99
128
  }
100
129
 
101
-
102
130
  function requestItems(operationInfo, operationTypes, options = {}) {
103
131
  const inputName = options.inputName ?? "input";
104
132
  const items = [
@@ -114,7 +142,11 @@ function requestItems(operationInfo, operationTypes, options = {}) {
114
142
  if (options.queryValueName) {
115
143
  items.push(`query: ${options.queryValueName}`);
116
144
  } else if (operationTypes.hasQueryParams) {
117
- if (!operationTypes.hasPathParams && !operationTypes.hasHeaderParams && !operationTypes.hasCookieParams) {
145
+ if (
146
+ !operationTypes.hasPathParams &&
147
+ !operationTypes.hasHeaderParams &&
148
+ !operationTypes.hasCookieParams
149
+ ) {
118
150
  items.push(`query: ${inputName}`);
119
151
  } else {
120
152
  items.push(
@@ -145,9 +177,13 @@ function requestItems(operationInfo, operationTypes, options = {}) {
145
177
  inputName,
146
178
  operationTypes.parametersByLocation.cookie,
147
179
  );
148
- const cookieCondition = operationTypes.parametersByLocation.cookie
149
- .map((parameter) => `${parameterValueExpression(inputName, parameter)} !== undefined`)
150
- .join(" || ") || "false";
180
+ const cookieCondition =
181
+ operationTypes.parametersByLocation.cookie
182
+ .map(
183
+ (parameter) =>
184
+ `${parameterValueExpression(inputName, parameter)} !== undefined`,
185
+ )
186
+ .join(" || ") || "false";
151
187
  headerSources.push(
152
188
  `${cookieCondition} ? { Cookie: toCookieHeader(${cookiesExpression}) } : undefined`,
153
189
  );
@@ -157,7 +193,10 @@ function requestItems(operationInfo, operationTypes, options = {}) {
157
193
 
158
194
  const type = contentTypeEnum(operationTypes.contentType);
159
195
  if (type) items.push(`type: ${type}`);
160
- const format = requestFormat(operationTypes.responseContentType, operationTypes.responseType);
196
+ const format = requestFormat(
197
+ operationTypes.responseContentType,
198
+ operationTypes.responseType,
199
+ );
161
200
  if (format) items.push(`format: ${JSON.stringify(format)}`);
162
201
  return items;
163
202
  }
@@ -193,14 +232,33 @@ function promiseType(operationTypes) {
193
232
  }
194
233
 
195
234
  function isPaginated(operationTypes) {
196
- return Boolean(operationTypes.paginationMetadata) ||
235
+ return (
236
+ Boolean(operationTypes.paginationMetadata) ||
197
237
  /(?:Api)?Pagination(?:Sort)?Response\b|Paged(?:Response|Result)?\b|Paginated(?:Response|Result)?\b/.test(
198
238
  operationTypes.responseType,
199
- );
239
+ )
240
+ );
241
+ }
242
+
243
+ function isFilterForm(operationTypes) {
244
+ return Boolean(operationTypes.filterFormMetadata);
245
+ }
246
+
247
+ function isPureQueryMethod(operationTypes) {
248
+ return (
249
+ operationTypes.hasQueryParams &&
250
+ !operationTypes.hasPathParams &&
251
+ !operationTypes.bodyType &&
252
+ !operationTypes.hasHeaderParams &&
253
+ !operationTypes.hasCookieParams
254
+ );
200
255
  }
201
256
 
202
257
  function methodDescription(operationInfo, operationTypes) {
203
- const description = operationInfo.operation.description || operationInfo.operation.summary || "No description";
258
+ const description =
259
+ operationInfo.operation.description ||
260
+ operationInfo.operation.summary ||
261
+ "No description";
204
262
  const tags = (operationInfo.operation.tags ?? []).join(", ");
205
263
  return `/**\n * ${description.replace(/\n/g, "\n * ")}\n *\n * @tags ${tags}\n * @name ${operationTypes.methodNameSource}\n * @request ${operationInfo.method}:${operationInfo.routePath}\n */`;
206
264
  }
@@ -214,7 +272,9 @@ function createRequestCall(operationInfo, operationTypes, options = {}) {
214
272
 
215
273
  function createPaginatedMethod(operationInfo, operationTypes, defaultHandlers) {
216
274
  const queryTypeName = operationTypes.parameterTypeNames.query;
217
- const requestCall = createRequestCall(operationInfo, operationTypes, { queryValueName: "builtQuery" });
275
+ const requestCall = createRequestCall(operationInfo, operationTypes, {
276
+ queryValueName: "builtQuery",
277
+ });
218
278
  return `${methodDescription(operationInfo, operationTypes)}
219
279
  export async function ${operationTypes.methodName}(
220
280
  filters: FilterFormValues<${queryTypeName}>[] = [],
@@ -237,13 +297,47 @@ export async function ${operationTypes.methodName}(
237
297
  }`;
238
298
  }
239
299
 
300
+ function createFilterFormMethod(
301
+ operationInfo,
302
+ operationTypes,
303
+ defaultHandlers,
304
+ ) {
305
+ const queryTypeName = operationTypes.parameterTypeNames.query;
306
+ const queryPropertyOptional = operationTypes.allParametersOptional ? "?" : "";
307
+ const filterFormDefault = operationTypes.allParametersOptional ? " = {}" : "";
308
+ const requestCall = createRequestCall(operationInfo, operationTypes, {
309
+ queryValueName: "builtQuery",
310
+ });
311
+
312
+ return `${methodDescription(operationInfo, operationTypes)}
313
+ export async function ${operationTypes.methodName}(
314
+ filterForm: {
315
+ query${queryPropertyOptional}: ${queryTypeName};
316
+ filters?: FilterFormValues<${queryTypeName}>[];
317
+ }${filterFormDefault},
318
+ options: ${optionsType(operationTypes)} = {},
319
+ ): ${promiseType(operationTypes)} {
320
+ const { onSuccess, onError, params = {} } = options;
321
+ const builtQuery = {
322
+ ...(filterForm.query ?? {}),
323
+ ...buildFilterQuery<${queryTypeName}>(filterForm.filters ?? []),
324
+ };
325
+
326
+ return handleApiResponse<${operationTypes.responseType}, ${operationTypes.errorType}>(
327
+ () => ${requestCall},
328
+ ${callbackOptions(operationTypes, defaultHandlers)},
329
+ );
330
+ }`;
331
+ }
332
+
240
333
  function regularParameterArgumentName(operationTypes) {
241
334
  if (operationTypes.hasPathParams) return "pathParams";
242
335
  if (
243
336
  operationTypes.hasQueryParams &&
244
337
  !operationTypes.hasHeaderParams &&
245
338
  !operationTypes.hasCookieParams
246
- ) return "query";
339
+ )
340
+ return "query";
247
341
  return "requestParams";
248
342
  }
249
343
 
@@ -254,7 +348,8 @@ function createRegularMethod(operationInfo, operationTypes, defaultHandlers) {
254
348
  : undefined;
255
349
 
256
350
  if (operationTypes.paramsTypeName) {
257
- const canOmitParams = operationTypes.allParametersOptional && !operationTypes.bodyType;
351
+ const canOmitParams =
352
+ operationTypes.allParametersOptional && !operationTypes.bodyType;
258
353
  args.push(
259
354
  `${parameterArgumentName}: ${operationTypes.paramsTypeName}${canOmitParams ? " = {}" : ""}`,
260
355
  );
@@ -285,15 +380,26 @@ export async function ${operationTypes.methodName}(
285
380
 
286
381
  function createMethod(operationInfo, operationTypes, defaultHandlers, options) {
287
382
  if (
288
- operationTypes.hasQueryParams &&
289
- !operationTypes.hasPathParams &&
290
- !operationTypes.bodyType &&
291
- !operationTypes.hasHeaderParams &&
292
- !operationTypes.hasCookieParams &&
383
+ isPureQueryMethod(operationTypes) &&
293
384
  options.useFilterFormValues !== false &&
294
385
  isPaginated(operationTypes)
295
386
  ) {
296
- return createPaginatedMethod(operationInfo, operationTypes, defaultHandlers);
387
+ return createPaginatedMethod(
388
+ operationInfo,
389
+ operationTypes,
390
+ defaultHandlers,
391
+ );
392
+ }
393
+ if (
394
+ isPureQueryMethod(operationTypes) &&
395
+ options.useFilterFormValues !== false &&
396
+ isFilterForm(operationTypes)
397
+ ) {
398
+ return createFilterFormMethod(
399
+ operationInfo,
400
+ operationTypes,
401
+ defaultHandlers,
402
+ );
297
403
  }
298
404
  return createRegularMethod(operationInfo, operationTypes, defaultHandlers);
299
405
  }
@@ -311,28 +417,43 @@ export function controllerNameForOperation(operationInfo, options = {}) {
311
417
  return pascalCase(parts[1] ?? parts[0] ?? "Default", "Default");
312
418
  }
313
419
 
314
- export function generateMethodFile(openApi, controllerName, operations, options = {}) {
420
+ export function generateMethodFile(
421
+ openApi,
422
+ controllerName,
423
+ operations,
424
+ options = {},
425
+ ) {
315
426
  const dataContractImports = [];
316
427
  const helperTypeImports = ["ApiResult", "ApiMethodOptions"];
317
428
  const helperValueImports = ["handleApiResponse"];
318
429
  const methods = [];
319
430
  let needsContentType = false;
320
431
  let needsPaginationTypes = false;
321
- let needsHeaderHelpers = false;
432
+ let needsFilterFormTypes = false;
433
+ let needsHeaderParams = false;
434
+ let needsCookieParams = false;
322
435
 
323
436
  for (const operationInfo of operations) {
324
437
  const operationTypes = getOperationTypes(openApi, operationInfo, options);
325
438
 
326
- for (const typeName of Object.values(operationTypes.parameterTypeNames)) dataContractImports.push(typeName);
327
- if (operationTypes.paramsTypeName) dataContractImports.push(operationTypes.paramsTypeName);
439
+ for (const typeName of Object.values(operationTypes.parameterTypeNames))
440
+ dataContractImports.push(typeName);
441
+ if (operationTypes.paramsTypeName)
442
+ dataContractImports.push(operationTypes.paramsTypeName);
328
443
  if (operationTypes.bodyType && !isPrimitiveType(operationTypes.bodyType)) {
329
- dataContractImports.push(...extractTopLevelTypeNames(operationTypes.bodyType));
444
+ dataContractImports.push(
445
+ ...extractTopLevelTypeNames(operationTypes.bodyType),
446
+ );
330
447
  }
331
448
  if (!isPrimitiveType(operationTypes.responseType)) {
332
- dataContractImports.push(...extractTopLevelTypeNames(operationTypes.responseType));
449
+ dataContractImports.push(
450
+ ...extractTopLevelTypeNames(operationTypes.responseType),
451
+ );
333
452
  }
334
453
  if (!isPrimitiveType(operationTypes.errorType)) {
335
- dataContractImports.push(...extractTopLevelTypeNames(operationTypes.errorType));
454
+ dataContractImports.push(
455
+ ...extractTopLevelTypeNames(operationTypes.errorType),
456
+ );
336
457
  }
337
458
  if (operationTypes.usesHttpErrorFallback) {
338
459
  helperTypeImports.push("ApiHttpError");
@@ -340,36 +461,78 @@ export function generateMethodFile(openApi, controllerName, operations, options
340
461
  }
341
462
 
342
463
  if (contentTypeEnum(operationTypes.contentType)) needsContentType = true;
343
- if (operationTypes.hasHeaderParams || operationTypes.hasCookieParams) needsHeaderHelpers = true;
464
+ if (operationTypes.hasHeaderParams) needsHeaderParams = true;
465
+ if (operationTypes.hasCookieParams) needsCookieParams = true;
344
466
  if (
345
- operationTypes.hasQueryParams &&
346
- !operationTypes.hasPathParams && !operationTypes.bodyType &&
347
- !operationTypes.hasHeaderParams && !operationTypes.hasCookieParams &&
348
- options.useFilterFormValues !== false && isPaginated(operationTypes)
467
+ isPureQueryMethod(operationTypes) &&
468
+ options.useFilterFormValues !== false &&
469
+ isPaginated(operationTypes)
349
470
  ) {
350
471
  needsPaginationTypes = true;
472
+ } else if (
473
+ isPureQueryMethod(operationTypes) &&
474
+ options.useFilterFormValues !== false &&
475
+ isFilterForm(operationTypes)
476
+ ) {
477
+ needsFilterFormTypes = true;
351
478
  }
352
479
 
353
- methods.push(createMethod(operationInfo, operationTypes, options.defaultHandlers, options));
480
+ methods.push(
481
+ createMethod(
482
+ operationInfo,
483
+ operationTypes,
484
+ options.defaultHandlers,
485
+ options,
486
+ ),
487
+ );
354
488
  }
355
489
 
356
- if (needsHeaderHelpers) helperValueImports.push("mergeHeaders", "toCookieHeader", "toRequestHeaders");
490
+ if (needsHeaderParams || needsCookieParams)
491
+ helperValueImports.push("mergeHeaders");
492
+ if (needsHeaderParams) helperValueImports.push("toRequestHeaders");
493
+ if (needsCookieParams) helperValueImports.push("toCookieHeader");
357
494
  if (needsPaginationTypes) {
358
495
  helperValueImports.push("buildQuery");
359
496
  helperTypeImports.push(
360
- "ExtractDataIfPaginated", "FilterFormValues", "SortableKeys", "SortDirection", "UnwrapArray",
497
+ "ExtractDataIfPaginated",
498
+ "FilterFormValues",
499
+ "SortableKeys",
500
+ "SortDirection",
501
+ "UnwrapArray",
361
502
  );
362
503
  }
504
+ if (needsFilterFormTypes) {
505
+ helperValueImports.push("buildFilterQuery");
506
+ helperTypeImports.push("FilterFormValues");
507
+ }
363
508
 
364
509
  const useTypeOnlyImports = options.useTypeOnlyImports !== false;
365
510
  const defaultHandlers = options.defaultHandlers;
366
511
  const imports = [
367
512
  generatedFileHeader(),
368
- createImport(["request", ...(needsContentType ? ["ContentType"] : [])], "../generated/http-client"),
369
- createImport(["RequestParams"], "../generated/http-client", useTypeOnlyImports),
370
- createImport(dataContractImports, "../generated/data-contracts", useTypeOnlyImports),
371
- createImport(helperValueImports, options.runtimePackageName ?? "typedapi-client-helpers"),
372
- createImport(helperTypeImports, options.runtimePackageName ?? "typedapi-client-helpers", useTypeOnlyImports),
513
+ createImport(
514
+ ["request", ...(needsContentType ? ["ContentType"] : [])],
515
+ "../generated/http-client",
516
+ ),
517
+ createImport(
518
+ ["RequestParams"],
519
+ "../generated/http-client",
520
+ useTypeOnlyImports,
521
+ ),
522
+ createImport(
523
+ dataContractImports,
524
+ "../generated/data-contracts",
525
+ useTypeOnlyImports,
526
+ ),
527
+ createImport(
528
+ helperValueImports,
529
+ options.runtimePackageName ?? "typedapi-client-helpers",
530
+ ),
531
+ createImport(
532
+ helperTypeImports,
533
+ options.runtimePackageName ?? "typedapi-client-helpers",
534
+ useTypeOnlyImports,
535
+ ),
373
536
  defaultHandlers
374
537
  ? `import { ${defaultHandlers.success} as typedApiDefaultSuccessHandler, ${defaultHandlers.error} as typedApiDefaultErrorHandler, ${defaultHandlers.errorMessage} as typedApiDefaultErrorMessage } from ${JSON.stringify(defaultHandlers.path)};`
375
538
  : "",