apigen-ts 0.1.0 → 0.1.2
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/_template.ts +9 -6
- package/dist/cli.cjs +2 -2
- package/dist/cli.js +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/{main-0c2fa229.js → main-bbe33f1b.js} +25 -10
- package/dist/{main-0c2fa229.mjs → main-bbe33f1b.mjs} +25 -10
- package/dist/{main-0ae61014.cjs → main-c2426ec2.cjs} +27 -31
- package/dist/main.cjs +2 -2
- package/dist/main.d.cts +1 -1
- package/dist/main.d.mts +1 -1
- package/dist/main.js +2 -2
- package/dist/main.mjs +2 -2
- package/package.json +5 -4
- package/readme.md +62 -17
package/dist/_template.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Note: Use uppercase for names in ApiClient to avoid conflict with the generated code
|
|
2
2
|
|
|
3
|
-
interface ApigenConfig {
|
|
3
|
+
export interface ApigenConfig {
|
|
4
4
|
baseUrl: string
|
|
5
5
|
headers: Record<string, string>
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
interface ApigenRequest extends Omit<RequestInit, "body"> {
|
|
8
|
+
export interface ApigenRequest extends Omit<RequestInit, "body"> {
|
|
9
9
|
search?: Record<string, unknown>
|
|
10
10
|
body?: unknown
|
|
11
11
|
}
|
|
@@ -42,8 +42,10 @@ export class ApiClient {
|
|
|
42
42
|
|
|
43
43
|
async Fetch<T>(method: string, path: string, opts: ApigenRequest = {}): Promise<T> {
|
|
44
44
|
let base = this.Config.baseUrl
|
|
45
|
-
if (
|
|
46
|
-
|
|
45
|
+
if ("location" in globalThis && (base === "" || base.startsWith("/"))) {
|
|
46
|
+
// make ts happy in pure nodejs environment, should never pass here
|
|
47
|
+
const { location } = globalThis as unknown as { location: { origin: string } }
|
|
48
|
+
base = `${location.origin}${base.endsWith("/") ? base : `/${base}`}`
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
const url = new URL(path, base)
|
|
@@ -57,7 +59,8 @@ export class ApiClient {
|
|
|
57
59
|
let body: FormData | URLSearchParams | string | undefined = undefined
|
|
58
60
|
|
|
59
61
|
if (ct === "multipart/form-data" || ct === "application/x-www-form-urlencoded") {
|
|
60
|
-
|
|
62
|
+
// https://stackoverflow.com/a/61053359/3664464
|
|
63
|
+
headers.delete("content-type")
|
|
61
64
|
body = ct === "multipart/form-data" ? new FormData() : new URLSearchParams()
|
|
62
65
|
for (const [k, v] of Object.entries(opts.body as Record<string, string>)) {
|
|
63
66
|
body.append(k, v)
|
|
@@ -75,7 +78,7 @@ export class ApiClient {
|
|
|
75
78
|
|
|
76
79
|
const rs = await rep.text()
|
|
77
80
|
try {
|
|
78
|
-
return this.PopulateDates(JSON.parse(rs))
|
|
81
|
+
return this.PopulateDates(JSON.parse(rs) as T)
|
|
79
82
|
} catch (e) {
|
|
80
83
|
return rs as unknown as T
|
|
81
84
|
}
|
package/dist/cli.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var main$1 = require('./main-
|
|
3
|
+
var main$1 = require('./main-c2426ec2.cjs');
|
|
4
4
|
require('fs/promises');
|
|
5
5
|
require('path');
|
|
6
6
|
require('url');
|
|
@@ -10,7 +10,7 @@ require('array-utils-ts');
|
|
|
10
10
|
require('lodash-es');
|
|
11
11
|
require('swagger2openapi');
|
|
12
12
|
require('typescript');
|
|
13
|
-
require('
|
|
13
|
+
require('node:path');
|
|
14
14
|
|
|
15
15
|
const main = async () => {
|
|
16
16
|
await main$1.apigen(main$1.getCliConfig());
|
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-
|
|
2
|
+
import { a as apigen, g as getCliConfig } from './main-bbe33f1b.js';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'path';
|
|
5
5
|
import 'url';
|
|
@@ -9,7 +9,7 @@ import 'array-utils-ts';
|
|
|
9
9
|
import 'lodash-es';
|
|
10
10
|
import 'swagger2openapi';
|
|
11
11
|
import 'typescript';
|
|
12
|
-
import '
|
|
12
|
+
import 'node:path';
|
|
13
13
|
|
|
14
14
|
const main = async () => {
|
|
15
15
|
await apigen(getCliConfig());
|
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as apigen, g as getCliConfig } from './main-
|
|
1
|
+
import { a as apigen, g as getCliConfig } from './main-bbe33f1b.mjs';
|
|
2
2
|
import 'fs/promises';
|
|
3
3
|
import 'path';
|
|
4
4
|
import 'url';
|
|
@@ -8,7 +8,7 @@ import 'array-utils-ts';
|
|
|
8
8
|
import 'lodash-es';
|
|
9
9
|
import 'swagger2openapi';
|
|
10
10
|
import 'typescript';
|
|
11
|
-
import '
|
|
11
|
+
import 'node:path';
|
|
12
12
|
|
|
13
13
|
const main = async () => {
|
|
14
14
|
await apigen(getCliConfig());
|
|
@@ -7,7 +7,7 @@ import { filterEmpty, filterNullable } from 'array-utils-ts';
|
|
|
7
7
|
import { get, uniq, upperFirst, isArray, isObject, sortBy, lowerFirst, uniqBy } from 'lodash-es';
|
|
8
8
|
import { convertObj } from 'swagger2openapi';
|
|
9
9
|
import ts from 'typescript';
|
|
10
|
-
import
|
|
10
|
+
import path from 'node:path';
|
|
11
11
|
|
|
12
12
|
const initCtx = (config) => {
|
|
13
13
|
return {
|
|
@@ -24,8 +24,8 @@ const initCtx = (config) => {
|
|
|
24
24
|
const getCliConfig = () => {
|
|
25
25
|
const argv = cli({
|
|
26
26
|
name: "apigen",
|
|
27
|
-
|
|
28
|
-
parameters: ["<source>", "
|
|
27
|
+
version: "0.1.1",
|
|
28
|
+
parameters: ["<source>", "[output]"],
|
|
29
29
|
flags: {
|
|
30
30
|
name: {
|
|
31
31
|
type: String,
|
|
@@ -41,7 +41,7 @@ const getCliConfig = () => {
|
|
|
41
41
|
});
|
|
42
42
|
const config = {
|
|
43
43
|
source: argv._.source,
|
|
44
|
-
output: argv._.output,
|
|
44
|
+
output: argv._.output ?? null,
|
|
45
45
|
name: argv.flags.name,
|
|
46
46
|
parseDates: argv.flags.parseDates
|
|
47
47
|
};
|
|
@@ -163,7 +163,8 @@ const Keywords = /* @__PURE__ */ new Set([
|
|
|
163
163
|
"Extract",
|
|
164
164
|
// ts keywords
|
|
165
165
|
"Date",
|
|
166
|
-
"object"
|
|
166
|
+
"object",
|
|
167
|
+
"Response"
|
|
167
168
|
// ts type names
|
|
168
169
|
]);
|
|
169
170
|
const normalizeIdentifier = (val, asVar = false) => {
|
|
@@ -498,6 +499,8 @@ const generateAst = async (ctx) => {
|
|
|
498
499
|
return { modules, types };
|
|
499
500
|
};
|
|
500
501
|
const loadSchema = async (url, upgrade = true) => {
|
|
502
|
+
if (url.startsWith("file://"))
|
|
503
|
+
url = url.substring(7);
|
|
501
504
|
const { bundle } = await redocly.bundle({
|
|
502
505
|
ref: url,
|
|
503
506
|
config: await redocly.createConfig({}),
|
|
@@ -529,8 +532,13 @@ const printCode = (nodes) => {
|
|
|
529
532
|
).replaceAll("}, ", "},\n\n");
|
|
530
533
|
};
|
|
531
534
|
const formatCode = async (code) => {
|
|
532
|
-
|
|
533
|
-
|
|
535
|
+
try {
|
|
536
|
+
const prettier = await import('prettier');
|
|
537
|
+
const options = await prettier.resolveConfig(path.join(process.cwd(), "file"));
|
|
538
|
+
return prettier.format(code, { ...options, parser: "typescript" });
|
|
539
|
+
} catch (e) {
|
|
540
|
+
return code;
|
|
541
|
+
}
|
|
534
542
|
};
|
|
535
543
|
|
|
536
544
|
const apigen = async (config) => {
|
|
@@ -543,17 +551,24 @@ const apigen = async (config) => {
|
|
|
543
551
|
`// Auto-generated by https://github.com/vladkens/apigen-ts`,
|
|
544
552
|
`// Source: ${config.source}
|
|
545
553
|
`,
|
|
546
|
-
|
|
554
|
+
// remove all comments expect which starts with "// apigen:"
|
|
555
|
+
...file.split("\n").filter((x) => !/\s*\/\/\s(?!apigen:)/.test(x))
|
|
547
556
|
].join("\n");
|
|
548
557
|
if (!ctx.parseDates) {
|
|
558
|
+
code = code.replace(/\s*ISO_FORMAT\s=.+$/gm, "");
|
|
549
559
|
code = code.replace(/PopulateDates.+?\n\s{2}\}/s, "");
|
|
550
560
|
code = code.replace(/this.PopulateDates\((.+)\)/, "$1");
|
|
551
561
|
}
|
|
552
562
|
code = code.replace("// apigen:modules", printCode(modules));
|
|
553
563
|
code = code.replace("// apigen:types", printCode(types));
|
|
554
564
|
code = code.replace("class ApiClient", `class ${ctx.name}`);
|
|
555
|
-
|
|
556
|
-
|
|
565
|
+
const result = await formatCode(code);
|
|
566
|
+
if (config.output === null) {
|
|
567
|
+
process.stdout.write(result);
|
|
568
|
+
} else {
|
|
569
|
+
await fs.mkdir(dirname(config.output), { recursive: true });
|
|
570
|
+
await fs.writeFile(config.output, result);
|
|
571
|
+
}
|
|
557
572
|
};
|
|
558
573
|
|
|
559
574
|
export { apigen as a, getCliConfig as g };
|
|
@@ -7,7 +7,7 @@ import { filterEmpty, filterNullable } from 'array-utils-ts';
|
|
|
7
7
|
import { get, uniq, upperFirst, isArray, isObject, sortBy, lowerFirst, uniqBy } from 'lodash-es';
|
|
8
8
|
import { convertObj } from 'swagger2openapi';
|
|
9
9
|
import ts from 'typescript';
|
|
10
|
-
import
|
|
10
|
+
import path from 'node:path';
|
|
11
11
|
|
|
12
12
|
const initCtx = (config) => {
|
|
13
13
|
return {
|
|
@@ -24,8 +24,8 @@ const initCtx = (config) => {
|
|
|
24
24
|
const getCliConfig = () => {
|
|
25
25
|
const argv = cli({
|
|
26
26
|
name: "apigen",
|
|
27
|
-
|
|
28
|
-
parameters: ["<source>", "
|
|
27
|
+
version: "0.1.1",
|
|
28
|
+
parameters: ["<source>", "[output]"],
|
|
29
29
|
flags: {
|
|
30
30
|
name: {
|
|
31
31
|
type: String,
|
|
@@ -41,7 +41,7 @@ const getCliConfig = () => {
|
|
|
41
41
|
});
|
|
42
42
|
const config = {
|
|
43
43
|
source: argv._.source,
|
|
44
|
-
output: argv._.output,
|
|
44
|
+
output: argv._.output ?? null,
|
|
45
45
|
name: argv.flags.name,
|
|
46
46
|
parseDates: argv.flags.parseDates
|
|
47
47
|
};
|
|
@@ -163,7 +163,8 @@ const Keywords = /* @__PURE__ */ new Set([
|
|
|
163
163
|
"Extract",
|
|
164
164
|
// ts keywords
|
|
165
165
|
"Date",
|
|
166
|
-
"object"
|
|
166
|
+
"object",
|
|
167
|
+
"Response"
|
|
167
168
|
// ts type names
|
|
168
169
|
]);
|
|
169
170
|
const normalizeIdentifier = (val, asVar = false) => {
|
|
@@ -498,6 +499,8 @@ const generateAst = async (ctx) => {
|
|
|
498
499
|
return { modules, types };
|
|
499
500
|
};
|
|
500
501
|
const loadSchema = async (url, upgrade = true) => {
|
|
502
|
+
if (url.startsWith("file://"))
|
|
503
|
+
url = url.substring(7);
|
|
501
504
|
const { bundle } = await redocly.bundle({
|
|
502
505
|
ref: url,
|
|
503
506
|
config: await redocly.createConfig({}),
|
|
@@ -529,8 +532,13 @@ const printCode = (nodes) => {
|
|
|
529
532
|
).replaceAll("}, ", "},\n\n");
|
|
530
533
|
};
|
|
531
534
|
const formatCode = async (code) => {
|
|
532
|
-
|
|
533
|
-
|
|
535
|
+
try {
|
|
536
|
+
const prettier = await import('prettier');
|
|
537
|
+
const options = await prettier.resolveConfig(path.join(process.cwd(), "file"));
|
|
538
|
+
return prettier.format(code, { ...options, parser: "typescript" });
|
|
539
|
+
} catch (e) {
|
|
540
|
+
return code;
|
|
541
|
+
}
|
|
534
542
|
};
|
|
535
543
|
|
|
536
544
|
const apigen = async (config) => {
|
|
@@ -543,17 +551,24 @@ const apigen = async (config) => {
|
|
|
543
551
|
`// Auto-generated by https://github.com/vladkens/apigen-ts`,
|
|
544
552
|
`// Source: ${config.source}
|
|
545
553
|
`,
|
|
546
|
-
|
|
554
|
+
// remove all comments expect which starts with "// apigen:"
|
|
555
|
+
...file.split("\n").filter((x) => !/\s*\/\/\s(?!apigen:)/.test(x))
|
|
547
556
|
].join("\n");
|
|
548
557
|
if (!ctx.parseDates) {
|
|
558
|
+
code = code.replace(/\s*ISO_FORMAT\s=.+$/gm, "");
|
|
549
559
|
code = code.replace(/PopulateDates.+?\n\s{2}\}/s, "");
|
|
550
560
|
code = code.replace(/this.PopulateDates\((.+)\)/, "$1");
|
|
551
561
|
}
|
|
552
562
|
code = code.replace("// apigen:modules", printCode(modules));
|
|
553
563
|
code = code.replace("// apigen:types", printCode(types));
|
|
554
564
|
code = code.replace("class ApiClient", `class ${ctx.name}`);
|
|
555
|
-
|
|
556
|
-
|
|
565
|
+
const result = await formatCode(code);
|
|
566
|
+
if (config.output === null) {
|
|
567
|
+
process.stdout.write(result);
|
|
568
|
+
} else {
|
|
569
|
+
await fs.mkdir(dirname(config.output), { recursive: true });
|
|
570
|
+
await fs.writeFile(config.output, result);
|
|
571
|
+
}
|
|
557
572
|
};
|
|
558
573
|
|
|
559
574
|
export { apigen as a, getCliConfig as g };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var fs = require('fs/promises');
|
|
4
|
-
var path = require('path');
|
|
4
|
+
var path$1 = require('path');
|
|
5
5
|
var url = require('url');
|
|
6
6
|
var cleye = require('cleye');
|
|
7
7
|
var redocly = require('@redocly/openapi-core');
|
|
@@ -9,28 +9,9 @@ var arrayUtilsTs = require('array-utils-ts');
|
|
|
9
9
|
var lodashEs = require('lodash-es');
|
|
10
10
|
var swagger2openapi = require('swagger2openapi');
|
|
11
11
|
var ts = require('typescript');
|
|
12
|
-
var
|
|
12
|
+
var path = require('node:path');
|
|
13
13
|
|
|
14
14
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
15
|
-
function _interopNamespaceDefault(e) {
|
|
16
|
-
var n = Object.create(null);
|
|
17
|
-
if (e) {
|
|
18
|
-
Object.keys(e).forEach(function (k) {
|
|
19
|
-
if (k !== 'default') {
|
|
20
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
21
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
get: function () { return e[k]; }
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
n.default = e;
|
|
29
|
-
return Object.freeze(n);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
var prettier__namespace = /*#__PURE__*/_interopNamespaceDefault(prettier);
|
|
33
|
-
|
|
34
15
|
const initCtx = (config) => {
|
|
35
16
|
return {
|
|
36
17
|
source: "",
|
|
@@ -46,8 +27,8 @@ const initCtx = (config) => {
|
|
|
46
27
|
const getCliConfig = () => {
|
|
47
28
|
const argv = cleye.cli({
|
|
48
29
|
name: "apigen",
|
|
49
|
-
|
|
50
|
-
parameters: ["<source>", "
|
|
30
|
+
version: "0.1.1",
|
|
31
|
+
parameters: ["<source>", "[output]"],
|
|
51
32
|
flags: {
|
|
52
33
|
name: {
|
|
53
34
|
type: String,
|
|
@@ -63,7 +44,7 @@ const getCliConfig = () => {
|
|
|
63
44
|
});
|
|
64
45
|
const config = {
|
|
65
46
|
source: argv._.source,
|
|
66
|
-
output: argv._.output,
|
|
47
|
+
output: argv._.output ?? null,
|
|
67
48
|
name: argv.flags.name,
|
|
68
49
|
parseDates: argv.flags.parseDates
|
|
69
50
|
};
|
|
@@ -185,7 +166,8 @@ const Keywords = /* @__PURE__ */ new Set([
|
|
|
185
166
|
"Extract",
|
|
186
167
|
// ts keywords
|
|
187
168
|
"Date",
|
|
188
|
-
"object"
|
|
169
|
+
"object",
|
|
170
|
+
"Response"
|
|
189
171
|
// ts type names
|
|
190
172
|
]);
|
|
191
173
|
const normalizeIdentifier = (val, asVar = false) => {
|
|
@@ -520,6 +502,8 @@ const generateAst = async (ctx) => {
|
|
|
520
502
|
return { modules, types };
|
|
521
503
|
};
|
|
522
504
|
const loadSchema = async (url, upgrade = true) => {
|
|
505
|
+
if (url.startsWith("file://"))
|
|
506
|
+
url = url.substring(7);
|
|
523
507
|
const { bundle } = await redocly.bundle({
|
|
524
508
|
ref: url,
|
|
525
509
|
config: await redocly.createConfig({}),
|
|
@@ -551,31 +535,43 @@ const printCode = (nodes) => {
|
|
|
551
535
|
).replaceAll("}, ", "},\n\n");
|
|
552
536
|
};
|
|
553
537
|
const formatCode = async (code) => {
|
|
554
|
-
|
|
555
|
-
|
|
538
|
+
try {
|
|
539
|
+
const prettier = await import('prettier');
|
|
540
|
+
const options = await prettier.resolveConfig(path.join(process.cwd(), "file"));
|
|
541
|
+
return prettier.format(code, { ...options, parser: "typescript" });
|
|
542
|
+
} catch (e) {
|
|
543
|
+
return code;
|
|
544
|
+
}
|
|
556
545
|
};
|
|
557
546
|
|
|
558
547
|
const apigen = async (config) => {
|
|
559
548
|
const doc = await loadSchema(config.source);
|
|
560
549
|
const ctx = initCtx({ ...config, doc });
|
|
561
550
|
const { modules, types } = await generateAst(ctx);
|
|
562
|
-
const filepath = path.join(path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('main-
|
|
551
|
+
const filepath = path$1.join(path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('main-c2426ec2.cjs', document.baseURI).href)))), "_template.ts");
|
|
563
552
|
const file = await fs.readFile(filepath, "utf-8");
|
|
564
553
|
let code = [
|
|
565
554
|
`// Auto-generated by https://github.com/vladkens/apigen-ts`,
|
|
566
555
|
`// Source: ${config.source}
|
|
567
556
|
`,
|
|
568
|
-
|
|
557
|
+
// remove all comments expect which starts with "// apigen:"
|
|
558
|
+
...file.split("\n").filter((x) => !/\s*\/\/\s(?!apigen:)/.test(x))
|
|
569
559
|
].join("\n");
|
|
570
560
|
if (!ctx.parseDates) {
|
|
561
|
+
code = code.replace(/\s*ISO_FORMAT\s=.+$/gm, "");
|
|
571
562
|
code = code.replace(/PopulateDates.+?\n\s{2}\}/s, "");
|
|
572
563
|
code = code.replace(/this.PopulateDates\((.+)\)/, "$1");
|
|
573
564
|
}
|
|
574
565
|
code = code.replace("// apigen:modules", printCode(modules));
|
|
575
566
|
code = code.replace("// apigen:types", printCode(types));
|
|
576
567
|
code = code.replace("class ApiClient", `class ${ctx.name}`);
|
|
577
|
-
|
|
578
|
-
|
|
568
|
+
const result = await formatCode(code);
|
|
569
|
+
if (config.output === null) {
|
|
570
|
+
process.stdout.write(result);
|
|
571
|
+
} else {
|
|
572
|
+
await fs.mkdir(path$1.dirname(config.output), { recursive: true });
|
|
573
|
+
await fs.writeFile(config.output, result);
|
|
574
|
+
}
|
|
579
575
|
};
|
|
580
576
|
|
|
581
577
|
exports.apigen = apigen;
|
package/dist/main.cjs
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
require('fs/promises');
|
|
4
4
|
require('path');
|
|
5
5
|
require('url');
|
|
6
|
-
var main = require('./main-
|
|
6
|
+
var main = require('./main-c2426ec2.cjs');
|
|
7
7
|
require('cleye');
|
|
8
8
|
require('@redocly/openapi-core');
|
|
9
9
|
require('array-utils-ts');
|
|
10
10
|
require('lodash-es');
|
|
11
11
|
require('swagger2openapi');
|
|
12
12
|
require('typescript');
|
|
13
|
-
require('
|
|
13
|
+
require('node:path');
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
package/dist/main.d.cts
CHANGED
|
@@ -8,7 +8,7 @@ type OpConfig = Oas3Operation & {
|
|
|
8
8
|
type OpName = [string, string];
|
|
9
9
|
type Config = {
|
|
10
10
|
source: string;
|
|
11
|
-
output: string;
|
|
11
|
+
output: string | null;
|
|
12
12
|
name: string;
|
|
13
13
|
parseDates: boolean;
|
|
14
14
|
resolveName?: (ctx: Context, op: OpConfig, proposal: OpName) => OpName | undefined;
|
package/dist/main.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ type OpConfig = Oas3Operation & {
|
|
|
8
8
|
type OpName = [string, string];
|
|
9
9
|
type Config = {
|
|
10
10
|
source: string;
|
|
11
|
-
output: string;
|
|
11
|
+
output: string | null;
|
|
12
12
|
name: string;
|
|
13
13
|
parseDates: boolean;
|
|
14
14
|
resolveName?: (ctx: Context, op: OpConfig, proposal: OpName) => OpName | undefined;
|
package/dist/main.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import 'fs/promises';
|
|
2
2
|
import 'path';
|
|
3
3
|
import 'url';
|
|
4
|
-
export { a as apigen } from './main-
|
|
4
|
+
export { a as apigen } from './main-bbe33f1b.js';
|
|
5
5
|
import 'cleye';
|
|
6
6
|
import '@redocly/openapi-core';
|
|
7
7
|
import 'array-utils-ts';
|
|
8
8
|
import 'lodash-es';
|
|
9
9
|
import 'swagger2openapi';
|
|
10
10
|
import 'typescript';
|
|
11
|
-
import '
|
|
11
|
+
import 'node:path';
|
package/dist/main.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import 'fs/promises';
|
|
2
2
|
import 'path';
|
|
3
3
|
import 'url';
|
|
4
|
-
export { a as apigen } from './main-
|
|
4
|
+
export { a as apigen } from './main-bbe33f1b.mjs';
|
|
5
5
|
import 'cleye';
|
|
6
6
|
import '@redocly/openapi-core';
|
|
7
7
|
import 'array-utils-ts';
|
|
8
8
|
import 'lodash-es';
|
|
9
9
|
import 'swagger2openapi';
|
|
10
10
|
import 'typescript';
|
|
11
|
-
import '
|
|
11
|
+
import 'node:path';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "apigen-ts",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Vlad Pronsky <v.pronsky@gmail.com>",
|
|
7
7
|
"repository": "vladkens/apigen-ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"ci": "tsc --noEmit && yarn test-cov && yarn build"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@redocly/openapi-core": "^1.
|
|
25
|
+
"@redocly/openapi-core": "^1.6.0",
|
|
26
26
|
"@types/lodash-es": "^4.17.12",
|
|
27
27
|
"@types/swagger2openapi": "^7.0.4",
|
|
28
28
|
"array-utils-ts": "^0.1.2",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"swagger2openapi": "^7.0.8"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@types/node": "^20.10.
|
|
35
|
-
"c8": "^
|
|
34
|
+
"@types/node": "^20.10.8",
|
|
35
|
+
"c8": "^9.0.0",
|
|
36
36
|
"fetch-mock": "^9.11.0",
|
|
37
37
|
"pkgroll": "^2.0.1",
|
|
38
38
|
"prettier": "^3.1.0",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"files": [
|
|
49
49
|
"dist"
|
|
50
50
|
],
|
|
51
|
+
"main": "./dist/main.js",
|
|
51
52
|
"types": "./dist/main.d.cts",
|
|
52
53
|
"exports": {
|
|
53
54
|
"require": {
|
package/readme.md
CHANGED
|
@@ -3,31 +3,28 @@
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
5
|
[<img src="https://badgen.net/npm/v/apigen-ts" alt="version" />](https://npmjs.org/package/apigen-ts)
|
|
6
|
-
[<img src="https://github.com/vladkens/apigen-ts/workflows/test/badge.svg" alt="test status" />](https://github.com/vladkens/apigen-ts/actions)
|
|
7
6
|
[<img src="https://badgen.net/packagephobia/publish/apigen-ts" alt="size" />](https://packagephobia.now.sh/result?p=apigen-ts)
|
|
8
7
|
[<img src="https://badgen.net/npm/dm/apigen-ts" alt="downloads" />](https://npmjs.org/package/apigen-ts)
|
|
9
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)
|
|
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>
|
|
16
|
-
|
|
17
|
-
<div align="center">
|
|
18
|
-
TypeScript api client generator from OpenAPI specification
|
|
15
|
+
<div>TypeScript client generator from OpenAPI schema</div>
|
|
19
16
|
</div>
|
|
20
17
|
|
|
21
18
|
## Features
|
|
22
19
|
|
|
23
20
|
- Generates ready to use `ApiClient` with types (using `fetch`)
|
|
24
21
|
- Single output file, minimal third-party code
|
|
25
|
-
-
|
|
22
|
+
- Loads schemas from JSON / YAML, locally and remote
|
|
26
23
|
- Ability to customize `fetch` with your custom function
|
|
27
|
-
- Uses `type` instead of `interface`, no problem with declaration merging
|
|
28
24
|
- Automatic formating with Prettier
|
|
29
25
|
- Can parse dates from date-time format (`--parse-dates` flag)
|
|
30
26
|
- Support OpenAPI v2, v3, v3.1
|
|
27
|
+
- Can be used with npx as well
|
|
31
28
|
|
|
32
29
|
## Install
|
|
33
30
|
|
|
@@ -37,7 +34,7 @@ yarn install -D apigen-ts
|
|
|
37
34
|
|
|
38
35
|
## Usage
|
|
39
36
|
|
|
40
|
-
### Generate
|
|
37
|
+
### 1. Generate
|
|
41
38
|
|
|
42
39
|
```sh
|
|
43
40
|
# From url
|
|
@@ -47,11 +44,11 @@ yarn apigen-ts https://petstore3.swagger.io/api/v3/openapi.json ./api-client.ts
|
|
|
47
44
|
yarn apigen-ts ./openapi.json ./api-client.ts
|
|
48
45
|
```
|
|
49
46
|
|
|
50
|
-
Run `yarn apigen-ts --help` for more options.
|
|
47
|
+
Run `yarn apigen-ts --help` for more options. Examples of generated clients [here](./examples/).
|
|
51
48
|
|
|
52
|
-
### Import
|
|
49
|
+
### 2. Import
|
|
53
50
|
|
|
54
|
-
```
|
|
51
|
+
```ts
|
|
55
52
|
import { ApiClient } from "./api-client"
|
|
56
53
|
|
|
57
54
|
const api = new ApiClient({
|
|
@@ -60,9 +57,9 @@ const api = new ApiClient({
|
|
|
60
57
|
})
|
|
61
58
|
```
|
|
62
59
|
|
|
63
|
-
### Use
|
|
60
|
+
### 3. Use
|
|
64
61
|
|
|
65
|
-
```
|
|
62
|
+
```ts
|
|
66
63
|
// GET /pet/{petId}
|
|
67
64
|
await api.pet.getPetById(1) // -> Pet
|
|
68
65
|
|
|
@@ -77,18 +74,59 @@ await api.user.updateUser("username", { firstName: "John" })
|
|
|
77
74
|
|
|
78
75
|
### Login flow
|
|
79
76
|
|
|
80
|
-
```
|
|
77
|
+
```ts
|
|
81
78
|
const { token } = await api.auth.login({ usename, password })
|
|
82
79
|
api.Config.headers = { Authorization: token }
|
|
83
80
|
|
|
84
81
|
await api.protectedRoute.get() // here authenticated
|
|
85
82
|
```
|
|
86
83
|
|
|
87
|
-
###
|
|
84
|
+
### Automatic date parsing
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
yarn apigen-ts ./openapi.json ./api-client.ts --parse-dates
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const pet = await api.pet.getPetById(1)
|
|
92
|
+
const createdAt: Date = pet.createdAt // date parsed from string with format=date-time
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Errors handling
|
|
96
|
+
|
|
97
|
+
An exception will be thrown for all unsuccessful return codes.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
try {
|
|
101
|
+
const pet = await api.pet.getPetById(404)
|
|
102
|
+
} catch (e) {
|
|
103
|
+
console.log(e) // parse error depend of your domain model, e is awaited response.json()
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Also you can define custom function to parse error:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
class MyClient extends ApiClient {
|
|
111
|
+
async ParseError(rep: Response) {
|
|
112
|
+
// do what you want
|
|
113
|
+
return { code: "API_ERROR" }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const api = MyClient()
|
|
119
|
+
const pet = await api.pet.getPetById(404)
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.log(e) // e is { code: "API_ERROR" }
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Node.js API
|
|
88
126
|
|
|
89
127
|
Create file like `apigen.mjs` with content:
|
|
90
128
|
|
|
91
|
-
```
|
|
129
|
+
```js
|
|
92
130
|
import { apigen } from "apigen-ts"
|
|
93
131
|
|
|
94
132
|
await apigen({
|
|
@@ -109,7 +147,14 @@ await apigen({
|
|
|
109
147
|
|
|
110
148
|
Then run with: `node apigen.mjs`
|
|
111
149
|
|
|
112
|
-
##
|
|
150
|
+
## Compare
|
|
151
|
+
|
|
152
|
+
- [openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen) ([npm](https://www.npmjs.com/package/openapi-typescript-codegen)): no single file mode [#1263](https://github.com/ferdikoomen/openapi-typescript-codegen/issues/1263#issuecomment-1502890838)
|
|
153
|
+
- [openapi-typescript](https://github.com/drwpow/openapi-typescript) ([npm](https://www.npmjs.com/package/openapi-typescript)): low level api; no named types export to use in client code
|
|
154
|
+
- [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli) ([npm](https://www.npmjs.com/package/@openapitools/openapi-generator-cli)): wrapper around java lib
|
|
155
|
+
- [swagger-typescript-api](https://github.com/acacode/swagger-typescript-api) ([npm](https://www.npmjs.com/package/swagger-typescript-api)): complicated configuration; user-api breaking changes between versions
|
|
156
|
+
|
|
157
|
+
## Development
|
|
113
158
|
|
|
114
159
|
- https://ts-ast-viewer.com
|
|
115
160
|
- https://jsonschemalint.com
|