api 6.0.0 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cache.d.ts +4 -1
- package/dist/cli/codegen/languages/typescript/util.d.ts +0 -1
- package/dist/cli/codegen/languages/typescript/util.js +1 -10
- package/dist/cli/codegen/languages/typescript.d.ts +22 -5
- package/dist/cli/codegen/languages/typescript.js +53 -17
- package/dist/cli/commands/install.js +33 -31
- package/dist/cli/storage.d.ts +10 -10
- package/dist/cli/storage.js +14 -1
- package/dist/core/errors/fetchError.d.ts +4 -4
- package/dist/core/getJSONSchemaDefaults.d.ts +0 -1
- package/dist/core/getJSONSchemaDefaults.js +0 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/prepareAuth.d.ts +1 -1
- package/dist/core/prepareParams.js +8 -5
- package/dist/core/prepareServer.d.ts +0 -3
- package/dist/core/prepareServer.js +0 -3
- package/dist/fetcher.js +0 -1
- package/dist/index.js +0 -1
- package/dist/packageInfo.d.ts +1 -1
- package/dist/packageInfo.js +1 -1
- package/package.json +9 -22
- package/src/cache.ts +4 -1
- package/src/cli/codegen/index.ts +1 -1
- package/src/cli/codegen/language.ts +1 -1
- package/src/cli/codegen/languages/typescript/util.ts +0 -9
- package/src/cli/codegen/languages/typescript.ts +89 -27
- package/src/cli/commands/install.ts +14 -17
- package/src/cli/lib/prompt.ts +1 -1
- package/src/cli/storage.ts +27 -10
- package/src/core/errors/fetchError.ts +4 -4
- package/src/core/getJSONSchemaDefaults.ts +2 -3
- package/src/core/index.ts +7 -2
- package/src/core/prepareAuth.ts +4 -4
- package/src/core/prepareParams.ts +15 -10
- package/src/core/prepareServer.ts +0 -3
- package/src/fetcher.ts +2 -3
- package/src/index.ts +0 -1
- package/src/packageInfo.ts +1 -1
- package/tsconfig.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Or you can use it dynamically (though you won't have fancy TypeScript types to h
|
|
|
40
40
|
|
|
41
41
|
```js
|
|
42
42
|
const petstore = require('api')(
|
|
43
|
-
'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json'
|
|
43
|
+
'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json',
|
|
44
44
|
);
|
|
45
45
|
|
|
46
46
|
petstore.listPets().then(({ data }) => {
|
package/dist/cache.d.ts
CHANGED
|
@@ -3,8 +3,11 @@ import 'isomorphic-fetch';
|
|
|
3
3
|
import Fetcher from './fetcher';
|
|
4
4
|
type CacheStore = Record<string, {
|
|
5
5
|
hash: string;
|
|
6
|
-
path?: string;
|
|
7
6
|
original: string | OASDocument;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Deprecated in v4.5.0 in favor of `hash`.
|
|
9
|
+
*/
|
|
10
|
+
path?: string;
|
|
8
11
|
title?: string;
|
|
9
12
|
version?: string;
|
|
10
13
|
}>;
|
|
@@ -3,11 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
exports.__esModule = true;
|
|
6
|
-
exports.generateTypeName = exports.toSafeString = exports.docblockEscape = exports.wordWrap =
|
|
6
|
+
exports.generateTypeName = exports.toSafeString = exports.docblockEscape = exports.wordWrap = void 0;
|
|
7
7
|
var lodash_camelcase_1 = __importDefault(require("lodash.camelcase"));
|
|
8
8
|
var lodash_deburr_1 = __importDefault(require("lodash.deburr"));
|
|
9
9
|
var lodash_startcase_1 = __importDefault(require("lodash.startcase"));
|
|
10
|
-
var prettier_1 = require("prettier");
|
|
11
10
|
/**
|
|
12
11
|
* This is a mix of reserved JS words and keywords in TypeScript that might be reserved or
|
|
13
12
|
* allowable but functionally confusing (like `let any = 'buster';`)
|
|
@@ -103,14 +102,6 @@ var RESERVED_WORDS = [
|
|
|
103
102
|
'self',
|
|
104
103
|
'window',
|
|
105
104
|
];
|
|
106
|
-
function formatter(content) {
|
|
107
|
-
return (0, prettier_1.format)(content, {
|
|
108
|
-
parser: 'typescript',
|
|
109
|
-
printWidth: 100,
|
|
110
|
-
singleQuote: true
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
exports.formatter = formatter;
|
|
114
105
|
/**
|
|
115
106
|
* @see {@link https://www.30secondsofcode.org/js/s/word-wrap}
|
|
116
107
|
*/
|
|
@@ -2,19 +2,22 @@ import type Storage from '../../storage';
|
|
|
2
2
|
import type { InstallerOptions } from '../language';
|
|
3
3
|
import type Oas from 'oas';
|
|
4
4
|
import type { Operation } from 'oas';
|
|
5
|
-
import type { ClassDeclaration } from 'ts-morph';
|
|
5
|
+
import type { ClassDeclaration, JSDocStructure, JSDocTagStructure, OptionalKind } from 'ts-morph';
|
|
6
6
|
import { Project } from 'ts-morph';
|
|
7
7
|
import CodeGeneratorLanguage from '../language';
|
|
8
8
|
export interface TSGeneratorOptions {
|
|
9
|
-
outputJS?: boolean;
|
|
10
9
|
compilerTarget?: 'cjs' | 'esm';
|
|
10
|
+
outputJS?: boolean;
|
|
11
11
|
}
|
|
12
12
|
interface OperationTypeHousing {
|
|
13
|
+
operation: Operation;
|
|
13
14
|
types: {
|
|
14
15
|
params?: false | Record<'body' | 'formData' | 'metadata', string>;
|
|
15
|
-
responses?: Record<string,
|
|
16
|
+
responses?: Record<string | number, {
|
|
17
|
+
description?: string;
|
|
18
|
+
type: string;
|
|
19
|
+
}>;
|
|
16
20
|
};
|
|
17
|
-
operation: Operation;
|
|
18
21
|
}
|
|
19
22
|
export default class TSGenerator extends CodeGeneratorLanguage {
|
|
20
23
|
project: Project;
|
|
@@ -57,6 +60,17 @@ export default class TSGenerator extends CodeGeneratorLanguage {
|
|
|
57
60
|
* @see {@link https://npm.im/json-schema-to-ts}
|
|
58
61
|
*/
|
|
59
62
|
createTypesFile(): import("ts-morph").SourceFile;
|
|
63
|
+
/**
|
|
64
|
+
* Add a new JSDoc `@tag` to an existing docblock.
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
static addTagToDocblock(docblock: OptionalKind<JSDocStructure>, tag: OptionalKind<JSDocTagStructure>): {
|
|
68
|
+
tags: OptionalKind<JSDocTagStructure>[];
|
|
69
|
+
description?: string | import("ts-morph").WriterFunction;
|
|
70
|
+
leadingTrivia?: string | import("ts-morph").WriterFunction | (string | import("ts-morph").WriterFunction)[];
|
|
71
|
+
trailingTrivia?: string | import("ts-morph").WriterFunction | (string | import("ts-morph").WriterFunction)[];
|
|
72
|
+
kind?: import("ts-morph").StructureKind.JSDoc;
|
|
73
|
+
};
|
|
60
74
|
/**
|
|
61
75
|
* Create operation accessors on the SDK.
|
|
62
76
|
*
|
|
@@ -83,7 +97,10 @@ export default class TSGenerator extends CodeGeneratorLanguage {
|
|
|
83
97
|
*
|
|
84
98
|
*/
|
|
85
99
|
prepareResponseTypesForOperation(operation: Operation, operationId: string): {
|
|
86
|
-
[x: string]:
|
|
100
|
+
[x: string]: {
|
|
101
|
+
type: string;
|
|
102
|
+
description: any;
|
|
103
|
+
};
|
|
87
104
|
};
|
|
88
105
|
/**
|
|
89
106
|
* Add a given schema into our schema dataset that we'll be be exporting as types.
|
|
@@ -243,7 +243,7 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
243
243
|
// user will have `.d.ts` files for them instead.
|
|
244
244
|
return {};
|
|
245
245
|
}
|
|
246
|
-
var code =
|
|
246
|
+
var code = sourceFile.text;
|
|
247
247
|
if (file === 'index.js' && _this.compilerTarget === 'cjs') {
|
|
248
248
|
/**
|
|
249
249
|
* There's an annoying quirk with `ts-morph` where if we're exporting a default export
|
|
@@ -268,7 +268,7 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
268
268
|
return [2 /*return*/, __spreadArray(__spreadArray([], this.project.getSourceFiles().map(function (sourceFile) {
|
|
269
269
|
var _a;
|
|
270
270
|
return (_a = {},
|
|
271
|
-
_a[sourceFile.getBaseName()] =
|
|
271
|
+
_a[sourceFile.getBaseName()] = sourceFile.getFullText(),
|
|
272
272
|
_a);
|
|
273
273
|
}), true), this.project
|
|
274
274
|
.emitToMemory({ emitOnlyDtsFiles: true })
|
|
@@ -276,7 +276,7 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
276
276
|
.map(function (sourceFile) {
|
|
277
277
|
var _a;
|
|
278
278
|
return (_a = {},
|
|
279
|
-
_a[path_1["default"].basename(sourceFile.filePath)] =
|
|
279
|
+
_a[path_1["default"].basename(sourceFile.filePath)] = sourceFile.text,
|
|
280
280
|
_a);
|
|
281
281
|
}), true).reduce(function (prev, next) { return Object.assign(prev, next); })];
|
|
282
282
|
});
|
|
@@ -471,6 +471,16 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
471
471
|
});
|
|
472
472
|
return sourceFile;
|
|
473
473
|
};
|
|
474
|
+
/**
|
|
475
|
+
* Add a new JSDoc `@tag` to an existing docblock.
|
|
476
|
+
*
|
|
477
|
+
*/
|
|
478
|
+
TSGenerator.addTagToDocblock = function (docblock, tag) {
|
|
479
|
+
var _a;
|
|
480
|
+
var tags = (_a = docblock.tags) !== null && _a !== void 0 ? _a : [];
|
|
481
|
+
tags.push(tag);
|
|
482
|
+
return __assign(__assign({}, docblock), { tags: tags });
|
|
483
|
+
};
|
|
474
484
|
/**
|
|
475
485
|
* Create operation accessors on the SDK.
|
|
476
486
|
*
|
|
@@ -495,7 +505,10 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
495
505
|
return writer;
|
|
496
506
|
};
|
|
497
507
|
if (summary && description) {
|
|
498
|
-
docblock
|
|
508
|
+
docblock = TSGenerator.addTagToDocblock(docblock, {
|
|
509
|
+
tagName: 'summary',
|
|
510
|
+
text: (0, util_1.docblockEscape)((0, util_1.wordWrap)(summary))
|
|
511
|
+
});
|
|
499
512
|
}
|
|
500
513
|
}
|
|
501
514
|
var hasOptionalBody = false;
|
|
@@ -523,9 +536,9 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
523
536
|
}
|
|
524
537
|
var returnType = 'Promise<FetchResponse<number, unknown>>';
|
|
525
538
|
if (responseTypes) {
|
|
526
|
-
|
|
539
|
+
var returnTypes = Object.entries(responseTypes)
|
|
527
540
|
.map(function (_a) {
|
|
528
|
-
var status = _a[0],
|
|
541
|
+
var status = _a[0], _b = _a[1], responseDescription = _b.description, responseType = _b.type;
|
|
529
542
|
if (status.toLowerCase() === 'default') {
|
|
530
543
|
return "FetchResponse<number, ".concat(responseType, ">");
|
|
531
544
|
}
|
|
@@ -536,17 +549,42 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
536
549
|
// it and should instead fall back to treating it as an unknown number.
|
|
537
550
|
return "FetchResponse<number, ".concat(responseType, ">");
|
|
538
551
|
}
|
|
552
|
+
if (Number(statusPrefix) >= 4) {
|
|
553
|
+
docblock = TSGenerator.addTagToDocblock(docblock, {
|
|
554
|
+
tagName: 'throws',
|
|
555
|
+
text: "FetchError<".concat(status, ", ").concat(responseType, ">").concat(responseDescription ? (0, util_1.docblockEscape)((0, util_1.wordWrap)(" ".concat(responseDescription))) : '')
|
|
556
|
+
});
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
539
559
|
_this.usesHTTPMethodRangeInterface = true;
|
|
540
560
|
return "FetchResponse<HTTPMethodRange<".concat(statusPrefix, "00, ").concat(statusPrefix, "99>, ").concat(responseType, ">");
|
|
541
561
|
}
|
|
562
|
+
// 400 and 500 status code families are thrown as exceptions so adding them as a possible
|
|
563
|
+
// return type isn't valid.
|
|
564
|
+
if (Number(status) >= 400) {
|
|
565
|
+
docblock = TSGenerator.addTagToDocblock(docblock, {
|
|
566
|
+
tagName: 'throws',
|
|
567
|
+
text: "FetchError<".concat(status, ", ").concat(responseType, ">").concat(responseDescription ? (0, util_1.docblockEscape)((0, util_1.wordWrap)(" ".concat(responseDescription))) : '')
|
|
568
|
+
});
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
542
571
|
return "FetchResponse<".concat(status, ", ").concat(responseType, ">");
|
|
543
572
|
})
|
|
544
|
-
.
|
|
573
|
+
.filter(Boolean)
|
|
574
|
+
.join(' | ');
|
|
575
|
+
// If all of our documented responses are for error status codes then all we can document for
|
|
576
|
+
// anything else that might happen is `unknown`.
|
|
577
|
+
returnType = "Promise<".concat(returnTypes.length ? returnTypes : 'FetchResponse<number, unknown>', ">");
|
|
545
578
|
}
|
|
579
|
+
var shouldAddAltTypedOverloads = Object.keys(parameters).length === 2 && hasOptionalBody && !hasOptionalMetadata;
|
|
546
580
|
var operationIdAccessor = this.sdk.addMethod({
|
|
547
581
|
name: operationId,
|
|
548
582
|
returnType: returnType,
|
|
549
|
-
|
|
583
|
+
// If we're going to be creating typed method overloads for optional body an metadata handling
|
|
584
|
+
// we should only add a docblock to the first overload we create because IDE Intellisense will
|
|
585
|
+
// always use that and adding a docblock to all three will bloat the SDK with unused and
|
|
586
|
+
// unsurfaced method documentation.
|
|
587
|
+
docs: shouldAddAltTypedOverloads ? null : Object.keys(docblock).length ? [docblock] : null,
|
|
550
588
|
statements: function (writer) {
|
|
551
589
|
/**
|
|
552
590
|
* @example return this.core.fetch('/pet/findByStatus', 'get', body, metadata);
|
|
@@ -564,7 +602,7 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
564
602
|
fetchStmt.write(', ');
|
|
565
603
|
}
|
|
566
604
|
fetchStmt.write(arg.name);
|
|
567
|
-
if (
|
|
605
|
+
if (i !== totalParams - 1) {
|
|
568
606
|
fetchStmt.write(', ');
|
|
569
607
|
}
|
|
570
608
|
});
|
|
@@ -576,10 +614,6 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
576
614
|
// If we have both body and metadata parameters but only body is optional we need to create
|
|
577
615
|
// a couple function overloads as Typescript doesn't let us have an optional method parameter
|
|
578
616
|
// come before one that's required.
|
|
579
|
-
//
|
|
580
|
-
// None of these accessor overloads will receive a docblock because the original will have
|
|
581
|
-
// that covered.
|
|
582
|
-
var shouldAddAltTypedOverloads = Object.keys(parameters).length === 2 && hasOptionalBody && !hasOptionalMetadata;
|
|
583
617
|
if (shouldAddAltTypedOverloads) {
|
|
584
618
|
// Create an overload that has both `body` and `metadata` parameters as required.
|
|
585
619
|
operationIdAccessor.addOverload({
|
|
@@ -593,8 +627,7 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
593
627
|
// Create an overload that just has a single `metadata` parameter.
|
|
594
628
|
operationIdAccessor.addOverload({
|
|
595
629
|
parameters: [__assign({}, parameters.metadata)],
|
|
596
|
-
returnType: returnType
|
|
597
|
-
docs: Object.keys(docblock).length ? [docblock] : null
|
|
630
|
+
returnType: returnType
|
|
598
631
|
});
|
|
599
632
|
// Create an overload that has both `body` and `metadata` parameters as optional. Even though
|
|
600
633
|
// our `metadata` parameter is actually required for this operation this is the only way we're
|
|
@@ -746,7 +779,7 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
746
779
|
var res = Object.entries(schemas)
|
|
747
780
|
.map(function (_a) {
|
|
748
781
|
var _b;
|
|
749
|
-
var status = _a[0],
|
|
782
|
+
var status = _a[0], _c = _a[1], description = _c.description, schema = _c.schema;
|
|
750
783
|
var typeName;
|
|
751
784
|
if (typeof schema === 'string' && schema.startsWith('::convert::')) {
|
|
752
785
|
// If this schema is a string and has our conversion prefix then we've already created
|
|
@@ -763,7 +796,10 @@ var TSGenerator = /** @class */ (function (_super) {
|
|
|
763
796
|
return _b = {},
|
|
764
797
|
// Types are prefixed with `types.` because that's how we're importing them from
|
|
765
798
|
// `types.d.ts`.
|
|
766
|
-
_b[status] =
|
|
799
|
+
_b[status] = {
|
|
800
|
+
type: "types.".concat(typeName),
|
|
801
|
+
description: description
|
|
802
|
+
},
|
|
767
803
|
_b;
|
|
768
804
|
})
|
|
769
805
|
.reduce(function (prev, next) { return Object.assign(prev, next); }, {});
|
|
@@ -43,7 +43,6 @@ var commander_1 = require("commander");
|
|
|
43
43
|
var figures_1 = __importDefault(require("figures"));
|
|
44
44
|
var oas_1 = __importDefault(require("oas"));
|
|
45
45
|
var ora_1 = __importDefault(require("ora"));
|
|
46
|
-
var validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
47
46
|
var fetcher_1 = __importDefault(require("../../fetcher"));
|
|
48
47
|
var codegen_1 = __importDefault(require("../codegen"));
|
|
49
48
|
var prompt_1 = __importDefault(require("../lib/prompt"));
|
|
@@ -55,6 +54,7 @@ cmd
|
|
|
55
54
|
.name('install')
|
|
56
55
|
.description('install an API SDK into your codebase')
|
|
57
56
|
.argument('<uri>', 'an API to install')
|
|
57
|
+
.option('-i, --identifier <identifier>', 'API identifier (eg. `@api/petstore`)')
|
|
58
58
|
.addOption(new commander_1.Option('-l, --lang <language>', 'SDK language').choices([
|
|
59
59
|
'js',
|
|
60
60
|
'js-cjs',
|
|
@@ -107,10 +107,17 @@ cmd
|
|
|
107
107
|
// @todo
|
|
108
108
|
// logger(`It looks like you already have this API installed. Would you like to update it?`);
|
|
109
109
|
}
|
|
110
|
-
if (!
|
|
110
|
+
if (!options.identifier) return [3 /*break*/, 6];
|
|
111
|
+
// `Storage.isIdentifierValid` will throw an exception if an identifier is invalid.
|
|
112
|
+
if (storage_1["default"].isIdentifierValid(options.identifier)) {
|
|
113
|
+
identifier = options.identifier;
|
|
114
|
+
}
|
|
115
|
+
return [3 /*break*/, 9];
|
|
116
|
+
case 6:
|
|
117
|
+
if (!fetcher_1["default"].isAPIRegistryUUID(uri)) return [3 /*break*/, 7];
|
|
111
118
|
identifier = fetcher_1["default"].getProjectPrefixFromRegistryUUID(uri);
|
|
112
|
-
return [3 /*break*/,
|
|
113
|
-
case
|
|
119
|
+
return [3 /*break*/, 9];
|
|
120
|
+
case 7: return [4 /*yield*/, (0, prompt_1["default"])({
|
|
114
121
|
type: 'text',
|
|
115
122
|
name: 'value',
|
|
116
123
|
message: 'What would you like to identify this API as? This will be how you import the SDK. (e.g. entering `petstore` would result in `@api/petstore`)',
|
|
@@ -118,23 +125,18 @@ cmd
|
|
|
118
125
|
if (!value) {
|
|
119
126
|
return false;
|
|
120
127
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return "\"".concat(value, "\" is already taken in your `.api/` directory. Please enter another identifier.");
|
|
128
|
+
try {
|
|
129
|
+
return storage_1["default"].isIdentifierValid(value, true);
|
|
124
130
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
// `prompts` doesn't support surfacing multiple errors in a `validate` call so we can
|
|
128
|
-
// only surface the first to the user.
|
|
129
|
-
return isValidForNPM.errors[0];
|
|
131
|
+
catch (err) {
|
|
132
|
+
return err.message;
|
|
130
133
|
}
|
|
131
|
-
return true;
|
|
132
134
|
}
|
|
133
135
|
})];
|
|
134
|
-
case 7:
|
|
135
|
-
(identifier = (_a.sent()).value);
|
|
136
|
-
_a.label = 8;
|
|
137
136
|
case 8:
|
|
137
|
+
(identifier = (_a.sent()).value);
|
|
138
|
+
_a.label = 9;
|
|
139
|
+
case 9:
|
|
138
140
|
if (!identifier) {
|
|
139
141
|
(0, logger_1["default"])('You must tell us what you would like to identify this API as in order to install it.', true);
|
|
140
142
|
process.exit(1);
|
|
@@ -153,7 +155,7 @@ cmd
|
|
|
153
155
|
(0, logger_1["default"])(err.message, true);
|
|
154
156
|
process.exit(1);
|
|
155
157
|
})];
|
|
156
|
-
case
|
|
158
|
+
case 10:
|
|
157
159
|
oas = _a.sent();
|
|
158
160
|
// @todo look for a prettier config and if we find one ask them if we should use it
|
|
159
161
|
spinner = (0, ora_1["default"])('Generating your SDK').start();
|
|
@@ -169,7 +171,7 @@ cmd
|
|
|
169
171
|
(0, logger_1["default"])(err.message, true);
|
|
170
172
|
process.exit(1);
|
|
171
173
|
})];
|
|
172
|
-
case
|
|
174
|
+
case 11:
|
|
173
175
|
sdkSource = _a.sent();
|
|
174
176
|
spinner = (0, ora_1["default"])('Saving your SDK into your codebase').start();
|
|
175
177
|
return [4 /*yield*/, storage
|
|
@@ -182,15 +184,15 @@ cmd
|
|
|
182
184
|
(0, logger_1["default"])(err.message, true);
|
|
183
185
|
process.exit(1);
|
|
184
186
|
})];
|
|
185
|
-
case
|
|
187
|
+
case 12:
|
|
186
188
|
_a.sent();
|
|
187
|
-
if (!generator.hasRequiredPackages()) return [3 /*break*/,
|
|
189
|
+
if (!generator.hasRequiredPackages()) return [3 /*break*/, 18];
|
|
188
190
|
(0, logger_1["default"])("".concat(figures_1["default"].warning, " This generator requires some packages to be installed alongside it:"));
|
|
189
191
|
Object.entries(generator.requiredPackages).forEach(function (_a) {
|
|
190
192
|
var pkg = _a[0], pkgInfo = _a[1];
|
|
191
193
|
(0, logger_1["default"])(" ".concat(figures_1["default"].pointerSmall, " ").concat(pkg, ": ").concat(pkgInfo.reason, " ").concat(pkgInfo.url));
|
|
192
194
|
});
|
|
193
|
-
if (!!options.yes) return [3 /*break*/,
|
|
195
|
+
if (!!options.yes) return [3 /*break*/, 14];
|
|
194
196
|
return [4 /*yield*/, (0, prompt_1["default"])({
|
|
195
197
|
type: 'confirm',
|
|
196
198
|
name: 'value',
|
|
@@ -204,27 +206,27 @@ cmd
|
|
|
204
206
|
process.exit(1);
|
|
205
207
|
}
|
|
206
208
|
})];
|
|
207
|
-
case 12:
|
|
208
|
-
_a.sent();
|
|
209
|
-
_a.label = 13;
|
|
210
209
|
case 13:
|
|
211
|
-
|
|
210
|
+
_a.sent();
|
|
212
211
|
_a.label = 14;
|
|
213
212
|
case 14:
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
spinner = (0, ora_1["default"])('Installing required packages').start();
|
|
214
|
+
_a.label = 15;
|
|
216
215
|
case 15:
|
|
216
|
+
_a.trys.push([15, 17, , 18]);
|
|
217
|
+
return [4 /*yield*/, generator.installer(storage)];
|
|
218
|
+
case 16:
|
|
217
219
|
_a.sent();
|
|
218
220
|
spinner.succeed(spinner.text);
|
|
219
|
-
return [3 /*break*/,
|
|
220
|
-
case
|
|
221
|
+
return [3 /*break*/, 18];
|
|
222
|
+
case 17:
|
|
221
223
|
err_1 = _a.sent();
|
|
222
224
|
// @todo cleanup installed files
|
|
223
225
|
spinner.fail(spinner.text);
|
|
224
226
|
(0, logger_1["default"])(err_1.message, true);
|
|
225
227
|
process.exit(1);
|
|
226
|
-
return [3 /*break*/,
|
|
227
|
-
case
|
|
228
|
+
return [3 /*break*/, 18];
|
|
229
|
+
case 18:
|
|
228
230
|
(0, logger_1["default"])('🚀 All done!');
|
|
229
231
|
return [2 /*return*/];
|
|
230
232
|
}
|
package/dist/cli/storage.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export default class Storage {
|
|
|
23
23
|
static getDefaultLockfile(): Lockfile;
|
|
24
24
|
static generateIntegrityHash(definition: OASDocument): string;
|
|
25
25
|
static getLockfile(): Lockfile;
|
|
26
|
+
static isIdentifierValid(identifier: string, prefixWithAPINamespace?: boolean): boolean;
|
|
26
27
|
static isInLockFile(search: {
|
|
27
28
|
identifier?: string;
|
|
28
29
|
source?: string;
|
|
@@ -61,17 +62,16 @@ export default class Storage {
|
|
|
61
62
|
* ├── openapi.json
|
|
62
63
|
* └── package.json
|
|
63
64
|
*
|
|
64
|
-
* @param spec
|
|
65
65
|
*/
|
|
66
66
|
save(spec: OASDocument): OASDocument;
|
|
67
67
|
}
|
|
68
68
|
export interface Lockfile {
|
|
69
|
+
apis: LockfileAPI[];
|
|
69
70
|
/**
|
|
70
71
|
* The `api.json` schema version. This will only ever change if we introduce breaking changes to
|
|
71
72
|
* this store.
|
|
72
73
|
*/
|
|
73
74
|
version: '1.0';
|
|
74
|
-
apis: LockfileAPI[];
|
|
75
75
|
}
|
|
76
76
|
export interface LockfileAPI {
|
|
77
77
|
/**
|
|
@@ -82,13 +82,11 @@ export interface LockfileAPI {
|
|
|
82
82
|
*/
|
|
83
83
|
identifier: string;
|
|
84
84
|
/**
|
|
85
|
-
* The
|
|
85
|
+
* The version of `api` that was used to install this SDK.
|
|
86
86
|
*
|
|
87
|
-
* @example
|
|
88
|
-
* @example ./petstore.json
|
|
89
|
-
* @example @developers/v2.0#nysezql0wwo236
|
|
87
|
+
* @example 5.0.0
|
|
90
88
|
*/
|
|
91
|
-
|
|
89
|
+
installerVersion: string;
|
|
92
90
|
/**
|
|
93
91
|
* An integrity hash that will be used to determine on `npx api update` calls if the API has
|
|
94
92
|
* changed since the SDK was last generated.
|
|
@@ -97,9 +95,11 @@ export interface LockfileAPI {
|
|
|
97
95
|
*/
|
|
98
96
|
integrity: string;
|
|
99
97
|
/**
|
|
100
|
-
* The
|
|
98
|
+
* The original source that was used to generate the SDK with.
|
|
101
99
|
*
|
|
102
|
-
* @example
|
|
100
|
+
* @example https://raw.githubusercontent.com/readmeio/oas-examples/main/3.0/json/petstore-simple.json
|
|
101
|
+
* @example ./petstore.json
|
|
102
|
+
* @example @developers/v2.0#nysezql0wwo236
|
|
103
103
|
*/
|
|
104
|
-
|
|
104
|
+
source: string;
|
|
105
105
|
}
|
package/dist/cli/storage.js
CHANGED
|
@@ -43,6 +43,7 @@ var fs_1 = __importDefault(require("fs"));
|
|
|
43
43
|
var path_1 = __importDefault(require("path"));
|
|
44
44
|
var make_dir_1 = __importDefault(require("make-dir"));
|
|
45
45
|
var ssri_1 = __importDefault(require("ssri"));
|
|
46
|
+
var validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
46
47
|
var fetcher_1 = __importDefault(require("../fetcher"));
|
|
47
48
|
var packageInfo_1 = require("../packageInfo");
|
|
48
49
|
var Storage = /** @class */ (function () {
|
|
@@ -128,6 +129,19 @@ var Storage = /** @class */ (function () {
|
|
|
128
129
|
}
|
|
129
130
|
return Storage.lockfile;
|
|
130
131
|
};
|
|
132
|
+
Storage.isIdentifierValid = function (identifier, prefixWithAPINamespace) {
|
|
133
|
+
// Is this identifier already in storage?
|
|
134
|
+
if (Storage.isInLockFile({ identifier: identifier })) {
|
|
135
|
+
throw new Error("\"".concat(identifier, "\" is already taken in your `.api/` directory. Please try another identifier."));
|
|
136
|
+
}
|
|
137
|
+
var isValidForNPM = (0, validate_npm_package_name_1["default"])(prefixWithAPINamespace ? "@api/".concat(identifier) : identifier);
|
|
138
|
+
if (!isValidForNPM.validForNewPackages) {
|
|
139
|
+
// `prompts` doesn't support surfacing multiple errors in a `validate` call so we can only
|
|
140
|
+
// surface the first to the user.
|
|
141
|
+
throw new Error("Identifier cannot be used for an NPM package: ".concat(isValidForNPM.errors[0]));
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
};
|
|
131
145
|
Storage.isInLockFile = function (search) {
|
|
132
146
|
// Because this method may run before we initialize a new storage object we should make sure
|
|
133
147
|
// that we have a storage directory present.
|
|
@@ -221,7 +235,6 @@ var Storage = /** @class */ (function () {
|
|
|
221
235
|
* ├── openapi.json
|
|
222
236
|
* └── package.json
|
|
223
237
|
*
|
|
224
|
-
* @param spec
|
|
225
238
|
*/
|
|
226
239
|
Storage.prototype.save = function (spec) {
|
|
227
240
|
if (!this.identifier) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
declare class FetchError extends Error {
|
|
1
|
+
declare class FetchError<Status = number, Data = unknown> extends Error {
|
|
2
2
|
/** HTTP Status */
|
|
3
|
-
status:
|
|
3
|
+
status: Status;
|
|
4
4
|
/** The content of the response. */
|
|
5
|
-
data:
|
|
5
|
+
data: Data;
|
|
6
6
|
/** The Headers of the response. */
|
|
7
7
|
headers: Headers;
|
|
8
8
|
/** The raw `Response` object. */
|
|
9
9
|
res: Response;
|
|
10
|
-
constructor(status:
|
|
10
|
+
constructor(status: Status, data: Data, headers: Headers, res: Response);
|
|
11
11
|
}
|
|
12
12
|
export default FetchError;
|
|
@@ -8,7 +8,6 @@ import type { SchemaWrapper } from 'oas/dist/operation/get-parameters-as-json-sc
|
|
|
8
8
|
*
|
|
9
9
|
* @todo This is a good candidate to be moved into a core `oas` library method.
|
|
10
10
|
* @see {@link https://github.com/mdornseif/json-schema-default}
|
|
11
|
-
* @param jsonSchemas
|
|
12
11
|
*/
|
|
13
12
|
export default function getJSONSchemaDefaults(jsonSchemas: SchemaWrapper[]): {
|
|
14
13
|
[x: string]: Record<string, unknown>;
|
|
@@ -13,7 +13,6 @@ var json_schema_traverse_1 = __importDefault(require("json-schema-traverse"));
|
|
|
13
13
|
*
|
|
14
14
|
* @todo This is a good candidate to be moved into a core `oas` library method.
|
|
15
15
|
* @see {@link https://github.com/mdornseif/json-schema-default}
|
|
16
|
-
* @param jsonSchemas
|
|
17
16
|
*/
|
|
18
17
|
function getJSONSchemaDefaults(jsonSchemas) {
|
|
19
18
|
return jsonSchemas
|
package/dist/core/index.d.ts
CHANGED
|
@@ -16,9 +16,9 @@ export interface ConfigOptions {
|
|
|
16
16
|
}
|
|
17
17
|
export interface FetchResponse<status, data> {
|
|
18
18
|
data: data;
|
|
19
|
-
status: status;
|
|
20
19
|
headers: Headers;
|
|
21
20
|
res: Response;
|
|
21
|
+
status: status;
|
|
22
22
|
}
|
|
23
23
|
type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N ? Acc[number] : Enumerate<N, [...Acc, Acc['length']]>;
|
|
24
24
|
export type HTTPMethodRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>;
|
|
@@ -82,7 +82,7 @@ function isObject(thing) {
|
|
|
82
82
|
return typeof thing === 'object' && thing !== null && !Array.isArray(thing);
|
|
83
83
|
}
|
|
84
84
|
function isPrimitive(obj) {
|
|
85
|
-
return
|
|
85
|
+
return obj === null || typeof obj === 'number' || typeof obj === 'string';
|
|
86
86
|
}
|
|
87
87
|
function merge(src, target) {
|
|
88
88
|
if (Array.isArray(target)) {
|
|
@@ -343,6 +343,7 @@ function prepareParams(operation, body, metadata) {
|
|
|
343
343
|
if (typeof metadata === 'object' && !isEmpty(metadata)) {
|
|
344
344
|
if (paramName in metadata) {
|
|
345
345
|
value = metadata[paramName];
|
|
346
|
+
metadataHeaderParam = paramName;
|
|
346
347
|
}
|
|
347
348
|
else if (param["in"] === 'header') {
|
|
348
349
|
// Headers are sent case-insensitive so we need to make sure that we're properly
|
|
@@ -387,10 +388,7 @@ function prepareParams(operation, body, metadata) {
|
|
|
387
388
|
// If there's any leftover metadata that hasn't been moved into form data for this request we
|
|
388
389
|
// need to move it or else it'll get tossed.
|
|
389
390
|
if (!isEmpty(metadata)) {
|
|
390
|
-
if (
|
|
391
|
-
params.formData = merge(params.formData, metadata);
|
|
392
|
-
}
|
|
393
|
-
else if (typeof metadata === 'object') {
|
|
391
|
+
if (typeof metadata === 'object') {
|
|
394
392
|
// If the user supplied an `accept` or `authorization` header themselves we should allow it
|
|
395
393
|
// through. Normally these headers are automatically handled by `@readme/oas-to-har` but in
|
|
396
394
|
// the event that maybe the user wants to return XML for an API that normally returns JSON
|
|
@@ -400,9 +398,14 @@ function prepareParams(operation, body, metadata) {
|
|
|
400
398
|
var headerParam = Object.keys(metadata).find(function (m) { return m.toLowerCase() === headerName; });
|
|
401
399
|
if (headerParam) {
|
|
402
400
|
params.header[headerName] = metadata[headerParam];
|
|
401
|
+
// eslint-disable-next-line no-param-reassign
|
|
402
|
+
delete metadata[headerParam];
|
|
403
403
|
}
|
|
404
404
|
});
|
|
405
405
|
}
|
|
406
|
+
if (operation.isFormUrlEncoded()) {
|
|
407
|
+
params.formData = merge(params.formData, metadata);
|
|
408
|
+
}
|
|
406
409
|
else {
|
|
407
410
|
// Any other remaining unused metadata will be unused because we don't know where to place
|
|
408
411
|
// it in the request.
|
|
@@ -3,9 +3,6 @@ import type Oas from 'oas';
|
|
|
3
3
|
* With an SDK server config and an instance of OAS we should extract and prepare the server and
|
|
4
4
|
* any server variables to be supplied to `@readme/oas-to-har`.
|
|
5
5
|
*
|
|
6
|
-
* @param spec
|
|
7
|
-
* @param url
|
|
8
|
-
* @param variables
|
|
9
6
|
*/
|
|
10
7
|
export default function prepareServer(spec: Oas, url: string, variables?: Record<string, string | number>): false | {
|
|
11
8
|
selected: number;
|
|
@@ -10,9 +10,6 @@ function stripTrailingSlash(url) {
|
|
|
10
10
|
* With an SDK server config and an instance of OAS we should extract and prepare the server and
|
|
11
11
|
* any server variables to be supplied to `@readme/oas-to-har`.
|
|
12
12
|
*
|
|
13
|
-
* @param spec
|
|
14
|
-
* @param url
|
|
15
|
-
* @param variables
|
|
16
13
|
*/
|
|
17
14
|
function prepareServer(spec, url, variables) {
|
|
18
15
|
if (variables === void 0) { variables = {}; }
|
package/dist/fetcher.js
CHANGED
|
@@ -158,7 +158,6 @@ var Fetcher = /** @class */ (function () {
|
|
|
158
158
|
* @example @petstore/v1.0#n6kvf10vakpemvplx
|
|
159
159
|
* @example @petstore#n6kvf10vakpemvplx
|
|
160
160
|
*/
|
|
161
|
-
// eslint-disable-next-line unicorn/no-unsafe-regex
|
|
162
161
|
Fetcher.registryUUIDRegex = /^@(?<project>[a-zA-Z0-9-_]+)(\/?(?<version>.+))?#(?<uuid>[a-z0-9]+)$/;
|
|
163
162
|
return Fetcher;
|
|
164
163
|
}());
|