vite-plugin-openapi-codegen 3.2.0 → 3.2.1

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/dist/cli.mjs CHANGED
@@ -268,7 +268,49 @@ function collectOperations(spec, pathPrefix = "/api/", stripPrefix = true) {
268
268
  });
269
269
  }
270
270
  }
271
- return entries;
271
+ return excludeInternalOperations(entries, spec);
272
+ }
273
+ function excludeInternalOperations(entries, spec) {
274
+ const securitySchemes = spec.components?.securitySchemes;
275
+ if (!securitySchemes) return entries;
276
+ return entries.filter((entry) => readSecurityRequirement(entry, securitySchemes, spec.security)?.kind !== "internal");
277
+ }
278
+ function readSecurityRequirement(entry, securitySchemes, topLevelSecurity) {
279
+ const security = entry.operation.security ?? topLevelSecurity;
280
+ if (security === void 0) return null;
281
+ if (!Array.isArray(security)) throw new Error(`Operation "${entry.operationId}" has invalid security`);
282
+ if (security.length === 0) return { kind: "public" };
283
+ if (security.length > 1) throw new Error(`Operation "${entry.operationId}" declares ${security.length} security requirements; the backend contract emits at most one`);
284
+ const requirement = security[0];
285
+ if (!isRecord(requirement)) throw new Error(`Operation "${entry.operationId}" has an invalid security requirement`);
286
+ const schemeEntries = Object.entries(requirement);
287
+ if (schemeEntries.length > 1) throw new Error(`Operation "${entry.operationId}" declares ${schemeEntries.length} schemes in one security requirement; the backend contract emits exactly one`);
288
+ const schemeEntry = schemeEntries[0];
289
+ if (schemeEntry) {
290
+ const [schemeName, scopes] = schemeEntry;
291
+ const scheme = securitySchemes?.[schemeName];
292
+ if (scheme?.type === "apiKey" && scheme.in === "header") return { kind: "internal" };
293
+ if (scheme?.type === "http" || scheme?.type === "apiKey" && scheme.in === "cookie") {
294
+ const roles = readSecurityScopes(entry, schemeName, scopes);
295
+ return roles.length === 0 ? { kind: "authenticated" } : {
296
+ kind: "role",
297
+ roles
298
+ };
299
+ }
300
+ }
301
+ throw new Error(`Operation "${entry.operationId}" has an unrecognized security scheme`);
302
+ }
303
+ function readSecurityScopes(entry, schemeName, scopes) {
304
+ if (!Array.isArray(scopes)) throw new Error(`Operation "${entry.operationId}" has non-array scopes for security scheme "${schemeName}"`);
305
+ const roles = [];
306
+ for (const scope of scopes) {
307
+ if (typeof scope !== "string") throw new Error(`Operation "${entry.operationId}" has a non-string scope for security scheme "${schemeName}"`);
308
+ roles.push(scope);
309
+ }
310
+ return roles;
311
+ }
312
+ function isRecord(value) {
313
+ return typeof value === "object" && value !== null && !Array.isArray(value);
272
314
  }
273
315
  function getEffectiveParametersByLocation(entry, location) {
274
316
  return (entry.operation.parameters ?? []).filter((parameter) => getEffectiveParameterLocation(entry.apiPath, parameter) === location);
@@ -662,29 +704,6 @@ function createAccessPolicyEntries(operations, securitySchemes, topLevelSecurity
662
704
  }];
663
705
  });
664
706
  }
665
- function readSecurityRequirement(entry, securitySchemes, topLevelSecurity) {
666
- const security = entry.operation.security ?? topLevelSecurity;
667
- if (security === void 0) return null;
668
- if (!Array.isArray(security)) throw new Error(`Operation "${entry.operationId}" has invalid security`);
669
- if (security.length === 0) return { kind: "public" };
670
- const requirement = security[0];
671
- if (!isRecord(requirement)) throw new Error(`Operation "${entry.operationId}" has an invalid security requirement`);
672
- for (const [schemeName, scopes] of Object.entries(requirement)) {
673
- const scheme = securitySchemes?.[schemeName];
674
- if (scheme?.type === "apiKey" && scheme.in === "header") return { kind: "internal" };
675
- if (scheme?.type === "http" || scheme?.type === "apiKey" && scheme.in === "cookie") {
676
- const roles = Array.isArray(scopes) ? scopes.filter((scope) => typeof scope === "string") : [];
677
- return roles.length === 0 ? { kind: "authenticated" } : {
678
- kind: "role",
679
- roles
680
- };
681
- }
682
- }
683
- throw new Error(`Operation "${entry.operationId}" has an unrecognized security scheme`);
684
- }
685
- function isRecord(value) {
686
- return typeof value === "object" && value !== null && !Array.isArray(value);
687
- }
688
707
  function resolveChannel(channel, useTypeAliases) {
689
708
  if (!channel.typeRef) return channel;
690
709
  return {
package/dist/index.mjs CHANGED
@@ -266,7 +266,49 @@ function collectOperations(spec, pathPrefix = "/api/", stripPrefix = true) {
266
266
  });
267
267
  }
268
268
  }
269
- return entries;
269
+ return excludeInternalOperations(entries, spec);
270
+ }
271
+ function excludeInternalOperations(entries, spec) {
272
+ const securitySchemes = spec.components?.securitySchemes;
273
+ if (!securitySchemes) return entries;
274
+ return entries.filter((entry) => readSecurityRequirement(entry, securitySchemes, spec.security)?.kind !== "internal");
275
+ }
276
+ function readSecurityRequirement(entry, securitySchemes, topLevelSecurity) {
277
+ const security = entry.operation.security ?? topLevelSecurity;
278
+ if (security === void 0) return null;
279
+ if (!Array.isArray(security)) throw new Error(`Operation "${entry.operationId}" has invalid security`);
280
+ if (security.length === 0) return { kind: "public" };
281
+ if (security.length > 1) throw new Error(`Operation "${entry.operationId}" declares ${security.length} security requirements; the backend contract emits at most one`);
282
+ const requirement = security[0];
283
+ if (!isRecord(requirement)) throw new Error(`Operation "${entry.operationId}" has an invalid security requirement`);
284
+ const schemeEntries = Object.entries(requirement);
285
+ if (schemeEntries.length > 1) throw new Error(`Operation "${entry.operationId}" declares ${schemeEntries.length} schemes in one security requirement; the backend contract emits exactly one`);
286
+ const schemeEntry = schemeEntries[0];
287
+ if (schemeEntry) {
288
+ const [schemeName, scopes] = schemeEntry;
289
+ const scheme = securitySchemes?.[schemeName];
290
+ if (scheme?.type === "apiKey" && scheme.in === "header") return { kind: "internal" };
291
+ if (scheme?.type === "http" || scheme?.type === "apiKey" && scheme.in === "cookie") {
292
+ const roles = readSecurityScopes(entry, schemeName, scopes);
293
+ return roles.length === 0 ? { kind: "authenticated" } : {
294
+ kind: "role",
295
+ roles
296
+ };
297
+ }
298
+ }
299
+ throw new Error(`Operation "${entry.operationId}" has an unrecognized security scheme`);
300
+ }
301
+ function readSecurityScopes(entry, schemeName, scopes) {
302
+ if (!Array.isArray(scopes)) throw new Error(`Operation "${entry.operationId}" has non-array scopes for security scheme "${schemeName}"`);
303
+ const roles = [];
304
+ for (const scope of scopes) {
305
+ if (typeof scope !== "string") throw new Error(`Operation "${entry.operationId}" has a non-string scope for security scheme "${schemeName}"`);
306
+ roles.push(scope);
307
+ }
308
+ return roles;
309
+ }
310
+ function isRecord(value) {
311
+ return typeof value === "object" && value !== null && !Array.isArray(value);
270
312
  }
271
313
  function getEffectiveParametersByLocation(entry, location) {
272
314
  return (entry.operation.parameters ?? []).filter((parameter) => getEffectiveParameterLocation(entry.apiPath, parameter) === location);
@@ -660,29 +702,6 @@ function createAccessPolicyEntries(operations, securitySchemes, topLevelSecurity
660
702
  }];
661
703
  });
662
704
  }
663
- function readSecurityRequirement(entry, securitySchemes, topLevelSecurity) {
664
- const security = entry.operation.security ?? topLevelSecurity;
665
- if (security === void 0) return null;
666
- if (!Array.isArray(security)) throw new Error(`Operation "${entry.operationId}" has invalid security`);
667
- if (security.length === 0) return { kind: "public" };
668
- const requirement = security[0];
669
- if (!isRecord(requirement)) throw new Error(`Operation "${entry.operationId}" has an invalid security requirement`);
670
- for (const [schemeName, scopes] of Object.entries(requirement)) {
671
- const scheme = securitySchemes?.[schemeName];
672
- if (scheme?.type === "apiKey" && scheme.in === "header") return { kind: "internal" };
673
- if (scheme?.type === "http" || scheme?.type === "apiKey" && scheme.in === "cookie") {
674
- const roles = Array.isArray(scopes) ? scopes.filter((scope) => typeof scope === "string") : [];
675
- return roles.length === 0 ? { kind: "authenticated" } : {
676
- kind: "role",
677
- roles
678
- };
679
- }
680
- }
681
- throw new Error(`Operation "${entry.operationId}" has an unrecognized security scheme`);
682
- }
683
- function isRecord(value) {
684
- return typeof value === "object" && value !== null && !Array.isArray(value);
685
- }
686
705
  function resolveChannel(channel, useTypeAliases) {
687
706
  if (!channel.typeRef) return channel;
688
707
  return {
@@ -771,7 +790,7 @@ function openapiCodegen(options) {
771
790
  },
772
791
  async buildStart() {
773
792
  if (command === "serve" && options.generateOnDev !== false) {
774
- runDevelopmentGeneration(root, options);
793
+ runDevelopmentGeneration(root, options, { onError: resolvePluginErrorRaiser(this) });
775
794
  return;
776
795
  }
777
796
  },
@@ -781,9 +800,12 @@ function openapiCodegen(options) {
781
800
  const inputPath = resolve(root, options.input);
782
801
  if (resolve(ctx.file) !== inputPath) return;
783
802
  console.log("[openapi-codegen] openapi.json changed, regenerating...");
784
- await runDevelopmentGeneration(root, options, { onSuccess: () => {
785
- console.log("[openapi-codegen] regeneration complete.");
786
- } });
803
+ await runDevelopmentGeneration(root, options, {
804
+ onError: resolvePluginErrorRaiser(this),
805
+ onSuccess: () => {
806
+ console.log("[openapi-codegen] regeneration complete.");
807
+ }
808
+ });
787
809
  }
788
810
  };
789
811
  }
@@ -792,8 +814,15 @@ async function runDevelopmentGeneration(root, options, handlers) {
792
814
  await generateOpenAPIArtifacts(root, options);
793
815
  handlers?.onSuccess?.();
794
816
  } catch (error) {
795
- console.error("[openapi-codegen] generation failed during dev mode.", error);
817
+ const failure = error instanceof Error ? error : new Error(String(error));
818
+ console.error("[openapi-codegen] generation failed during dev mode.", failure);
819
+ handlers?.onError?.(failure);
796
820
  }
797
821
  }
822
+ function resolvePluginErrorRaiser(context) {
823
+ if (typeof context !== "object" || context === null || typeof context.error !== "function") return;
824
+ const pluginContext = context;
825
+ return (error) => pluginContext.error(error);
826
+ }
798
827
  //#endregion
799
828
  export { openapiCodegen, renderGeneratedArtifacts };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-openapi-codegen",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "Vite plugin that generates typed API clients and route builders from OpenAPI specs",
5
5
  "keywords": [
6
6
  "api-client",