apigen-ts 1.1.0 → 1.2.0

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.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var main$1 = require('./main-B2qgp9dv.cjs');
3
+ var main$1 = require('./main-C0qK6dZX.cjs');
4
4
  require('fs/promises');
5
5
  require('path');
6
6
  require('url');
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as apigen, g as getCliConfig } from './main-BvB08bJo.js';
2
+ import { a as apigen, g as getCliConfig } from './main-l0LIDQ3K.js';
3
3
  import 'fs/promises';
4
4
  import 'path';
5
5
  import 'url';
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as apigen, g as getCliConfig } from './main-BvB08bJo.mjs';
1
+ import { a as apigen, g as getCliConfig } from './main-l0LIDQ3K.mjs';
2
2
  import 'fs/promises';
3
3
  import 'path';
4
4
  import 'url';
@@ -13,7 +13,7 @@ var path = require('node:path');
13
13
 
14
14
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
15
  var name = "apigen-ts";
16
- var version = "1.1.0";
16
+ var version = "1.2.0";
17
17
 
18
18
  const initCtx = (config) => {
19
19
  return {
@@ -23,11 +23,20 @@ const initCtx = (config) => {
23
23
  doc: { openapi: "3.1.0" },
24
24
  parseDates: false,
25
25
  inlineEnums: false,
26
+ headers: {},
26
27
  ...config,
27
28
  logTag: "",
28
29
  usedNames: /* @__PURE__ */ new Set()
29
30
  };
30
31
  };
32
+ const parseHeaders = (items) => {
33
+ const headers = {};
34
+ for (const item of items) {
35
+ const [key, val] = item.split(":");
36
+ if (key && val) headers[key.trim()] = val.trim();
37
+ }
38
+ return headers;
39
+ };
31
40
  const getCliConfig = () => {
32
41
  const argv = cleye.cli({
33
42
  name,
@@ -36,18 +45,24 @@ const getCliConfig = () => {
36
45
  flags: {
37
46
  name: {
38
47
  type: String,
39
- description: "api class name to export",
48
+ description: "API class name to export",
40
49
  default: "ApiClient"
41
50
  },
42
51
  parseDates: {
43
52
  type: Boolean,
44
- description: "parse dates as Date objects",
53
+ description: "Parse dates as Date objects",
45
54
  default: false
46
55
  },
47
56
  inlineEnums: {
48
57
  type: Boolean,
49
- description: "use inline enums instead of enum types",
58
+ description: "Use inline enums instead of enum types",
50
59
  default: false
60
+ },
61
+ header: {
62
+ type: [String],
63
+ alias: "H",
64
+ description: 'HTTP header as key=value (e.g., -H "x-api-key: your-key"). Used only when generating code.',
65
+ default: []
51
66
  }
52
67
  }
53
68
  });
@@ -56,13 +71,14 @@ const getCliConfig = () => {
56
71
  output: argv._.output ?? null,
57
72
  name: argv.flags.name,
58
73
  parseDates: argv.flags.parseDates,
59
- inlineEnums: argv.flags.inlineEnums
74
+ inlineEnums: argv.flags.inlineEnums,
75
+ headers: parseHeaders(argv.flags.header)
60
76
  };
61
77
  return config;
62
78
  };
63
79
 
64
80
  const unref = (ctx, s) => {
65
- if (!s) return undefined;
81
+ if (!s) return void 0;
66
82
  if ("$ref" in s && s.$ref) {
67
83
  const parts = s.$ref.replace("#/", "").split("/");
68
84
  const obj = parts.reduce(
@@ -72,15 +88,15 @@ const unref = (ctx, s) => {
72
88
  );
73
89
  if (obj) return obj;
74
90
  console.warn(`${ctx.logTag} ref ${s.$ref} not found`);
75
- return undefined;
91
+ return void 0;
76
92
  }
77
93
  return s;
78
94
  };
79
95
  const getReqSchema = (ctx, config) => {
80
96
  const req = unref(ctx, config.requestBody);
81
- if (!req) return undefined;
97
+ if (!req) return void 0;
82
98
  const cts = Object.entries(req.content ?? {}).map((x) => [x[0].split(";")[0], x[1].schema]).filter((x) => x[1]);
83
- if (cts.length === 0) return undefined;
99
+ if (cts.length === 0) return void 0;
84
100
  const pretenders = [
85
101
  "application/json",
86
102
  "text/",
@@ -92,18 +108,18 @@ const getReqSchema = (ctx, config) => {
92
108
  if (ct) return ct;
93
109
  }
94
110
  cts.map((x) => x[0]);
95
- return undefined;
111
+ return void 0;
96
112
  };
97
113
  const getRepSchema = (ctx, config) => {
98
114
  const successCodes = Object.keys(config.responses ?? {}).filter((x) => x.startsWith("2")).filter((x) => lodashEs.get(config, ["responses", x, "content"]));
99
115
  const cts = Object.entries(lodashEs.get(config, ["responses", successCodes[0], "content"], {})).filter((x) => x[1].schema);
100
- if (cts.length === 0) return undefined;
116
+ if (cts.length === 0) return void 0;
101
117
  const ctJson = cts.find((x) => x[0].startsWith("application/json"));
102
118
  if (ctJson) return ctJson[1].schema;
103
119
  const ctText = cts.find((x) => x[0].startsWith("text/"));
104
120
  if (ctText) return { type: "string" };
105
121
  cts.map((x) => x[0]).join(", ");
106
- return undefined;
122
+ return void 0;
107
123
  };
108
124
 
109
125
  const f$2 = ts.factory;
@@ -179,9 +195,9 @@ const normalizeIdentifier = (val, asVar = false) => {
179
195
  return name;
180
196
  };
181
197
  const makeInlineEnum = (s) => {
182
- if (!s.enum) return undefined;
198
+ if (!s.enum) return void 0;
183
199
  const values = arrayUtilsTs.filterEmpty(s.enum);
184
- if (!values.length) return undefined;
200
+ if (!values.length) return void 0;
185
201
  if (!s.type) {
186
202
  if (values.every((x) => typeof x === "string")) s.type = "string";
187
203
  if (values.every((x) => typeof x === "number")) s.type = "number";
@@ -202,7 +218,7 @@ const makeInlineEnum = (s) => {
202
218
  return f$2.createUnionTypeNode(tokens.map((x) => f$2.createLiteralTypeNode(x)));
203
219
  }
204
220
  console.warn(`enum with unknown type "${s.type}" in`, s);
205
- return undefined;
221
+ return void 0;
206
222
  };
207
223
  const makeObject = (ctx, s) => {
208
224
  if (s.type !== "object") throw new Error(`makeObject: not an object ${JSON.stringify(s)}`);
@@ -214,9 +230,15 @@ const makeObject = (ctx, s) => {
214
230
  }
215
231
  return f$2.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword);
216
232
  };
233
+ const makeLiteralUnion = (ctx, types) => {
234
+ const tokens = types.map((x) => makeType(ctx, { type: x }));
235
+ const hasUnknown = tokens.some((x) => x.kind === ts.SyntaxKind.UnknownKeyword);
236
+ if (hasUnknown) return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
237
+ return f$2.createUnionTypeNode(tokens);
238
+ };
217
239
  const makeType = (ctx, s) => {
218
240
  const mk = makeType.bind(null, ctx);
219
- if (s === undefined) return f$2.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
241
+ if (s === void 0) return f$2.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
220
242
  if (s === null) return f$2.createLiteralTypeNode(f$2.createNull());
221
243
  if ("$ref" in s && s.$ref) {
222
244
  const parts = s.$ref.replace("#/", "").split("/");
@@ -240,28 +262,20 @@ const makeType = (ctx, s) => {
240
262
  return f$2.createTypeLiteralNode(
241
263
  Object.entries(s.properties).map(([k, v]) => {
242
264
  const r = s.required ?? [];
243
- const q = r.includes(k) ? undefined : f$2.createToken(ts.SyntaxKind.QuestionToken);
244
- return f$2.createPropertySignature(undefined, f$2.createStringLiteral(k), q, mk(v));
265
+ const q = r.includes(k) ? void 0 : f$2.createToken(ts.SyntaxKind.QuestionToken);
266
+ return f$2.createPropertySignature(void 0, f$2.createStringLiteral(k), q, mk(v));
245
267
  })
246
268
  );
247
269
  }
248
270
  if ("type" in s) {
249
- if (Array.isArray(s.type)) {
250
- const types = [];
251
- for (const type of s.type) {
252
- if (type === "null") types.push({ type: "null" });
253
- else types.push({ ...s, type });
254
- }
255
- return mk({ oneOf: types });
256
- }
257
271
  let t;
258
272
  if (s.type === "object") t = makeObject(ctx, s);
259
273
  else if (s.type === "boolean") t = f$2.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
260
274
  else if (s.type === "number") t = f$2.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
261
275
  else if (s.type === "string") t = f$2.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
262
- else if (s.type === "array") t = f$2.createArrayTypeNode(mk(s.items));
263
276
  else if (s.type === "null") t = f$2.createLiteralTypeNode(f$2.createNull());
264
- else if (lodashEs.isArray(s.type)) t = f$2.createUnionTypeNode(s.type.map((x) => mk({ type: x })));
277
+ else if (lodashEs.isArray(s.type)) t = makeLiteralUnion(ctx, s.type);
278
+ else if (s.type === "array" && !lodashEs.isBoolean(s.items)) t = f$2.createArrayTypeNode(mk(s.items));
265
279
  else {
266
280
  console.warn(`makeType: unknown type "${s.type}"`);
267
281
  return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
@@ -270,7 +284,10 @@ const makeType = (ctx, s) => {
270
284
  if (s.format === "binary") t = f$2.createTypeReferenceNode("File");
271
285
  if (s.format === "date-time" && ctx.parseDates) t = f$2.createTypeReferenceNode("Date");
272
286
  }
273
- return s.nullable ? f$2.createUnionTypeNode([t, f$2.createLiteralTypeNode(f$2.createNull())]) : t;
287
+ if ("nullable" in s && s.nullable) {
288
+ return f$2.createUnionTypeNode([t, f$2.createLiteralTypeNode(f$2.createNull())]);
289
+ }
290
+ return t;
274
291
  }
275
292
  return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
276
293
  };
@@ -298,7 +315,7 @@ const makeTypeAlias = (ctx, name, s) => {
298
315
  return f$2.createTypeAliasDeclaration(
299
316
  [f$2.createToken(ts.SyntaxKind.ExportKeyword)],
300
317
  f$2.createIdentifier(normalizeIdentifier(name, true)),
301
- undefined,
318
+ void 0,
302
319
  makeType(ctx, s)
303
320
  );
304
321
  };
@@ -327,7 +344,7 @@ const getOpName = (ctx, op) => {
327
344
  if (ctx.resolveName) {
328
345
  const res = ctx.resolveName(ctx, op, proposal);
329
346
  if (Array.isArray(res) && res.length === 2) return res;
330
- if (res !== undefined) {
347
+ if (res !== void 0) {
331
348
  console.warn(`${ctx.logTag} resolveName should return [ns, fn] or undefined (skipping)`);
332
349
  }
333
350
  }
@@ -369,10 +386,10 @@ const prepareOp = (ctx, cfg, opName) => {
369
386
  const name = normalizeIdentifier(x.name, true);
370
387
  const type = makeType(ctx, x.schema);
371
388
  urlReplacements[x.name] = name;
372
- return f$1.createParameterDeclaration(undefined, undefined, name, undefined, type);
389
+ return f$1.createParameterDeclaration(void 0, void 0, name, void 0, type);
373
390
  });
374
391
  const cbArgs = arrayUtilsTs.filterNullable([
375
- search.length ? f$1.createShorthandPropertyAssignment("search") : undefined,
392
+ search.length ? f$1.createShorthandPropertyAssignment("search") : void 0,
376
393
  reqSchema && f$1.createShorthandPropertyAssignment("body"),
377
394
  reqSchema && reqSchema[0] !== "application/json" ? f$1.createPropertyAssignment(
378
395
  "headers",
@@ -382,16 +399,16 @@ const prepareOp = (ctx, cfg, opName) => {
382
399
  f$1.createStringLiteral(reqSchema[0])
383
400
  )
384
401
  ])
385
- ) : undefined
402
+ ) : void 0
386
403
  ]);
387
404
  return f$1.createPropertyAssignment(
388
405
  f$1.createIdentifier(normalizeIdentifier(opName)),
389
406
  f$1.createArrowFunction(
390
- undefined,
391
- undefined,
407
+ void 0,
408
+ void 0,
392
409
  fnArgs,
393
- undefined,
394
- undefined,
410
+ void 0,
411
+ void 0,
395
412
  f$1.createBlock([
396
413
  f$1.createReturnStatement(
397
414
  f$1.createCallExpression(
@@ -413,10 +430,10 @@ const prepareOp = (ctx, cfg, opName) => {
413
430
  };
414
431
  const prepareNs = (ctx, name, handlers) => {
415
432
  return f$1.createPropertyDeclaration(
416
- undefined,
433
+ void 0,
417
434
  normalizeIdentifier(name),
418
- undefined,
419
- undefined,
435
+ void 0,
436
+ void 0,
420
437
  f$1.createObjectLiteralExpression(handlers)
421
438
  );
422
439
  };
@@ -476,12 +493,23 @@ const generateAst = async (ctx) => {
476
493
  }
477
494
  return { modules, types };
478
495
  };
479
- const loadSchema = async (url, upgrade = true) => {
496
+ const loadSchema = async ({
497
+ url,
498
+ upgrade = true,
499
+ headers = {}
500
+ }) => {
480
501
  if (url.startsWith("file://")) url = url.substring(7);
481
502
  const { bundle } = await redocly.bundle({
482
503
  ref: url,
483
504
  config: await redocly.createConfig({}),
484
- removeUnusedComponents: false
505
+ removeUnusedComponents: false,
506
+ externalRefResolver: new redocly.BaseResolver({
507
+ http: {
508
+ headers: Object.entries(headers).map(([name, value]) => {
509
+ return { name, value, matches: "**" };
510
+ })
511
+ }
512
+ })
485
513
  });
486
514
  if (bundle.parsed.swagger && upgrade) {
487
515
  const { openapi } = await swagger2openapi.convertObj(bundle.parsed, { patch: true });
@@ -519,10 +547,10 @@ const formatCode = async (code) => {
519
547
  };
520
548
 
521
549
  const apigen = async (config) => {
522
- const doc = await loadSchema(config.source);
550
+ const doc = await loadSchema({ url: config.source, headers: config.headers });
523
551
  const ctx = initCtx({ ...config, doc });
524
552
  const { modules, types } = await generateAst(ctx);
525
- const filepath = path$1.join(path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('main-B2qgp9dv.cjs', document.baseURI).href)))), "_template.ts");
553
+ const filepath = path$1.join(path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('main-C0qK6dZX.cjs', document.baseURI).href)))), "_template.ts");
526
554
  const file = await fs.readFile(filepath, "utf-8");
527
555
  let code = [
528
556
  `// Auto-generated by https://github.com/vladkens/apigen-ts`,
@@ -2,15 +2,15 @@ import fs from 'fs/promises';
2
2
  import { join, dirname } from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { cli } from 'cleye';
5
- import redocly from '@redocly/openapi-core';
5
+ import redocly, { BaseResolver } from '@redocly/openapi-core';
6
6
  import { filterEmpty, filterNullable } from 'array-utils-ts';
7
- import { get, uniq, upperFirst, isArray, isBoolean, isObject, sortBy, lowerFirst, uniqBy } from 'lodash-es';
7
+ import { get, uniq, upperFirst, isArray, isBoolean, sortBy, isObject, lowerFirst, uniqBy } from 'lodash-es';
8
8
  import { convertObj } from 'swagger2openapi';
9
9
  import ts from 'typescript';
10
10
  import path from 'node:path';
11
11
 
12
12
  var name = "apigen-ts";
13
- var version = "1.1.0";
13
+ var version = "1.2.0";
14
14
 
15
15
  const initCtx = (config) => {
16
16
  return {
@@ -20,11 +20,20 @@ const initCtx = (config) => {
20
20
  doc: { openapi: "3.1.0" },
21
21
  parseDates: false,
22
22
  inlineEnums: false,
23
+ headers: {},
23
24
  ...config,
24
25
  logTag: "",
25
26
  usedNames: /* @__PURE__ */ new Set()
26
27
  };
27
28
  };
29
+ const parseHeaders = (items) => {
30
+ const headers = {};
31
+ for (const item of items) {
32
+ const [key, val] = item.split(":");
33
+ if (key && val) headers[key.trim()] = val.trim();
34
+ }
35
+ return headers;
36
+ };
28
37
  const getCliConfig = () => {
29
38
  const argv = cli({
30
39
  name,
@@ -33,18 +42,24 @@ const getCliConfig = () => {
33
42
  flags: {
34
43
  name: {
35
44
  type: String,
36
- description: "api class name to export",
45
+ description: "API class name to export",
37
46
  default: "ApiClient"
38
47
  },
39
48
  parseDates: {
40
49
  type: Boolean,
41
- description: "parse dates as Date objects",
50
+ description: "Parse dates as Date objects",
42
51
  default: false
43
52
  },
44
53
  inlineEnums: {
45
54
  type: Boolean,
46
- description: "use inline enums instead of enum types",
55
+ description: "Use inline enums instead of enum types",
47
56
  default: false
57
+ },
58
+ header: {
59
+ type: [String],
60
+ alias: "H",
61
+ description: 'HTTP header as key=value (e.g., -H "x-api-key: your-key"). Used only when generating code.',
62
+ default: []
48
63
  }
49
64
  }
50
65
  });
@@ -53,13 +68,14 @@ const getCliConfig = () => {
53
68
  output: argv._.output ?? null,
54
69
  name: argv.flags.name,
55
70
  parseDates: argv.flags.parseDates,
56
- inlineEnums: argv.flags.inlineEnums
71
+ inlineEnums: argv.flags.inlineEnums,
72
+ headers: parseHeaders(argv.flags.header)
57
73
  };
58
74
  return config;
59
75
  };
60
76
 
61
77
  const unref = (ctx, s) => {
62
- if (!s) return undefined;
78
+ if (!s) return void 0;
63
79
  if ("$ref" in s && s.$ref) {
64
80
  const parts = s.$ref.replace("#/", "").split("/");
65
81
  const obj = parts.reduce(
@@ -69,15 +85,15 @@ const unref = (ctx, s) => {
69
85
  );
70
86
  if (obj) return obj;
71
87
  console.warn(`${ctx.logTag} ref ${s.$ref} not found`);
72
- return undefined;
88
+ return void 0;
73
89
  }
74
90
  return s;
75
91
  };
76
92
  const getReqSchema = (ctx, config) => {
77
93
  const req = unref(ctx, config.requestBody);
78
- if (!req) return undefined;
94
+ if (!req) return void 0;
79
95
  const cts = Object.entries(req.content ?? {}).map((x) => [x[0].split(";")[0], x[1].schema]).filter((x) => x[1]);
80
- if (cts.length === 0) return undefined;
96
+ if (cts.length === 0) return void 0;
81
97
  const pretenders = [
82
98
  "application/json",
83
99
  "text/",
@@ -89,18 +105,18 @@ const getReqSchema = (ctx, config) => {
89
105
  if (ct) return ct;
90
106
  }
91
107
  cts.map((x) => x[0]);
92
- return undefined;
108
+ return void 0;
93
109
  };
94
110
  const getRepSchema = (ctx, config) => {
95
111
  const successCodes = Object.keys(config.responses ?? {}).filter((x) => x.startsWith("2")).filter((x) => get(config, ["responses", x, "content"]));
96
112
  const cts = Object.entries(get(config, ["responses", successCodes[0], "content"], {})).filter((x) => x[1].schema);
97
- if (cts.length === 0) return undefined;
113
+ if (cts.length === 0) return void 0;
98
114
  const ctJson = cts.find((x) => x[0].startsWith("application/json"));
99
115
  if (ctJson) return ctJson[1].schema;
100
116
  const ctText = cts.find((x) => x[0].startsWith("text/"));
101
117
  if (ctText) return { type: "string" };
102
118
  cts.map((x) => x[0]).join(", ");
103
- return undefined;
119
+ return void 0;
104
120
  };
105
121
 
106
122
  const f$2 = ts.factory;
@@ -176,9 +192,9 @@ const normalizeIdentifier = (val, asVar = false) => {
176
192
  return name;
177
193
  };
178
194
  const makeInlineEnum = (s) => {
179
- if (!s.enum) return undefined;
195
+ if (!s.enum) return void 0;
180
196
  const values = filterEmpty(s.enum);
181
- if (!values.length) return undefined;
197
+ if (!values.length) return void 0;
182
198
  if (!s.type) {
183
199
  if (values.every((x) => typeof x === "string")) s.type = "string";
184
200
  if (values.every((x) => typeof x === "number")) s.type = "number";
@@ -199,7 +215,7 @@ const makeInlineEnum = (s) => {
199
215
  return f$2.createUnionTypeNode(tokens.map((x) => f$2.createLiteralTypeNode(x)));
200
216
  }
201
217
  console.warn(`enum with unknown type "${s.type}" in`, s);
202
- return undefined;
218
+ return void 0;
203
219
  };
204
220
  const makeObject = (ctx, s) => {
205
221
  if (s.type !== "object") throw new Error(`makeObject: not an object ${JSON.stringify(s)}`);
@@ -211,9 +227,15 @@ const makeObject = (ctx, s) => {
211
227
  }
212
228
  return f$2.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword);
213
229
  };
230
+ const makeLiteralUnion = (ctx, types) => {
231
+ const tokens = types.map((x) => makeType(ctx, { type: x }));
232
+ const hasUnknown = tokens.some((x) => x.kind === ts.SyntaxKind.UnknownKeyword);
233
+ if (hasUnknown) return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
234
+ return f$2.createUnionTypeNode(tokens);
235
+ };
214
236
  const makeType = (ctx, s) => {
215
237
  const mk = makeType.bind(null, ctx);
216
- if (s === undefined) return f$2.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
238
+ if (s === void 0) return f$2.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
217
239
  if (s === null) return f$2.createLiteralTypeNode(f$2.createNull());
218
240
  if ("$ref" in s && s.$ref) {
219
241
  const parts = s.$ref.replace("#/", "").split("/");
@@ -237,28 +259,20 @@ const makeType = (ctx, s) => {
237
259
  return f$2.createTypeLiteralNode(
238
260
  Object.entries(s.properties).map(([k, v]) => {
239
261
  const r = s.required ?? [];
240
- const q = r.includes(k) ? undefined : f$2.createToken(ts.SyntaxKind.QuestionToken);
241
- return f$2.createPropertySignature(undefined, f$2.createStringLiteral(k), q, mk(v));
262
+ const q = r.includes(k) ? void 0 : f$2.createToken(ts.SyntaxKind.QuestionToken);
263
+ return f$2.createPropertySignature(void 0, f$2.createStringLiteral(k), q, mk(v));
242
264
  })
243
265
  );
244
266
  }
245
267
  if ("type" in s) {
246
- if (Array.isArray(s.type)) {
247
- const types = [];
248
- for (const type of s.type) {
249
- if (type === "null") types.push({ type: "null" });
250
- else types.push({ ...s, type });
251
- }
252
- return mk({ oneOf: types });
253
- }
254
268
  let t;
255
269
  if (s.type === "object") t = makeObject(ctx, s);
256
270
  else if (s.type === "boolean") t = f$2.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
257
271
  else if (s.type === "number") t = f$2.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
258
272
  else if (s.type === "string") t = f$2.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
259
- else if (s.type === "array") t = f$2.createArrayTypeNode(mk(s.items));
260
273
  else if (s.type === "null") t = f$2.createLiteralTypeNode(f$2.createNull());
261
- else if (isArray(s.type)) t = f$2.createUnionTypeNode(s.type.map((x) => mk({ type: x })));
274
+ else if (isArray(s.type)) t = makeLiteralUnion(ctx, s.type);
275
+ else if (s.type === "array" && !isBoolean(s.items)) t = f$2.createArrayTypeNode(mk(s.items));
262
276
  else {
263
277
  console.warn(`makeType: unknown type "${s.type}"`);
264
278
  return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
@@ -267,7 +281,10 @@ const makeType = (ctx, s) => {
267
281
  if (s.format === "binary") t = f$2.createTypeReferenceNode("File");
268
282
  if (s.format === "date-time" && ctx.parseDates) t = f$2.createTypeReferenceNode("Date");
269
283
  }
270
- return s.nullable ? f$2.createUnionTypeNode([t, f$2.createLiteralTypeNode(f$2.createNull())]) : t;
284
+ if ("nullable" in s && s.nullable) {
285
+ return f$2.createUnionTypeNode([t, f$2.createLiteralTypeNode(f$2.createNull())]);
286
+ }
287
+ return t;
271
288
  }
272
289
  return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
273
290
  };
@@ -295,7 +312,7 @@ const makeTypeAlias = (ctx, name, s) => {
295
312
  return f$2.createTypeAliasDeclaration(
296
313
  [f$2.createToken(ts.SyntaxKind.ExportKeyword)],
297
314
  f$2.createIdentifier(normalizeIdentifier(name, true)),
298
- undefined,
315
+ void 0,
299
316
  makeType(ctx, s)
300
317
  );
301
318
  };
@@ -324,7 +341,7 @@ const getOpName = (ctx, op) => {
324
341
  if (ctx.resolveName) {
325
342
  const res = ctx.resolveName(ctx, op, proposal);
326
343
  if (Array.isArray(res) && res.length === 2) return res;
327
- if (res !== undefined) {
344
+ if (res !== void 0) {
328
345
  console.warn(`${ctx.logTag} resolveName should return [ns, fn] or undefined (skipping)`);
329
346
  }
330
347
  }
@@ -366,10 +383,10 @@ const prepareOp = (ctx, cfg, opName) => {
366
383
  const name = normalizeIdentifier(x.name, true);
367
384
  const type = makeType(ctx, x.schema);
368
385
  urlReplacements[x.name] = name;
369
- return f$1.createParameterDeclaration(undefined, undefined, name, undefined, type);
386
+ return f$1.createParameterDeclaration(void 0, void 0, name, void 0, type);
370
387
  });
371
388
  const cbArgs = filterNullable([
372
- search.length ? f$1.createShorthandPropertyAssignment("search") : undefined,
389
+ search.length ? f$1.createShorthandPropertyAssignment("search") : void 0,
373
390
  reqSchema && f$1.createShorthandPropertyAssignment("body"),
374
391
  reqSchema && reqSchema[0] !== "application/json" ? f$1.createPropertyAssignment(
375
392
  "headers",
@@ -379,16 +396,16 @@ const prepareOp = (ctx, cfg, opName) => {
379
396
  f$1.createStringLiteral(reqSchema[0])
380
397
  )
381
398
  ])
382
- ) : undefined
399
+ ) : void 0
383
400
  ]);
384
401
  return f$1.createPropertyAssignment(
385
402
  f$1.createIdentifier(normalizeIdentifier(opName)),
386
403
  f$1.createArrowFunction(
387
- undefined,
388
- undefined,
404
+ void 0,
405
+ void 0,
389
406
  fnArgs,
390
- undefined,
391
- undefined,
407
+ void 0,
408
+ void 0,
392
409
  f$1.createBlock([
393
410
  f$1.createReturnStatement(
394
411
  f$1.createCallExpression(
@@ -410,10 +427,10 @@ const prepareOp = (ctx, cfg, opName) => {
410
427
  };
411
428
  const prepareNs = (ctx, name, handlers) => {
412
429
  return f$1.createPropertyDeclaration(
413
- undefined,
430
+ void 0,
414
431
  normalizeIdentifier(name),
415
- undefined,
416
- undefined,
432
+ void 0,
433
+ void 0,
417
434
  f$1.createObjectLiteralExpression(handlers)
418
435
  );
419
436
  };
@@ -473,12 +490,23 @@ const generateAst = async (ctx) => {
473
490
  }
474
491
  return { modules, types };
475
492
  };
476
- const loadSchema = async (url, upgrade = true) => {
493
+ const loadSchema = async ({
494
+ url,
495
+ upgrade = true,
496
+ headers = {}
497
+ }) => {
477
498
  if (url.startsWith("file://")) url = url.substring(7);
478
499
  const { bundle } = await redocly.bundle({
479
500
  ref: url,
480
501
  config: await redocly.createConfig({}),
481
- removeUnusedComponents: false
502
+ removeUnusedComponents: false,
503
+ externalRefResolver: new BaseResolver({
504
+ http: {
505
+ headers: Object.entries(headers).map(([name, value]) => {
506
+ return { name, value, matches: "**" };
507
+ })
508
+ }
509
+ })
482
510
  });
483
511
  if (bundle.parsed.swagger && upgrade) {
484
512
  const { openapi } = await convertObj(bundle.parsed, { patch: true });
@@ -516,7 +544,7 @@ const formatCode = async (code) => {
516
544
  };
517
545
 
518
546
  const apigen = async (config) => {
519
- const doc = await loadSchema(config.source);
547
+ const doc = await loadSchema({ url: config.source, headers: config.headers });
520
548
  const ctx = initCtx({ ...config, doc });
521
549
  const { modules, types } = await generateAst(ctx);
522
550
  const filepath = join(dirname(fileURLToPath(import.meta.url)), "_template.ts");
@@ -2,15 +2,15 @@ import fs from 'fs/promises';
2
2
  import { join, dirname } from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { cli } from 'cleye';
5
- import redocly from '@redocly/openapi-core';
5
+ import redocly, { BaseResolver } from '@redocly/openapi-core';
6
6
  import { filterEmpty, filterNullable } from 'array-utils-ts';
7
- import { get, uniq, upperFirst, isArray, isBoolean, isObject, sortBy, lowerFirst, uniqBy } from 'lodash-es';
7
+ import { get, uniq, upperFirst, isArray, isBoolean, sortBy, isObject, lowerFirst, uniqBy } from 'lodash-es';
8
8
  import { convertObj } from 'swagger2openapi';
9
9
  import ts from 'typescript';
10
10
  import path from 'node:path';
11
11
 
12
12
  var name = "apigen-ts";
13
- var version = "1.1.0";
13
+ var version = "1.2.0";
14
14
 
15
15
  const initCtx = (config) => {
16
16
  return {
@@ -20,11 +20,20 @@ const initCtx = (config) => {
20
20
  doc: { openapi: "3.1.0" },
21
21
  parseDates: false,
22
22
  inlineEnums: false,
23
+ headers: {},
23
24
  ...config,
24
25
  logTag: "",
25
26
  usedNames: /* @__PURE__ */ new Set()
26
27
  };
27
28
  };
29
+ const parseHeaders = (items) => {
30
+ const headers = {};
31
+ for (const item of items) {
32
+ const [key, val] = item.split(":");
33
+ if (key && val) headers[key.trim()] = val.trim();
34
+ }
35
+ return headers;
36
+ };
28
37
  const getCliConfig = () => {
29
38
  const argv = cli({
30
39
  name,
@@ -33,18 +42,24 @@ const getCliConfig = () => {
33
42
  flags: {
34
43
  name: {
35
44
  type: String,
36
- description: "api class name to export",
45
+ description: "API class name to export",
37
46
  default: "ApiClient"
38
47
  },
39
48
  parseDates: {
40
49
  type: Boolean,
41
- description: "parse dates as Date objects",
50
+ description: "Parse dates as Date objects",
42
51
  default: false
43
52
  },
44
53
  inlineEnums: {
45
54
  type: Boolean,
46
- description: "use inline enums instead of enum types",
55
+ description: "Use inline enums instead of enum types",
47
56
  default: false
57
+ },
58
+ header: {
59
+ type: [String],
60
+ alias: "H",
61
+ description: 'HTTP header as key=value (e.g., -H "x-api-key: your-key"). Used only when generating code.',
62
+ default: []
48
63
  }
49
64
  }
50
65
  });
@@ -53,13 +68,14 @@ const getCliConfig = () => {
53
68
  output: argv._.output ?? null,
54
69
  name: argv.flags.name,
55
70
  parseDates: argv.flags.parseDates,
56
- inlineEnums: argv.flags.inlineEnums
71
+ inlineEnums: argv.flags.inlineEnums,
72
+ headers: parseHeaders(argv.flags.header)
57
73
  };
58
74
  return config;
59
75
  };
60
76
 
61
77
  const unref = (ctx, s) => {
62
- if (!s) return undefined;
78
+ if (!s) return void 0;
63
79
  if ("$ref" in s && s.$ref) {
64
80
  const parts = s.$ref.replace("#/", "").split("/");
65
81
  const obj = parts.reduce(
@@ -69,15 +85,15 @@ const unref = (ctx, s) => {
69
85
  );
70
86
  if (obj) return obj;
71
87
  console.warn(`${ctx.logTag} ref ${s.$ref} not found`);
72
- return undefined;
88
+ return void 0;
73
89
  }
74
90
  return s;
75
91
  };
76
92
  const getReqSchema = (ctx, config) => {
77
93
  const req = unref(ctx, config.requestBody);
78
- if (!req) return undefined;
94
+ if (!req) return void 0;
79
95
  const cts = Object.entries(req.content ?? {}).map((x) => [x[0].split(";")[0], x[1].schema]).filter((x) => x[1]);
80
- if (cts.length === 0) return undefined;
96
+ if (cts.length === 0) return void 0;
81
97
  const pretenders = [
82
98
  "application/json",
83
99
  "text/",
@@ -89,18 +105,18 @@ const getReqSchema = (ctx, config) => {
89
105
  if (ct) return ct;
90
106
  }
91
107
  cts.map((x) => x[0]);
92
- return undefined;
108
+ return void 0;
93
109
  };
94
110
  const getRepSchema = (ctx, config) => {
95
111
  const successCodes = Object.keys(config.responses ?? {}).filter((x) => x.startsWith("2")).filter((x) => get(config, ["responses", x, "content"]));
96
112
  const cts = Object.entries(get(config, ["responses", successCodes[0], "content"], {})).filter((x) => x[1].schema);
97
- if (cts.length === 0) return undefined;
113
+ if (cts.length === 0) return void 0;
98
114
  const ctJson = cts.find((x) => x[0].startsWith("application/json"));
99
115
  if (ctJson) return ctJson[1].schema;
100
116
  const ctText = cts.find((x) => x[0].startsWith("text/"));
101
117
  if (ctText) return { type: "string" };
102
118
  cts.map((x) => x[0]).join(", ");
103
- return undefined;
119
+ return void 0;
104
120
  };
105
121
 
106
122
  const f$2 = ts.factory;
@@ -176,9 +192,9 @@ const normalizeIdentifier = (val, asVar = false) => {
176
192
  return name;
177
193
  };
178
194
  const makeInlineEnum = (s) => {
179
- if (!s.enum) return undefined;
195
+ if (!s.enum) return void 0;
180
196
  const values = filterEmpty(s.enum);
181
- if (!values.length) return undefined;
197
+ if (!values.length) return void 0;
182
198
  if (!s.type) {
183
199
  if (values.every((x) => typeof x === "string")) s.type = "string";
184
200
  if (values.every((x) => typeof x === "number")) s.type = "number";
@@ -199,7 +215,7 @@ const makeInlineEnum = (s) => {
199
215
  return f$2.createUnionTypeNode(tokens.map((x) => f$2.createLiteralTypeNode(x)));
200
216
  }
201
217
  console.warn(`enum with unknown type "${s.type}" in`, s);
202
- return undefined;
218
+ return void 0;
203
219
  };
204
220
  const makeObject = (ctx, s) => {
205
221
  if (s.type !== "object") throw new Error(`makeObject: not an object ${JSON.stringify(s)}`);
@@ -211,9 +227,15 @@ const makeObject = (ctx, s) => {
211
227
  }
212
228
  return f$2.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword);
213
229
  };
230
+ const makeLiteralUnion = (ctx, types) => {
231
+ const tokens = types.map((x) => makeType(ctx, { type: x }));
232
+ const hasUnknown = tokens.some((x) => x.kind === ts.SyntaxKind.UnknownKeyword);
233
+ if (hasUnknown) return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
234
+ return f$2.createUnionTypeNode(tokens);
235
+ };
214
236
  const makeType = (ctx, s) => {
215
237
  const mk = makeType.bind(null, ctx);
216
- if (s === undefined) return f$2.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
238
+ if (s === void 0) return f$2.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
217
239
  if (s === null) return f$2.createLiteralTypeNode(f$2.createNull());
218
240
  if ("$ref" in s && s.$ref) {
219
241
  const parts = s.$ref.replace("#/", "").split("/");
@@ -237,28 +259,20 @@ const makeType = (ctx, s) => {
237
259
  return f$2.createTypeLiteralNode(
238
260
  Object.entries(s.properties).map(([k, v]) => {
239
261
  const r = s.required ?? [];
240
- const q = r.includes(k) ? undefined : f$2.createToken(ts.SyntaxKind.QuestionToken);
241
- return f$2.createPropertySignature(undefined, f$2.createStringLiteral(k), q, mk(v));
262
+ const q = r.includes(k) ? void 0 : f$2.createToken(ts.SyntaxKind.QuestionToken);
263
+ return f$2.createPropertySignature(void 0, f$2.createStringLiteral(k), q, mk(v));
242
264
  })
243
265
  );
244
266
  }
245
267
  if ("type" in s) {
246
- if (Array.isArray(s.type)) {
247
- const types = [];
248
- for (const type of s.type) {
249
- if (type === "null") types.push({ type: "null" });
250
- else types.push({ ...s, type });
251
- }
252
- return mk({ oneOf: types });
253
- }
254
268
  let t;
255
269
  if (s.type === "object") t = makeObject(ctx, s);
256
270
  else if (s.type === "boolean") t = f$2.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
257
271
  else if (s.type === "number") t = f$2.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
258
272
  else if (s.type === "string") t = f$2.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
259
- else if (s.type === "array") t = f$2.createArrayTypeNode(mk(s.items));
260
273
  else if (s.type === "null") t = f$2.createLiteralTypeNode(f$2.createNull());
261
- else if (isArray(s.type)) t = f$2.createUnionTypeNode(s.type.map((x) => mk({ type: x })));
274
+ else if (isArray(s.type)) t = makeLiteralUnion(ctx, s.type);
275
+ else if (s.type === "array" && !isBoolean(s.items)) t = f$2.createArrayTypeNode(mk(s.items));
262
276
  else {
263
277
  console.warn(`makeType: unknown type "${s.type}"`);
264
278
  return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
@@ -267,7 +281,10 @@ const makeType = (ctx, s) => {
267
281
  if (s.format === "binary") t = f$2.createTypeReferenceNode("File");
268
282
  if (s.format === "date-time" && ctx.parseDates) t = f$2.createTypeReferenceNode("Date");
269
283
  }
270
- return s.nullable ? f$2.createUnionTypeNode([t, f$2.createLiteralTypeNode(f$2.createNull())]) : t;
284
+ if ("nullable" in s && s.nullable) {
285
+ return f$2.createUnionTypeNode([t, f$2.createLiteralTypeNode(f$2.createNull())]);
286
+ }
287
+ return t;
271
288
  }
272
289
  return f$2.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
273
290
  };
@@ -295,7 +312,7 @@ const makeTypeAlias = (ctx, name, s) => {
295
312
  return f$2.createTypeAliasDeclaration(
296
313
  [f$2.createToken(ts.SyntaxKind.ExportKeyword)],
297
314
  f$2.createIdentifier(normalizeIdentifier(name, true)),
298
- undefined,
315
+ void 0,
299
316
  makeType(ctx, s)
300
317
  );
301
318
  };
@@ -324,7 +341,7 @@ const getOpName = (ctx, op) => {
324
341
  if (ctx.resolveName) {
325
342
  const res = ctx.resolveName(ctx, op, proposal);
326
343
  if (Array.isArray(res) && res.length === 2) return res;
327
- if (res !== undefined) {
344
+ if (res !== void 0) {
328
345
  console.warn(`${ctx.logTag} resolveName should return [ns, fn] or undefined (skipping)`);
329
346
  }
330
347
  }
@@ -366,10 +383,10 @@ const prepareOp = (ctx, cfg, opName) => {
366
383
  const name = normalizeIdentifier(x.name, true);
367
384
  const type = makeType(ctx, x.schema);
368
385
  urlReplacements[x.name] = name;
369
- return f$1.createParameterDeclaration(undefined, undefined, name, undefined, type);
386
+ return f$1.createParameterDeclaration(void 0, void 0, name, void 0, type);
370
387
  });
371
388
  const cbArgs = filterNullable([
372
- search.length ? f$1.createShorthandPropertyAssignment("search") : undefined,
389
+ search.length ? f$1.createShorthandPropertyAssignment("search") : void 0,
373
390
  reqSchema && f$1.createShorthandPropertyAssignment("body"),
374
391
  reqSchema && reqSchema[0] !== "application/json" ? f$1.createPropertyAssignment(
375
392
  "headers",
@@ -379,16 +396,16 @@ const prepareOp = (ctx, cfg, opName) => {
379
396
  f$1.createStringLiteral(reqSchema[0])
380
397
  )
381
398
  ])
382
- ) : undefined
399
+ ) : void 0
383
400
  ]);
384
401
  return f$1.createPropertyAssignment(
385
402
  f$1.createIdentifier(normalizeIdentifier(opName)),
386
403
  f$1.createArrowFunction(
387
- undefined,
388
- undefined,
404
+ void 0,
405
+ void 0,
389
406
  fnArgs,
390
- undefined,
391
- undefined,
407
+ void 0,
408
+ void 0,
392
409
  f$1.createBlock([
393
410
  f$1.createReturnStatement(
394
411
  f$1.createCallExpression(
@@ -410,10 +427,10 @@ const prepareOp = (ctx, cfg, opName) => {
410
427
  };
411
428
  const prepareNs = (ctx, name, handlers) => {
412
429
  return f$1.createPropertyDeclaration(
413
- undefined,
430
+ void 0,
414
431
  normalizeIdentifier(name),
415
- undefined,
416
- undefined,
432
+ void 0,
433
+ void 0,
417
434
  f$1.createObjectLiteralExpression(handlers)
418
435
  );
419
436
  };
@@ -473,12 +490,23 @@ const generateAst = async (ctx) => {
473
490
  }
474
491
  return { modules, types };
475
492
  };
476
- const loadSchema = async (url, upgrade = true) => {
493
+ const loadSchema = async ({
494
+ url,
495
+ upgrade = true,
496
+ headers = {}
497
+ }) => {
477
498
  if (url.startsWith("file://")) url = url.substring(7);
478
499
  const { bundle } = await redocly.bundle({
479
500
  ref: url,
480
501
  config: await redocly.createConfig({}),
481
- removeUnusedComponents: false
502
+ removeUnusedComponents: false,
503
+ externalRefResolver: new BaseResolver({
504
+ http: {
505
+ headers: Object.entries(headers).map(([name, value]) => {
506
+ return { name, value, matches: "**" };
507
+ })
508
+ }
509
+ })
482
510
  });
483
511
  if (bundle.parsed.swagger && upgrade) {
484
512
  const { openapi } = await convertObj(bundle.parsed, { patch: true });
@@ -516,7 +544,7 @@ const formatCode = async (code) => {
516
544
  };
517
545
 
518
546
  const apigen = async (config) => {
519
- const doc = await loadSchema(config.source);
547
+ const doc = await loadSchema({ url: config.source, headers: config.headers });
520
548
  const ctx = initCtx({ ...config, doc });
521
549
  const { modules, types } = await generateAst(ctx);
522
550
  const filepath = join(dirname(fileURLToPath(import.meta.url)), "_template.ts");
package/dist/main.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  require('fs/promises');
4
4
  require('path');
5
5
  require('url');
6
- var main = require('./main-B2qgp9dv.cjs');
6
+ var main = require('./main-C0qK6dZX.cjs');
7
7
  require('cleye');
8
8
  require('@redocly/openapi-core');
9
9
  require('array-utils-ts');
package/dist/main.d.cts CHANGED
@@ -13,6 +13,7 @@ type Config = {
13
13
  parseDates: boolean;
14
14
  inlineEnums: boolean;
15
15
  resolveName?: (ctx: Context, op: OpConfig, proposal: OpName) => OpName | undefined;
16
+ headers: Record<string, string>;
16
17
  };
17
18
  type Context = Config & {
18
19
  doc: Oas3Definition;
package/dist/main.d.mts CHANGED
@@ -13,6 +13,7 @@ type Config = {
13
13
  parseDates: boolean;
14
14
  inlineEnums: boolean;
15
15
  resolveName?: (ctx: Context, op: OpConfig, proposal: OpName) => OpName | undefined;
16
+ headers: Record<string, string>;
16
17
  };
17
18
  type Context = Config & {
18
19
  doc: Oas3Definition;
package/dist/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import 'fs/promises';
2
2
  import 'path';
3
3
  import 'url';
4
- export { a as apigen } from './main-BvB08bJo.js';
4
+ export { a as apigen } from './main-l0LIDQ3K.js';
5
5
  import 'cleye';
6
6
  import '@redocly/openapi-core';
7
7
  import 'array-utils-ts';
package/dist/main.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import 'fs/promises';
2
2
  import 'path';
3
3
  import 'url';
4
- export { a as apigen } from './main-BvB08bJo.mjs';
4
+ export { a as apigen } from './main-l0LIDQ3K.mjs';
5
5
  import 'cleye';
6
6
  import '@redocly/openapi-core';
7
7
  import 'array-utils-ts';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "apigen-ts",
4
- "version": "1.1.0",
4
+ "version": "1.2.0",
5
5
  "license": "MIT",
6
6
  "author": "vladkens <v.pronsky@gmail.com>",
7
7
  "repository": "vladkens/apigen-ts",
@@ -22,23 +22,23 @@
22
22
  "ci": "tsc --noEmit && yarn test-cov && yarn build"
23
23
  },
24
24
  "dependencies": {
25
- "@redocly/openapi-core": "1.27.2",
25
+ "@redocly/openapi-core": "1.34.1",
26
26
  "@types/lodash-es": "4.17.12",
27
27
  "@types/swagger2openapi": "7.0.4",
28
28
  "array-utils-ts": "1.0.2",
29
- "cleye": "1.3.2",
29
+ "cleye": "1.3.4",
30
30
  "lodash-es": "4.17.21",
31
31
  "swagger2openapi": "7.0.8"
32
32
  },
33
33
  "devDependencies": {
34
- "@types/node": "22.10.7",
34
+ "@types/node": "22.14.0",
35
35
  "c8": "10.1.3",
36
- "fetch-mock": "12.2.0",
37
- "pkgroll": "2.6.1",
38
- "prettier": "3.4.2",
36
+ "fetch-mock": "12.5.2",
37
+ "pkgroll": "2.12.1",
38
+ "prettier": "3.5.3",
39
39
  "prettier-plugin-organize-imports": "4.1.0",
40
40
  "tsm": "2.3.0",
41
- "typescript": "5.7.3",
41
+ "typescript": "5.8.3",
42
42
  "uvu": "0.5.6"
43
43
  },
44
44
  "peerDependencies": {
package/readme.md CHANGED
@@ -2,17 +2,16 @@
2
2
 
3
3
  <div align="center">
4
4
 
5
- [<img src="https://badgen.net/npm/v/apigen-ts" alt="version" />](https://npmjs.org/package/apigen-ts)
6
- [<img src="https://badgen.net/packagephobia/publish/apigen-ts" alt="size" />](https://packagephobia.now.sh/result?p=apigen-ts)
7
- [<img src="https://badgen.net/npm/dm/apigen-ts" alt="downloads" />](https://npmjs.org/package/apigen-ts)
8
- [<img src="https://badgen.net/github/license/vladkens/apigen-ts" alt="license" />](https://github.com/vladkens/apigen-ts/blob/main/LICENSE)
9
- [<img src="https://badgen.net/static/-/buy%20me%20a%20coffee/ff813f?icon=buymeacoffee&label" alt="donate" />](https://buymeacoffee.com/vladkens)
5
+ [<img src="https://badges.ws/npm/v/apigen-ts" alt="version" />](https://npmjs.org/package/apigen-ts)
6
+ [<img src="https://badges.ws/packagephobia/publish/apigen-ts" alt="size" />](https://packagephobia.now.sh/result?p=apigen-ts)
7
+ [<img src="https://badges.ws/npm/dm/apigen-ts" alt="downloads" />](https://npmjs.org/package/apigen-ts)
8
+ [<img src="https://badges.ws/github/license/vladkens/apigen-ts" alt="license" />](https://github.com/vladkens/apigen-ts/blob/main/LICENSE)
9
+ [<img src="https://badges.ws/badge/-/buy%20me%20a%20coffee/ff813f?icon=buymeacoffee&label" alt="donate" />](https://buymeacoffee.com/vladkens)
10
10
 
11
11
  </div>
12
12
 
13
13
  <div align="center">
14
14
  <img src="./logo.svg" alt="apigen-ts logo" height="80" />
15
- <div>Simple typed OpenAPI client generator</div>
16
15
  </div>
17
16
 
18
17
  ## Features
@@ -29,7 +28,11 @@
29
28
  ## Install
30
29
 
31
30
  ```sh
32
- yarn install -D apigen-ts
31
+ npm install apigen-ts --save-dev
32
+ ```
33
+
34
+ ```sh
35
+ yarn add -D apigen-ts
33
36
  ```
34
37
 
35
38
  ## Usage
@@ -37,11 +40,14 @@ yarn install -D apigen-ts
37
40
  ### 1. Generate
38
41
 
39
42
  ```sh
43
+ # From file
44
+ yarn apigen-ts ./openapi.json ./api-client.ts
45
+
40
46
  # From url
41
47
  yarn apigen-ts https://petstore3.swagger.io/api/v3/openapi.json ./api-client.ts
42
48
 
43
- # From file
44
- yarn apigen-ts ./openapi.json ./api-client.ts
49
+ # From protected url
50
+ yarn apigen-ts https://secret-api.example.com ./api-client.ts -H "x-api-key: secret-key"
45
51
  ```
46
52
 
47
53
  Run `yarn apigen-ts --help` for more options. Examples of generated clients [here](./examples/).
@@ -177,6 +183,7 @@ await apigen({
177
183
  name: "MyApiClient", // default "ApiClient"
178
184
  parseDates: true, // default false
179
185
  inlineEnums: false, // default false, use string literal union instead of enum
186
+ headers: { "x-api-key": "secret-key" }, // Custom HTTP headers to use when fetching schema
180
187
  resolveName(ctx, op, proposal) {
181
188
  // proposal is [string, string] which represents module.funcName
182
189
  if (proposal[0] === "users") return // will use default proposal