api 5.0.0-beta.3 → 5.0.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/README.md +7 -7
- package/dist/bin.js +1 -1
- package/dist/cache.d.ts +37 -2
- package/dist/cache.js +7 -26
- package/dist/cli/codegen/index.d.ts +1 -1
- package/dist/cli/codegen/language.d.ts +1 -1
- package/dist/cli/codegen/language.js +13 -0
- package/dist/cli/codegen/languages/typescript/util.d.ts +21 -0
- package/dist/cli/codegen/languages/typescript/util.js +185 -0
- package/dist/cli/codegen/languages/typescript.d.ts +31 -38
- package/dist/cli/codegen/languages/typescript.js +390 -478
- package/dist/cli/commands/install.js +6 -6
- package/dist/cli/storage.js +2 -2
- package/dist/core/errors/fetchError.d.ts +12 -0
- package/dist/core/errors/fetchError.js +36 -0
- package/dist/core/index.d.ts +11 -3
- package/dist/core/index.js +36 -11
- package/dist/core/parseResponse.d.ts +6 -1
- package/dist/core/parseResponse.js +9 -3
- package/dist/core/prepareAuth.js +47 -18
- package/dist/core/prepareParams.d.ts +0 -3
- package/dist/core/prepareParams.js +81 -57
- package/dist/fetcher.js +3 -3
- package/dist/index.js +24 -40
- package/dist/packageInfo.d.ts +1 -1
- package/dist/packageInfo.js +1 -1
- package/package.json +28 -17
- package/src/bin.ts +2 -1
- package/src/cache.ts +8 -30
- package/src/cli/codegen/index.ts +1 -1
- package/src/cli/codegen/language.ts +18 -1
- package/src/cli/codegen/languages/typescript/util.ts +183 -0
- package/src/cli/codegen/languages/typescript.ts +340 -402
- package/src/cli/commands/install.ts +6 -8
- package/src/cli/storage.ts +3 -3
- package/src/core/errors/fetchError.ts +31 -0
- package/src/core/getJSONSchemaDefaults.ts +2 -1
- package/src/core/index.ts +52 -17
- package/src/core/parseResponse.ts +8 -2
- package/src/core/prepareAuth.ts +55 -31
- package/src/core/prepareParams.ts +88 -55
- package/src/fetcher.ts +4 -3
- package/src/index.ts +24 -32
- package/src/packageInfo.ts +1 -1
- package/src/typings.d.ts +0 -1
- package/tsconfig.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -59,8 +48,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
59
48
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
60
49
|
};
|
|
61
50
|
var oas_1 = __importDefault(require("oas"));
|
|
62
|
-
var core_1 = __importDefault(require("./core"));
|
|
63
51
|
var cache_1 = __importDefault(require("./cache"));
|
|
52
|
+
var core_1 = __importDefault(require("./core"));
|
|
64
53
|
var packageInfo_1 = require("./packageInfo");
|
|
65
54
|
var Sdk = /** @class */ (function () {
|
|
66
55
|
function Sdk(uri, opts) {
|
|
@@ -77,28 +66,6 @@ var Sdk = /** @class */ (function () {
|
|
|
77
66
|
var isLoaded = false;
|
|
78
67
|
var isCached = cache.isCached();
|
|
79
68
|
var sdk = {};
|
|
80
|
-
/**
|
|
81
|
-
* Create dynamic accessors for every HTTP method that the OpenAPI specification supports.
|
|
82
|
-
*
|
|
83
|
-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#fixed-fields-7}
|
|
84
|
-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#fixed-fields-7}
|
|
85
|
-
*/
|
|
86
|
-
function loadMethods() {
|
|
87
|
-
return ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace']
|
|
88
|
-
.map(function (httpVerb) {
|
|
89
|
-
var _a;
|
|
90
|
-
return _a = {},
|
|
91
|
-
_a[httpVerb] = (function (method, path) {
|
|
92
|
-
var args = [];
|
|
93
|
-
for (var _i = 2; _i < arguments.length; _i++) {
|
|
94
|
-
args[_i - 2] = arguments[_i];
|
|
95
|
-
}
|
|
96
|
-
return core.fetch.apply(core, __spreadArray([path, method], args, false));
|
|
97
|
-
}).bind(null, httpVerb),
|
|
98
|
-
_a;
|
|
99
|
-
})
|
|
100
|
-
.reduce(function (prev, next) { return Object.assign(prev, next); });
|
|
101
|
-
}
|
|
102
69
|
/**
|
|
103
70
|
* Create dynamic accessors for every operation with a defined operation ID. If an operation
|
|
104
71
|
* does not have an operation ID it can be accessed by its `.method('/path')` accessor instead.
|
|
@@ -112,15 +79,15 @@ var Sdk = /** @class */ (function () {
|
|
|
112
79
|
return Object.values(operations);
|
|
113
80
|
})
|
|
114
81
|
.reduce(function (prev, next) { return prev.concat(next); }, [])
|
|
115
|
-
.filter(function (operation) { return operation.hasOperationId(); })
|
|
116
82
|
.reduce(function (prev, next) {
|
|
117
83
|
var _a;
|
|
118
84
|
// `getOperationId()` creates dynamic operation IDs when one isn't available but we need
|
|
119
85
|
// to know here if we actually have one present or not. The `camelCase` option here also
|
|
120
86
|
// cleans up any `operationId` that we might have into something that can be used as a
|
|
121
87
|
// valid JS method.
|
|
88
|
+
var originalOperationId = next.getOperationId();
|
|
122
89
|
var operationId = next.getOperationId({ camelCase: true });
|
|
123
|
-
|
|
90
|
+
var op = (_a = {},
|
|
124
91
|
_a[operationId] = (function (operation) {
|
|
125
92
|
var args = [];
|
|
126
93
|
for (var _i = 1; _i < arguments.length; _i++) {
|
|
@@ -128,7 +95,24 @@ var Sdk = /** @class */ (function () {
|
|
|
128
95
|
}
|
|
129
96
|
return core.fetchOperation.apply(core, __spreadArray([operation], args, false));
|
|
130
97
|
}).bind(null, next),
|
|
131
|
-
_a)
|
|
98
|
+
_a);
|
|
99
|
+
if (operationId !== originalOperationId) {
|
|
100
|
+
// If we cleaned up their operation ID into a friendly method accessor (`findPetById`
|
|
101
|
+
// versus `find pet by id`) we should still let them use the non-friendly version if
|
|
102
|
+
// they want.
|
|
103
|
+
//
|
|
104
|
+
// This work is to maintain backwards compatibility with `api@4` and does not exist
|
|
105
|
+
// within our code generated SDKs -- those only allow the cleaner camelCase
|
|
106
|
+
// `operationId` to be used.
|
|
107
|
+
op[originalOperationId] = (function (operation) {
|
|
108
|
+
var args = [];
|
|
109
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
110
|
+
args[_i - 1] = arguments[_i];
|
|
111
|
+
}
|
|
112
|
+
return core.fetchOperation.apply(core, __spreadArray([operation], args, false));
|
|
113
|
+
}).bind(null, next);
|
|
114
|
+
}
|
|
115
|
+
return Object.assign(prev, op);
|
|
132
116
|
}, {});
|
|
133
117
|
}
|
|
134
118
|
function loadFromCache() {
|
|
@@ -150,7 +134,7 @@ var Sdk = /** @class */ (function () {
|
|
|
150
134
|
case 4:
|
|
151
135
|
spec = new oas_1["default"](cachedSpec);
|
|
152
136
|
core.setSpec(spec);
|
|
153
|
-
sdk = Object.assign(sdk,
|
|
137
|
+
sdk = Object.assign(sdk, loadOperations(spec));
|
|
154
138
|
isLoaded = true;
|
|
155
139
|
return [2 /*return*/];
|
|
156
140
|
}
|
|
@@ -234,10 +218,10 @@ var Sdk = /** @class */ (function () {
|
|
|
234
218
|
core.setAuth.apply(core, values);
|
|
235
219
|
},
|
|
236
220
|
/**
|
|
237
|
-
* Optionally configure various options
|
|
221
|
+
* Optionally configure various options that the SDK allows.
|
|
238
222
|
*
|
|
239
223
|
* @param config Object of supported SDK options and toggles.
|
|
240
|
-
* @param config.
|
|
224
|
+
* @param config.timeout Override the default `fetch` request timeout of 30 seconds (30000ms).
|
|
241
225
|
*/
|
|
242
226
|
config: function (config) {
|
|
243
227
|
core.setConfig(config);
|
package/dist/packageInfo.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const PACKAGE_NAME = "api";
|
|
2
|
-
export declare const PACKAGE_VERSION = "5.0.0
|
|
2
|
+
export declare const PACKAGE_VERSION = "5.0.0";
|
package/dist/packageInfo.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "api",
|
|
3
|
-
"version": "5.0.0
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Magical SDK generation from an OpenAPI definition 🪄",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"debug:bin": "node -r ts-node/register src/bin.ts",
|
|
13
|
-
"prebuild": "rm -rf dist/; npm run
|
|
14
|
-
"prebuild.packageConfig": "node -p \"'// This file is automatically updated by the build script.\\nexport const PACKAGE_NAME = \\'' + require('./package.json').name + '\\';\\nexport const PACKAGE_VERSION = \\'' + require('./package.json').version + '\\';'\" > src/packageInfo.ts; git add src/packageInfo.ts",
|
|
13
|
+
"prebuild": "rm -rf dist/; npm run version",
|
|
15
14
|
"prepack": "npm run build",
|
|
16
|
-
"test": "nyc mocha
|
|
15
|
+
"test": "nyc mocha $(find test -name '*.test.ts' -not -path '*/smoketest.test.ts')",
|
|
16
|
+
"test:smoke": "npx mocha test/cli/codegen/languages/typescript/smoketest.test.ts",
|
|
17
|
+
"version": "node -p \"'// This file is automatically updated by the build script.\\nexport const PACKAGE_NAME = \\'' + require('./package.json').name + '\\';\\nexport const PACKAGE_VERSION = \\'' + require('./package.json').version + '\\';'\" > src/packageInfo.ts; git add src/packageInfo.ts"
|
|
17
18
|
},
|
|
18
19
|
"repository": {
|
|
19
20
|
"type": "git",
|
|
@@ -36,14 +37,14 @@
|
|
|
36
37
|
"swagger"
|
|
37
38
|
],
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"@readme/oas-to-har": "^
|
|
40
|
+
"@readme/oas-to-har": "^20.0.0",
|
|
40
41
|
"@readme/openapi-parser": "^2.2.0",
|
|
41
42
|
"caseless": "^0.12.0",
|
|
42
43
|
"chalk": "^4.1.2",
|
|
43
|
-
"commander": "^9.
|
|
44
|
+
"commander": "^9.4.0",
|
|
44
45
|
"datauri": "^4.1.0",
|
|
45
46
|
"execa": "^5.1.1",
|
|
46
|
-
"fetch-har": "^8.
|
|
47
|
+
"fetch-har": "^8.1.3",
|
|
47
48
|
"figures": "^3.2.0",
|
|
48
49
|
"find-cache-dir": "^3.3.1",
|
|
49
50
|
"form-data-encoder": "^1.7.2",
|
|
@@ -51,28 +52,37 @@
|
|
|
51
52
|
"get-stream": "^6.0.1",
|
|
52
53
|
"isomorphic-fetch": "^3.0.0",
|
|
53
54
|
"js-yaml": "^4.1.0",
|
|
54
|
-
"json-schema-to-
|
|
55
|
+
"json-schema-to-ts": "^2.5.5",
|
|
55
56
|
"json-schema-traverse": "^1.0.0",
|
|
57
|
+
"lodash.camelcase": "^4.3.0",
|
|
58
|
+
"lodash.deburr": "^4.1.0",
|
|
56
59
|
"lodash.merge": "^4.6.2",
|
|
60
|
+
"lodash.setwith": "^4.3.2",
|
|
61
|
+
"lodash.startcase": "^4.4.0",
|
|
57
62
|
"make-dir": "^3.1.0",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
63
|
+
"node-abort-controller": "^3.0.1",
|
|
64
|
+
"oas": "^20.0.0",
|
|
60
65
|
"ora": "^5.4.1",
|
|
66
|
+
"prettier": "^2.7.1",
|
|
61
67
|
"prompts": "^2.4.2",
|
|
62
68
|
"remove-undefined-objects": "^2.0.1",
|
|
63
|
-
"ssri": "^
|
|
64
|
-
"ts-morph": "^
|
|
65
|
-
"validate-npm-package-name": "^
|
|
69
|
+
"ssri": "^10.0.0",
|
|
70
|
+
"ts-morph": "^16.0.0",
|
|
71
|
+
"validate-npm-package-name": "^5.0.0"
|
|
66
72
|
},
|
|
67
73
|
"devDependencies": {
|
|
68
|
-
"@readme/oas-examples": "^5.
|
|
74
|
+
"@readme/oas-examples": "^5.7.1",
|
|
69
75
|
"@types/caseless": "^0.12.2",
|
|
70
76
|
"@types/chai": "^4.3.1",
|
|
71
77
|
"@types/find-cache-dir": "^3.2.1",
|
|
72
78
|
"@types/js-yaml": "^4.0.5",
|
|
79
|
+
"@types/lodash.camelcase": "^4.3.7",
|
|
80
|
+
"@types/lodash.deburr": "^4.1.7",
|
|
73
81
|
"@types/lodash.merge": "^4.6.7",
|
|
74
|
-
"@types/
|
|
75
|
-
"@types/
|
|
82
|
+
"@types/lodash.setwith": "^4.3.7",
|
|
83
|
+
"@types/lodash.startcase": "^4.4.7",
|
|
84
|
+
"@types/mocha": "^10.0.0",
|
|
85
|
+
"@types/prettier": "^2.7.1",
|
|
76
86
|
"@types/prompts": "^2.0.14",
|
|
77
87
|
"@types/sinon-chai": "^3.2.8",
|
|
78
88
|
"@types/ssri": "^7.1.1",
|
|
@@ -82,6 +92,7 @@
|
|
|
82
92
|
"mocha": "^10.0.0",
|
|
83
93
|
"mock-require": "^3.0.3",
|
|
84
94
|
"nyc": "^15.1.0",
|
|
95
|
+
"oas-normalize": "^7.1.0",
|
|
85
96
|
"sinon": "^14.0.0",
|
|
86
97
|
"sinon-chai": "^3.7.0",
|
|
87
98
|
"typescript": "^4.7.4",
|
|
@@ -94,5 +105,5 @@
|
|
|
94
105
|
"test/"
|
|
95
106
|
]
|
|
96
107
|
},
|
|
97
|
-
"gitHead": "
|
|
108
|
+
"gitHead": "bb044ecdb3296c24838056764553fa7f18e6d228"
|
|
98
109
|
}
|
package/src/bin.ts
CHANGED
package/src/cache.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import type { OASDocument } from 'oas/dist/rmoas.types';
|
|
2
2
|
|
|
3
|
-
import 'isomorphic-fetch';
|
|
4
|
-
import OpenAPIParser from '@readme/openapi-parser';
|
|
5
3
|
import crypto from 'crypto';
|
|
6
|
-
import findCacheDir from 'find-cache-dir';
|
|
7
4
|
import fs from 'fs';
|
|
8
5
|
import os from 'os';
|
|
9
6
|
import path from 'path';
|
|
10
|
-
import makeDir from 'make-dir';
|
|
11
7
|
|
|
12
|
-
import
|
|
8
|
+
import findCacheDir from 'find-cache-dir';
|
|
9
|
+
import 'isomorphic-fetch';
|
|
10
|
+
import makeDir from 'make-dir';
|
|
13
11
|
|
|
14
12
|
import Fetcher from './fetcher';
|
|
13
|
+
import { PACKAGE_NAME } from './packageInfo';
|
|
15
14
|
|
|
16
15
|
type CacheStore = Record<
|
|
17
16
|
string,
|
|
@@ -103,28 +102,6 @@ export default class Cache {
|
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
|
|
106
|
-
static validate(json: any) {
|
|
107
|
-
if (json.swagger) {
|
|
108
|
-
throw new Error('Sorry, this module only supports OpenAPI definitions.');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// The `validate` method handles dereferencing for us.
|
|
112
|
-
return OpenAPIParser.validate(json, {
|
|
113
|
-
dereference: {
|
|
114
|
-
// If circular `$refs` are ignored they'll remain in the API definition as `$ref: String`.
|
|
115
|
-
// This allows us to not only do easy circular reference detection but also stringify and
|
|
116
|
-
// save dereferenced API definitions back into the cache directory.
|
|
117
|
-
circular: 'ignore',
|
|
118
|
-
},
|
|
119
|
-
}).catch(err => {
|
|
120
|
-
if (/is not a valid openapi definition/i.test(err.message)) {
|
|
121
|
-
throw new Error("Sorry, that doesn't look like a valid OpenAPI definition.");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
throw err;
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
105
|
isCached() {
|
|
129
106
|
const cache = this.getCache();
|
|
130
107
|
return cache && this.uriHash in cache;
|
|
@@ -171,10 +148,11 @@ export default class Cache {
|
|
|
171
148
|
}
|
|
172
149
|
|
|
173
150
|
async load() {
|
|
174
|
-
// If the class was supplied a raw object
|
|
175
|
-
//
|
|
151
|
+
// If the class was supplied a raw object we should still validate and make sure that it's
|
|
152
|
+
// dereferenced in order for everything to function, but we shouldn't worry about saving it
|
|
153
|
+
// into the cache directory architecture.
|
|
176
154
|
if (typeof this.uri === 'object') {
|
|
177
|
-
return this.uri;
|
|
155
|
+
return Fetcher.validate(this.uri);
|
|
178
156
|
}
|
|
179
157
|
|
|
180
158
|
return this.fetcher.load().then(async spec => this.save(spec));
|
package/src/cli/codegen/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type Oas from 'oas';
|
|
2
1
|
import type Storage from '../storage';
|
|
2
|
+
import type Oas from 'oas';
|
|
3
|
+
|
|
3
4
|
import { PACKAGE_NAME, PACKAGE_VERSION } from '../../packageInfo';
|
|
4
5
|
|
|
5
6
|
export interface InstallerOptions {
|
|
@@ -35,6 +36,22 @@ export default abstract class CodeGeneratorLanguage {
|
|
|
35
36
|
// a `petstore` spec installed on api@4.2.0.
|
|
36
37
|
const info = spec.getDefinition().info;
|
|
37
38
|
this.userAgent = `${identifier}/${info.version} (${PACKAGE_NAME}/${PACKAGE_VERSION})`;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* This check is barbaric but there are a number of issues with how the `transformer` work we
|
|
42
|
+
* have in `oas` and in `.getParametersAsJSONSchema()` and `.getResponseAsJSONSchema()` that
|
|
43
|
+
* are fully crashing when attempting to codegen an SDK for an API definition that has a
|
|
44
|
+
* circular reference.
|
|
45
|
+
*
|
|
46
|
+
* In order to get v5 out the door we're not going to support this case initialy.
|
|
47
|
+
*
|
|
48
|
+
* @see {@link https://github.com/readmeio/api/issues/549}
|
|
49
|
+
*/
|
|
50
|
+
if (JSON.stringify(spec.api).includes('"$ref":"#/')) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
'Sorry, this library does not yet support generating an SDK for an OpenAPI definition that contains circular references.'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
38
55
|
}
|
|
39
56
|
|
|
40
57
|
abstract generator(): Promise<Record<string, string>>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import camelCase from 'lodash.camelcase';
|
|
2
|
+
import deburr from 'lodash.deburr';
|
|
3
|
+
import startCase from 'lodash.startcase';
|
|
4
|
+
import { format as prettier } from 'prettier';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This is a mix of reserved JS words and keywords in TypeScript that might be reserved or
|
|
8
|
+
* allowable but functionally confusing (like `let any = 'buster';`)
|
|
9
|
+
*
|
|
10
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar}
|
|
11
|
+
*/
|
|
12
|
+
const RESERVED_WORDS = [
|
|
13
|
+
'abstract',
|
|
14
|
+
'any',
|
|
15
|
+
'arguments',
|
|
16
|
+
'as',
|
|
17
|
+
'async',
|
|
18
|
+
'await',
|
|
19
|
+
'boolean',
|
|
20
|
+
'break',
|
|
21
|
+
'byte',
|
|
22
|
+
'case',
|
|
23
|
+
'catch',
|
|
24
|
+
'char',
|
|
25
|
+
'class',
|
|
26
|
+
'const',
|
|
27
|
+
'continue',
|
|
28
|
+
'constructor',
|
|
29
|
+
'debugger',
|
|
30
|
+
'default',
|
|
31
|
+
'delete',
|
|
32
|
+
'do',
|
|
33
|
+
'double',
|
|
34
|
+
'else',
|
|
35
|
+
'enum',
|
|
36
|
+
'eval',
|
|
37
|
+
'export',
|
|
38
|
+
'extends',
|
|
39
|
+
'false',
|
|
40
|
+
'final',
|
|
41
|
+
'finally',
|
|
42
|
+
'float',
|
|
43
|
+
'for',
|
|
44
|
+
'from',
|
|
45
|
+
'function',
|
|
46
|
+
'get',
|
|
47
|
+
'goto',
|
|
48
|
+
'if',
|
|
49
|
+
'implements',
|
|
50
|
+
'import',
|
|
51
|
+
'interface',
|
|
52
|
+
'in',
|
|
53
|
+
'instanceof',
|
|
54
|
+
'int',
|
|
55
|
+
'let',
|
|
56
|
+
'long',
|
|
57
|
+
'native',
|
|
58
|
+
'new',
|
|
59
|
+
'null',
|
|
60
|
+
'number',
|
|
61
|
+
'of',
|
|
62
|
+
'package',
|
|
63
|
+
'private',
|
|
64
|
+
'protected',
|
|
65
|
+
'public',
|
|
66
|
+
'module',
|
|
67
|
+
'namespace',
|
|
68
|
+
'return',
|
|
69
|
+
'set',
|
|
70
|
+
'short',
|
|
71
|
+
'static',
|
|
72
|
+
'string',
|
|
73
|
+
'super',
|
|
74
|
+
'switch',
|
|
75
|
+
'synchronized',
|
|
76
|
+
'this',
|
|
77
|
+
'throw',
|
|
78
|
+
'throws',
|
|
79
|
+
'transient',
|
|
80
|
+
'true',
|
|
81
|
+
'try',
|
|
82
|
+
'type',
|
|
83
|
+
'typeof',
|
|
84
|
+
'var',
|
|
85
|
+
'void',
|
|
86
|
+
'while',
|
|
87
|
+
'with',
|
|
88
|
+
'volatile',
|
|
89
|
+
'yield',
|
|
90
|
+
|
|
91
|
+
// These aren't reserved keywords but because we maybe codegen'ing an SDK to be used in the
|
|
92
|
+
// browser it'd be very bad if we overwrote these. This obviously doesn't account for browser APIs
|
|
93
|
+
// you can access outside of the `Window` API (like `alert()`), but we can add checks for those
|
|
94
|
+
// later if we need to.
|
|
95
|
+
'frames',
|
|
96
|
+
'global',
|
|
97
|
+
'globalThis',
|
|
98
|
+
'navigator',
|
|
99
|
+
'self',
|
|
100
|
+
'window',
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
export function formatter(content: string) {
|
|
104
|
+
return prettier(content, {
|
|
105
|
+
parser: 'typescript',
|
|
106
|
+
printWidth: 100,
|
|
107
|
+
singleQuote: true,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @see {@link https://www.30secondsofcode.org/js/s/word-wrap}
|
|
113
|
+
*/
|
|
114
|
+
export function wordWrap(str: string, max = 88) {
|
|
115
|
+
return str.replace(new RegExp(`(?![^\\n]{1,${max}}$)([^\\n]{1,${max}})\\s`, 'g'), '$1\n');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Safely escape some string characters that may break a docblock.
|
|
120
|
+
*
|
|
121
|
+
*/
|
|
122
|
+
export function docblockEscape(str: string) {
|
|
123
|
+
return str.replace(/\/\*/g, '/\\*').replace(/\*\//g, '*\\/');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Convert a string that might contain spaces or special characters to one that can safely be used
|
|
128
|
+
* as a TypeScript interface or enum name.
|
|
129
|
+
*
|
|
130
|
+
* This function has been adapted and slighty modified from `json-schema-to-typescript`.
|
|
131
|
+
*
|
|
132
|
+
* @license MIT
|
|
133
|
+
* @see {@link https://github.com/bcherny/json-schema-to-typescript}
|
|
134
|
+
*/
|
|
135
|
+
export function toSafeString(str: string) {
|
|
136
|
+
// identifiers in javaScript/ts:
|
|
137
|
+
// First character: a-zA-Z | _ | $
|
|
138
|
+
// Rest: a-zA-Z | _ | $ | 0-9
|
|
139
|
+
|
|
140
|
+
// remove accents, umlauts, ... by their basic latin letters
|
|
141
|
+
return (
|
|
142
|
+
deburr(str)
|
|
143
|
+
// if the string starts with a number, prefix it with character that typescript can accept
|
|
144
|
+
// https://github.com/bcherny/json-schema-to-typescript/issues/489
|
|
145
|
+
.replace(/^(\d){1}/, '$$1')
|
|
146
|
+
// replace chars which are not valid for typescript identifiers with whitespace
|
|
147
|
+
.replace(/(^\s*[^a-zA-Z_$])|([^a-zA-Z_$\d])/g, ' ')
|
|
148
|
+
// uppercase leading underscores followed by lowercase
|
|
149
|
+
.replace(/^_[a-z]/g, (match: string) => match.toUpperCase())
|
|
150
|
+
// remove non-leading underscores followed by lowercase (convert snake_case)
|
|
151
|
+
.replace(/_[a-z]/g, (match: string) => match.substr(1, match.length).toUpperCase())
|
|
152
|
+
// uppercase letters after digits, dollars
|
|
153
|
+
.replace(/([\d$]+[a-zA-Z])/g, (match: string) => match.toUpperCase())
|
|
154
|
+
// uppercase first letter after whitespace
|
|
155
|
+
.replace(/\s+([a-zA-Z])/g, (match: string) => match.toUpperCase().trim())
|
|
156
|
+
// remove remaining whitespace
|
|
157
|
+
.replace(/\s/g, '')
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function generateTypeName(...parts: string[]) {
|
|
162
|
+
let str;
|
|
163
|
+
|
|
164
|
+
// If the end of our string ends with something like `2XX`, the combination of `startCase` and
|
|
165
|
+
// `camelCase` will transform it into `2Xx`.
|
|
166
|
+
if (parts.length > 1) {
|
|
167
|
+
const last = parts[parts.length - 1];
|
|
168
|
+
if (last.match(/^(\d)XX$/)) {
|
|
169
|
+
str = startCase(camelCase(parts.slice(0, -1).join(' ')));
|
|
170
|
+
str += ` ${last}`;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!str) {
|
|
175
|
+
str = startCase(camelCase(parts.join(' ')));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (RESERVED_WORDS.includes(str.toLowerCase())) {
|
|
179
|
+
str = `$${str}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return toSafeString(str);
|
|
183
|
+
}
|