@icib.dev/api-client 1.1.0 → 1.1.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/README.md CHANGED
@@ -25,7 +25,7 @@ setAuthToken(process.env.API_TOKEN);
25
25
  const res = await apiClient.allegati.list({ page: 1, size: 10 });
26
26
  ```
27
27
 
28
- 3. Add verify to your build (fails if docs changed or client was modified):
28
+ 3. Add verify to your build (ensures version alignment for production; fails if docs changed or client was modified):
29
29
 
30
30
  ```json
31
31
  {
@@ -90,7 +90,9 @@ api/
90
90
 
91
91
  ### Hash verification
92
92
 
93
- Add `api-client-verify` before your build to ensure the generated client matches the current OpenAPI docs. When you run your build, it:
93
+ Add `api-client-verify` before your build to ensure the generated client matches the current OpenAPI docs. You can insert it in the build step of your utilization library (the app or library that consumes the API client) to verify version alignment before production builds—if the API docs changed or the client was modified, the build fails and you must regenerate.
94
+
95
+ When you run your build, it:
94
96
 
95
97
  1. Reads the manifest (created by `generate`)
96
98
  2. Fetches the current docs and compares their hash
@@ -92,6 +92,25 @@ function getDefinitions(doc) {
92
92
  function getPaths(doc) {
93
93
  return doc.paths ?? {};
94
94
  }
95
+ /** Extract response schema from OpenAPI 2.0 (schema) or OpenAPI 3.0 (content) */
96
+ function getResponseSchema(response) {
97
+ if (!response || typeof response !== "object")
98
+ return undefined;
99
+ const r = response;
100
+ // OpenAPI 2.0: schema directly on response
101
+ if (r.schema && typeof r.schema === "object") {
102
+ return r.schema;
103
+ }
104
+ // OpenAPI 3.0: schema under content['application/json'] or content['*/*']
105
+ const content = r.content;
106
+ if (content) {
107
+ const jsonContent = content["application/json"] ??
108
+ content["*/*"] ??
109
+ Object.values(content)[0];
110
+ return jsonContent?.schema;
111
+ }
112
+ return undefined;
113
+ }
95
114
  function schemaToTsType(schema, definitions, refsSeen = new Set()) {
96
115
  if (!schema)
97
116
  return "unknown";
@@ -251,7 +270,7 @@ function extractOperations(paths, definitions) {
251
270
  }
252
271
  }
253
272
  const successResponse = op.responses?.["200"] ?? op.responses?.["201"];
254
- const respSchema = successResponse?.schema;
273
+ const respSchema = getResponseSchema(successResponse);
255
274
  const respDesc = successResponse?.description ?? "";
256
275
  const xResponseType = successResponse?.["x-response-type"];
257
276
  let responseType = "unknown";
@@ -536,12 +555,23 @@ function generateContextFile(tag, operations, definitions, tagDescription) {
536
555
  }
537
556
  function generateClient(baseUrl) {
538
557
  return `// Auto-generated Axios client
539
- import axios, { type AxiosInstance } from "axios";
558
+ import axios, { type AxiosInstance, AxiosError } from "axios";
540
559
 
541
560
  let _token: string | null = null;
542
561
 
543
- export function setAuthToken(token: string | null): void {
562
+ export function setAuthToken(token: string | null, callback?: (token: string | null) => void): void {
544
563
  _token = token;
564
+ if (callback) callback(token);
565
+ // insert your own logic here, e.g. save to localStorage, sessionStorage, etc.
566
+ }
567
+
568
+ export function getAuthToken(): string | null {
569
+ return _token;
570
+ }
571
+
572
+ export function clearAuthToken(): void {
573
+ _token = null;
574
+ // insert your own logic here
545
575
  }
546
576
 
547
577
  export const client: AxiosInstance = axios.create({
@@ -558,6 +588,21 @@ client.interceptors.request.use((config) => {
558
588
  return config;
559
589
  });
560
590
 
591
+ client.interceptors.response.use(
592
+ (response) => {
593
+ if (response.status === 401) {
594
+ clearAuthToken();
595
+ }
596
+ return response.data;
597
+ },
598
+ (error) => {
599
+ if (error.response.status === 401) {
600
+ clearAuthToken();
601
+ }
602
+ return AxiosError.from(error);
603
+ },
604
+ );
605
+
561
606
  /** Options for blob/download endpoints */
562
607
  export interface BlobDownloadOptions {
563
608
  /** When true, triggers a file download in the browser */
@@ -631,7 +676,7 @@ function generateIndex(contextTags) {
631
676
  return exports.join("\n");
632
677
  }
633
678
  async function main() {
634
- const { url, out, basePath: basePathOverride, baseUrl: baseUrlOverride } = parseArgs();
679
+ const { url, out, basePath: basePathOverride, baseUrl: baseUrlOverride, } = parseArgs();
635
680
  console.log(`Fetching spec from ${url}...`);
636
681
  const rawSpec = await loadRawSpec(url);
637
682
  const doc = await parseSpec(rawSpec);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icib.dev/api-client",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Generator for strictly-typed TypeScript API clients from OpenAPI specs",
5
5
  "type": "module",
6
6
  "bin": {