@povio/openapi-codegen-cli 3.0.0-rc.1 → 3.0.0-rc.3

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.
package/README.md CHANGED
@@ -92,7 +92,10 @@ yarn openapi-codegen generate --config my-config.ts
92
92
  --axiosRequestConfig Include Axios request config parameters in query hooks (default: false)
93
93
  --infiniteQueries Generate infinite queries for paginated API endpoints (default: false)
94
94
  --mutationEffects Add mutation effects options to mutation hooks (default: true)
95
- --mutationScope Serialize mutations for the same path-param resource via TanStack scope.id (default: false)
95
+ --mutationScope Serialize mutations for the same path-param resource via TanStack scope.id (default: false).
96
+ In config files also accepts { include: string[] } or { exclude: string[] } to opt specific
97
+ operations in/out of scoping. Use "Tag/operationId" format for precision (e.g. "EmployeeSettings/update")
98
+ or just "operationId" to match across all tags. Cannot specify both include and exclude.
96
99
  --mutationDefaultOnError Use OpenApiQueryConfig.onError as the default onError for mutation hooks (default: false)
97
100
  --workspaceContext Comma-separated list of path/ACL params that generated hooks may resolve from OpenApiWorkspaceContext
98
101
  --inlineEndpoints Inline endpoint implementations into generated query files (default: false)
@@ -1,4 +1,4 @@
1
- import { t as GenerateOptions } from "./options-C6CNQ6tq.mjs";
1
+ import { t as GenerateOptions } from "./options-saKmD8s1.mjs";
2
2
 
3
3
  //#region src/generators/types/config.d.ts
4
4
  type OpenAPICodegenConfig = Partial<GenerateOptions>;
@@ -1,4 +1,4 @@
1
- import { S as Profiler, h as deepMerge, i as writeGenerateFileData, p as DEFAULT_GENERATE_OPTIONS, r as removeStaleGeneratedFiles, t as generateCodeFromOpenAPIDoc } from "./generateCodeFromOpenAPIDoc-BKIXvJIW.mjs";
1
+ import { S as Profiler, h as deepMerge, i as writeGenerateFileData, p as DEFAULT_GENERATE_OPTIONS, r as removeStaleGeneratedFiles, t as generateCodeFromOpenAPIDoc } from "./generateCodeFromOpenAPIDoc-D-UDIQX5.mjs";
2
2
  import path from "path";
3
3
  import SwaggerParser from "@apidevtools/swagger-parser";
4
4
 
@@ -1717,12 +1717,26 @@ function getAclImports({ tag, endpoints, options }) {
1717
1717
  options
1718
1718
  });
1719
1719
  }
1720
+ function normalizeOutputPath(output) {
1721
+ return output.replace(/\\/g, "/").replace(/\/$/, "");
1722
+ }
1723
+ function outputMatchesTsPath(options) {
1724
+ const normalizedOutput = normalizeOutputPath(options.output);
1725
+ if (options.tsPath.startsWith("@/")) {
1726
+ const physicalPath = `src/${options.tsPath.slice(2)}`;
1727
+ return normalizedOutput === physicalPath || normalizedOutput.endsWith(`/${physicalPath}`);
1728
+ }
1729
+ return normalizedOutput === options.tsPath;
1730
+ }
1731
+ function shouldUseRelativeImports(options) {
1732
+ return options.importPath === "ts" && options.tsPath === "@/data" && !outputMatchesTsPath(options);
1733
+ }
1720
1734
  function getImportPath(options, fromRoot = false) {
1721
- let importPath = options.tsPath;
1722
- if (options.importPath === "relative") importPath = fromRoot ? "./" : "../";
1723
- else if (options.importPath === "absolute") importPath = options.output;
1724
- else if (new RegExp(`${TEMPLATE_DATA_FILE_PATH}`, "g").test(options.output)) importPath = options.output.replace(new RegExp(`.*${TEMPLATE_DATA_FILE_PATH}`, "g"), options.tsPath);
1725
- return `${importPath}/`.replace(/\/\//g, "/");
1735
+ if (options.importPath === "relative") return `${fromRoot ? "./" : "../"}`.replace(/\/\//g, "/");
1736
+ if (options.importPath === "absolute") return `${options.output}/`.replace(/\/\//g, "/");
1737
+ if (new RegExp(`${TEMPLATE_DATA_FILE_PATH}`, "g").test(options.output)) return `${options.output.replace(new RegExp(`.*${TEMPLATE_DATA_FILE_PATH}`, "g"), options.tsPath)}/`.replace(/\/\//g, "/");
1738
+ if (shouldUseRelativeImports(options)) return `${fromRoot ? "./" : "../"}`.replace(/\/\//g, "/");
1739
+ return `${options.tsPath}/`.replace(/\/\//g, "/");
1726
1740
  }
1727
1741
  function getImports({ type = GenerateType.Models, tag: currentTag, entities, getTag, getEntityName, options }) {
1728
1742
  const imports = /* @__PURE__ */ new Map();
@@ -2207,9 +2221,16 @@ function getEndpointBody({ resolver, operation, operationName, isUniqueOperation
2207
2221
  };
2208
2222
  }
2209
2223
 
2224
+ //#endregion
2225
+ //#region src/generators/utils/query-filter-component-names.utils.ts
2226
+ function resolveQueryFilterComponentName(operationId, queryFilterComponentNames) {
2227
+ if (!operationId || !queryFilterComponentNames) return;
2228
+ return queryFilterComponentNames[operationId];
2229
+ }
2230
+
2210
2231
  //#endregion
2211
2232
  //#region src/generators/core/endpoints/getEndpointParameter.ts
2212
- function getEndpointParameter({ resolver, param, operationName, isUniqueOperationName, tag }) {
2233
+ function getEndpointParameter({ resolver, param, operationName, operationId, isUniqueOperationName, tag }) {
2213
2234
  const paramObj = resolver.resolveObject(param);
2214
2235
  if (!ALLOWED_PATH_IN.includes(paramObj.in)) return;
2215
2236
  let schema = {};
@@ -2222,7 +2243,8 @@ function getEndpointParameter({ resolver, param, operationName, isUniqueOperatio
2222
2243
  schema = mediaTypeObject?.schema ?? mediaTypeObject;
2223
2244
  } else if (paramObj.schema) schema = paramObj.schema;
2224
2245
  if (resolver.options.withDescription && schema) schema.description = (paramObj.description ?? "").trim();
2225
- const fallbackName = getParamZodSchemaName(getZodSchemaOperationName(operationName, isUniqueOperationName, tag), paramObj.name);
2246
+ const zodSchemaOperationName = getZodSchemaOperationName(operationName, isUniqueOperationName, tag);
2247
+ const fallbackName = (paramObj.name === resolver.options.filterParamName && !isReferenceObject(schema) && resolver.options.queryFilterComponentNames ? resolveQueryFilterComponentName(operationId, resolver.options.queryFilterComponentNames) : void 0) ?? getParamZodSchemaName(zodSchemaOperationName, paramObj.name);
2226
2248
  let parameterSortingEnumSchemaName = void 0;
2227
2249
  if (isSortingParameterObject(paramObj)) {
2228
2250
  const enumZodSchemaName = getEnumZodSchemaName(fallbackName, resolver.options.enumSuffix, resolver.options.schemaSuffix);
@@ -2321,6 +2343,7 @@ function getEndpointsFromOpenAPIDoc(resolver) {
2321
2343
  resolver,
2322
2344
  param,
2323
2345
  operationName,
2346
+ operationId: operation.operationId,
2324
2347
  isUniqueOperationName,
2325
2348
  tag
2326
2349
  });
@@ -4034,6 +4057,10 @@ function renderModelJsDocs({ name, zodSchema, tag, resolver }) {
4034
4057
  const endpointParamMappingCache = /* @__PURE__ */ new WeakMap();
4035
4058
  function generateQueries(params) {
4036
4059
  const { resolver, data, tag } = params;
4060
+ const mutationScopeOption = resolver.options.mutationScope;
4061
+ if (mutationScopeOption && typeof mutationScopeOption === "object") {
4062
+ if ("include" in mutationScopeOption && "exclude" in mutationScopeOption) throw new Error("mutationScope cannot specify both 'include' and 'exclude'");
4063
+ }
4037
4064
  const inlineEndpoints = shouldInlineEndpointsForTag(tag, resolver.options);
4038
4065
  const endpoints = data.get(tag)?.endpoints;
4039
4066
  if (!endpoints || endpoints.length === 0) return;
@@ -4541,6 +4568,27 @@ function renderMutation({ resolver, endpoint, inlineEndpoints, precomputed }) {
4541
4568
  const destructuredVariables = precomputed?.destructuredVariables ?? getDestructuredVariables(resolver, endpoint, updateQueryEndpoints);
4542
4569
  const hasMutationFnBody = endpoint.mediaUpload || hasAclCheck || Object.keys(workspaceParamReplacements).length > 0;
4543
4570
  const mutationVariablesType = endpoint.mediaUpload ? `${endpointParams}${endpointParams ? "; " : ""}abortController?: AbortController; onUploadProgress?: (progress: { loaded: number; total: number }) => void` : endpointParams;
4571
+ const isPost = endpoint.method === "post";
4572
+ const mutationScopeOption = resolver.options.mutationScope;
4573
+ const operationId = getEndpointName(endpoint);
4574
+ const scopeMatchKey = `${tag}/${operationId}`;
4575
+ let scopeEnabled = false;
4576
+ if (!isPost && mutationScopeOption) {
4577
+ if (mutationScopeOption === true) scopeEnabled = true;
4578
+ else if (typeof mutationScopeOption === "object" && "include" in mutationScopeOption) scopeEnabled = mutationScopeOption.include.some((id) => id === operationId || id === scopeMatchKey);
4579
+ else if (typeof mutationScopeOption === "object" && "exclude" in mutationScopeOption) scopeEnabled = !mutationScopeOption.exclude.some((id) => id === operationId || id === scopeMatchKey);
4580
+ }
4581
+ const scopePathParams = scopeEnabled ? mapEndpointParamsToFunctionParams(resolver, endpoint, {}).filter((p) => p.paramType === "Path") : [];
4582
+ const isScoped = scopePathParams.length > 0;
4583
+ const nonPathEndpointParams = isScoped ? renderEndpointParams(resolver, endpoint, {
4584
+ includeFileParam: true,
4585
+ optionalPathParams: resolver.options.workspaceContext,
4586
+ modelNamespaceTag: tag,
4587
+ excludePathParams: true
4588
+ }) : endpointParams;
4589
+ const nonPathMutationVariablesType = isScoped ? endpoint.mediaUpload ? `${nonPathEndpointParams}${nonPathEndpointParams ? "; " : ""}abortController?: AbortController; onUploadProgress?: (progress: { loaded: number; total: number }) => void` : nonPathEndpointParams : mutationVariablesType;
4590
+ const pathParamFirstArg = isScoped ? `{ ${scopePathParams.map((p) => p.name).join(", ")} }: { ${scopePathParams.map((p) => `${p.name}: ${p.type}`).join("; ")} }, ` : "";
4591
+ const mutationOptionsTypeArg = isScoped ? nonPathMutationVariablesType ? `, { ${nonPathMutationVariablesType} }` : "" : `, { ${mutationVariablesType} }`;
4544
4592
  const lines = [];
4545
4593
  lines.push(renderQueryJsDocs({
4546
4594
  resolver,
@@ -4548,7 +4596,7 @@ function renderMutation({ resolver, endpoint, inlineEndpoints, precomputed }) {
4548
4596
  mode: "mutation",
4549
4597
  tag
4550
4598
  }));
4551
- lines.push(`export const ${getQueryName(endpoint, true)} = (options?: AppMutationOptions<typeof ${endpointFunction}, { ${mutationVariablesType} }>${hasMutationEffects ? ` & ${MUTATION_EFFECTS.optionsType}` : ""}${hasAxiosRequestConfig ? `, ${AXIOS_REQUEST_CONFIG_NAME}?: ${AXIOS_REQUEST_CONFIG_TYPE}` : ""}) => {`);
4599
+ lines.push(`export const ${getQueryName(endpoint, true)} = (${pathParamFirstArg}options?: AppMutationOptions<typeof ${endpointFunction}${mutationOptionsTypeArg}>${hasMutationEffects ? ` & ${MUTATION_EFFECTS.optionsType}` : ""}${hasAxiosRequestConfig ? `, ${AXIOS_REQUEST_CONFIG_NAME}?: ${AXIOS_REQUEST_CONFIG_TYPE}` : ""}) => {`);
4552
4600
  if (hasMutationDefaultOnError) lines.push(" const queryConfig = OpenApiQueryConfig.useConfig();");
4553
4601
  if (hasAclCheck) lines.push(` const { checkAcl } = ${ACL_CHECK_HOOK}();`);
4554
4602
  lines.push(...renderWorkspaceContextDestructure({
@@ -4559,7 +4607,13 @@ function renderMutation({ resolver, endpoint, inlineEndpoints, precomputed }) {
4559
4607
  if (hasMutationEffects) lines.push(` const { runMutationEffects } = useMutationEffects<typeof ${QUERY_MODULE_ENUM}.${tag}>({ currentModule: ${QUERIES_MODULE_NAME} });`);
4560
4608
  lines.push("");
4561
4609
  lines.push(` return ${QUERY_HOOKS.mutation}({`);
4562
- const mutationFnArg = endpointParams ? `{ ${destructuredMutationArgs}${endpoint.mediaUpload ? `${destructuredMutationArgs ? ", " : ""}abortController, onUploadProgress` : ""} }` : "";
4610
+ const nonPathDestructuredArgs = isScoped ? renderEndpointArgs(resolver, endpoint, {
4611
+ includeFileParam: true,
4612
+ excludePathParams: true
4613
+ }) : destructuredMutationArgs;
4614
+ const effectiveParams = isScoped ? nonPathEndpointParams : endpointParams;
4615
+ const effectiveArgs = isScoped ? nonPathDestructuredArgs : destructuredMutationArgs;
4616
+ const mutationFnArg = effectiveParams || endpoint.mediaUpload ? `{ ${effectiveArgs}${endpoint.mediaUpload ? `${effectiveArgs ? ", " : ""}abortController, onUploadProgress` : ""} }` : "";
4563
4617
  lines.push(` mutationFn: ${endpoint.mediaUpload ? "async " : ""}(${mutationFnArg}) => ${hasMutationFnBody ? "{ " : ""}`);
4564
4618
  lines.push(...renderWorkspaceParamCoalescing({
4565
4619
  replacements: workspaceParamReplacements,
@@ -4596,12 +4650,18 @@ function renderMutation({ resolver, endpoint, inlineEndpoints, precomputed }) {
4596
4650
  } else lines.push(` ${hasMutationFnBody ? "return " : ""}${endpointFunction}(${resolvedEndpointArgs}${hasAxiosRequestConfig ? `${resolvedEndpointArgs ? ", " : ""}${AXIOS_REQUEST_CONFIG_NAME}` : ""})`);
4597
4651
  if (hasMutationFnBody) lines.push(" },");
4598
4652
  else lines.push(",");
4653
+ if (isScoped) {
4654
+ const scopePathParamInterpolations = scopePathParams.map((p) => `:\${${p.name}}`).join("");
4655
+ lines.push(` scope: { id: \`${getEndpointName(endpoint)}${scopePathParamInterpolations}\` },`);
4656
+ }
4599
4657
  lines.push(" ...options,");
4600
4658
  if (hasMutationDefaultOnError) lines.push(" onError: options?.onError ?? queryConfig.onError,");
4601
4659
  if (hasMutationEffects) {
4602
4660
  lines.push(" onSuccess: async (resData, variables, onMutateResult, context) => {");
4603
4661
  if (updateQueryEndpoints.length > 0) {
4604
- if (destructuredVariables.length > 0) lines.push(` const { ${destructuredVariables.join(", ")} } = variables;`);
4662
+ const scopedPathParamNames = new Set(scopePathParams.map((p) => p.name));
4663
+ const variablesDestructure = destructuredVariables.filter((v) => !scopedPathParamNames.has(v));
4664
+ if (variablesDestructure.length > 0) lines.push(` const { ${variablesDestructure.join(", ")} } = variables;`);
4605
4665
  lines.push(...renderWorkspaceParamCoalescing({
4606
4666
  replacements: workspaceParamReplacements,
4607
4667
  indent: " "
@@ -1,4 +1,4 @@
1
- import { n as GenerateFileData, t as GenerateOptions } from "./options-C6CNQ6tq.mjs";
1
+ import { n as GenerateFileData, t as GenerateOptions } from "./options-saKmD8s1.mjs";
2
2
  import { OpenAPIV3 } from "openapi-types";
3
3
 
4
4
  //#region src/generators/types/metadata.d.ts
@@ -1,4 +1,4 @@
1
- import { _ as getNamespaceName, a as getDataFromOpenAPIDoc, b as isParamMediaTypeAllowed, c as getSchemaTsMetaType, d as getTagImportPath, f as getQueryName, g as invalidVariableNameCharactersToCamel, l as getTsTypeBase, o as isMutation, p as DEFAULT_GENERATE_OPTIONS, s as isQuery, t as generateCodeFromOpenAPIDoc, v as GenerateType, x as formatTag, y as isMediaTypeAllowed } from "./generateCodeFromOpenAPIDoc-BKIXvJIW.mjs";
1
+ import { _ as getNamespaceName, a as getDataFromOpenAPIDoc, b as isParamMediaTypeAllowed, c as getSchemaTsMetaType, d as getTagImportPath, f as getQueryName, g as invalidVariableNameCharactersToCamel, l as getTsTypeBase, o as isMutation, p as DEFAULT_GENERATE_OPTIONS, s as isQuery, t as generateCodeFromOpenAPIDoc, v as GenerateType, x as formatTag, y as isMediaTypeAllowed } from "./generateCodeFromOpenAPIDoc-D-UDIQX5.mjs";
2
2
  import SwaggerParser from "@apidevtools/swagger-parser";
3
3
 
4
4
  //#region src/generators/core/getMetadataFromOpenAPIDoc.ts
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { a as GeneralErrorCodes, i as ErrorHandlerOptions, n as ErrorEntry, o as SharedErrorHandler, r as ErrorHandler, t as ApplicationException } from "./error-handling-CvW_FecB.mjs";
2
- import "./options-C6CNQ6tq.mjs";
3
- import { t as OpenAPICodegenConfig } from "./config-CKmoJbQB.mjs";
2
+ import "./options-saKmD8s1.mjs";
3
+ import { t as OpenAPICodegenConfig } from "./config-1XCOTZ4a.mjs";
4
4
  import { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosResponseHeaders, CreateAxiosDefaults } from "axios";
5
5
  import { z } from "zod";
6
6
  import "i18next";
@@ -42,7 +42,11 @@ interface QueriesGenerateOptions {
42
42
  mutationDefaultOnError?: boolean;
43
43
  workspaceContext?: string[];
44
44
  prefetchQueries?: boolean;
45
- mutationScope?: boolean;
45
+ mutationScope?: boolean | {
46
+ include: string[];
47
+ } | {
48
+ exclude: string[];
49
+ };
46
50
  }
47
51
  interface InfiniteQueriesGenerateOptions {
48
52
  infiniteQueries?: boolean;
@@ -68,6 +72,13 @@ interface BuilderConfigsGenerateOptions {
68
72
  dynamicInputsImportPath: string;
69
73
  dynamicColumnsImportPath: string;
70
74
  }
75
+ interface QueryFilterComponentNameOptions {
76
+ /**
77
+ * Optional map of OpenAPI operationId to stable filter schema names.
78
+ * Used for inline `filter` query objects when migrating away from named filter DTO refs.
79
+ */
80
+ queryFilterComponentNames?: Record<string, string>;
81
+ }
71
82
  interface GenerateConfig {
72
83
  outputFileNameSuffix: string;
73
84
  namespaceSuffix: string;
@@ -78,6 +89,8 @@ interface BaseGenerateOptions {
78
89
  clearOutput?: boolean;
79
90
  incremental?: boolean;
80
91
  splitByTags: boolean;
92
+ /** When true, non-default tags emit proxy models that re-export from CommonModels. */
93
+ modelsInCommon?: boolean;
81
94
  defaultTag: string;
82
95
  includeTags: string[];
83
96
  excludeTags: string[];
@@ -91,6 +104,6 @@ interface BaseGenerateOptions {
91
104
  modelsOnly?: boolean;
92
105
  standalone?: boolean;
93
106
  }
94
- interface GenerateOptions extends BaseGenerateOptions, ZodGenerateOptions, EndpointsGenerateOptions, QueriesGenerateOptions, InfiniteQueriesGenerateOptions, ACLGenerateOptions, BuilderConfigsGenerateOptions {}
107
+ interface GenerateOptions extends BaseGenerateOptions, ZodGenerateOptions, EndpointsGenerateOptions, QueriesGenerateOptions, InfiniteQueriesGenerateOptions, ACLGenerateOptions, BuilderConfigsGenerateOptions, QueryFilterComponentNameOptions {}
95
108
  //#endregion
96
109
  export { GenerateFileData as n, GenerateFileFormatter as r, GenerateOptions as t };
package/dist/sh.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { C as VALIDATION_ERROR_TYPE_TITLE, S as Profiler, a as getDataFromOpenAPIDoc, m as groupByType, n as getOutputFileName, u as getTagFileName, v as GenerateType } from "./generateCodeFromOpenAPIDoc-BKIXvJIW.mjs";
3
- import { n as resolveConfig, t as runGenerate } from "./generate.runner-B0iop_CE.mjs";
2
+ import { C as VALIDATION_ERROR_TYPE_TITLE, S as Profiler, a as getDataFromOpenAPIDoc, m as groupByType, n as getOutputFileName, u as getTagFileName, v as GenerateType } from "./generateCodeFromOpenAPIDoc-D-UDIQX5.mjs";
3
+ import { n as resolveConfig, t as runGenerate } from "./generate.runner-CioDqx6u.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import yargs from "yargs";
6
6
  import { hideBin } from "yargs/helpers";
@@ -39,7 +39,7 @@ function logBanner(message) {
39
39
  * Fetch the version from package.json
40
40
  */
41
41
  function getVersion() {
42
- return "3.0.0-rc.1";
42
+ return "3.0.0-rc.3";
43
43
  }
44
44
 
45
45
  //#endregion
package/dist/vite.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { r as GenerateFileFormatter } from "./options-C6CNQ6tq.mjs";
2
- import { t as OpenAPICodegenConfig } from "./config-CKmoJbQB.mjs";
1
+ import { r as GenerateFileFormatter } from "./options-saKmD8s1.mjs";
2
+ import { t as OpenAPICodegenConfig } from "./config-1XCOTZ4a.mjs";
3
3
  import { Plugin } from "vite";
4
4
 
5
5
  //#region src/vite/openapi-codegen.plugin.d.ts
package/dist/vite.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { S as Profiler } from "./generateCodeFromOpenAPIDoc-BKIXvJIW.mjs";
2
- import { t as runGenerate } from "./generate.runner-B0iop_CE.mjs";
1
+ import { S as Profiler } from "./generateCodeFromOpenAPIDoc-D-UDIQX5.mjs";
2
+ import { t as runGenerate } from "./generate.runner-CioDqx6u.mjs";
3
3
  import path from "path";
4
4
 
5
5
  //#region src/vite/openapi-codegen.plugin.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@povio/openapi-codegen-cli",
3
- "version": "3.0.0-rc.1",
3
+ "version": "3.0.0-rc.3",
4
4
  "keywords": [
5
5
  "codegen",
6
6
  "openapi",