@loopback/rest-explorer 2.1.1 → 2.2.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/CHANGELOG.md +35 -0
- package/README.md +41 -8
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/rest-explorer.component.js +30 -26
- package/dist/rest-explorer.component.js.map +1 -1
- package/dist/rest-explorer.controller.d.ts +1 -0
- package/dist/rest-explorer.controller.js +76 -68
- package/dist/rest-explorer.controller.js.map +1 -1
- package/dist/rest-explorer.keys.d.ts +2 -2
- package/dist/rest-explorer.keys.js +1 -0
- package/dist/rest-explorer.keys.js.map +1 -1
- package/dist/rest-explorer.types.d.ts +1 -0
- package/package.json +15 -15
- package/src/rest-explorer.controller.ts +5 -0
- package/src/rest-explorer.keys.ts +4 -4
- package/src/rest-explorer.types.ts +3 -0
- package/templates/index.html.ejs +1 -1
- package/index.d.ts +0 -6
- package/index.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,41 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.2.2](https://github.com/strongloop/loopback-next/compare/@loopback/rest-explorer@2.2.1...@loopback/rest-explorer@2.2.2) (2020-05-20)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @loopback/rest-explorer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [2.2.1](https://github.com/strongloop/loopback-next/compare/@loopback/rest-explorer@2.2.0...@loopback/rest-explorer@2.2.1) (2020-05-19)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @loopback/rest-explorer
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# [2.2.0](https://github.com/strongloop/loopback-next/compare/@loopback/rest-explorer@2.1.2...@loopback/rest-explorer@2.2.0) (2020-05-07)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* demo customize the swagger ui theme ([695ba58](https://github.com/strongloop/loopback-next/commit/695ba58fda37763467c07016bdaa15a7399cd0e6))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## [2.1.2](https://github.com/strongloop/loopback-next/compare/@loopback/rest-explorer@2.1.1...@loopback/rest-explorer@2.1.2) (2020-04-29)
|
|
34
|
+
|
|
35
|
+
**Note:** Version bump only for package @loopback/rest-explorer
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
6
41
|
## [2.1.1](https://github.com/strongloop/loopback-next/compare/@loopback/rest-explorer@2.1.0...@loopback/rest-explorer@2.1.1) (2020-04-23)
|
|
7
42
|
|
|
8
43
|
**Note:** Version bump only for package @loopback/rest-explorer
|
package/README.md
CHANGED
|
@@ -44,14 +44,6 @@ this.bind(RestExplorerBindings.CONFIG).to({
|
|
|
44
44
|
});
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
_NOTE: The Explorer UI's visual style is not customizable yet. Our recommended
|
|
48
|
-
solution is to create a fork of this module, make any style changes in the fork
|
|
49
|
-
and publish the modified module under a different name. The
|
|
50
|
-
[GitHub issue #2023](https://github.com/strongloop/loopback-next/issues/2023) is
|
|
51
|
-
requesting a configuration option for customizing the visual style, please
|
|
52
|
-
up-vote the issue and/or join the discussion if you are interested in this
|
|
53
|
-
feature._
|
|
54
|
-
|
|
55
47
|
### Advanced Configuration and Reverse Proxies
|
|
56
48
|
|
|
57
49
|
By default, the component will add an additional OpenAPI spec endpoint, in the
|
|
@@ -139,6 +131,47 @@ needed in this situation, such as passing a non-standard header from your
|
|
|
139
131
|
reverse proxy to tell the app the external path, and custom code in your app to
|
|
140
132
|
make the app and explorer aware of this.
|
|
141
133
|
|
|
134
|
+
### Customizing Swagger UI Theme
|
|
135
|
+
|
|
136
|
+
The Explorer UI’s visual style can be customized by configuring the
|
|
137
|
+
`swaggerThemeFile` property. Here is the steps to do it:
|
|
138
|
+
|
|
139
|
+
First, provide your own Swagger-UI theme file in a public folder. For example,
|
|
140
|
+
in the
|
|
141
|
+
[Todo example](https://github.com/strongloop/loopback-next/tree/master/examples/todo)
|
|
142
|
+
application:
|
|
143
|
+
|
|
144
|
+
Its `/public` folder is set up as the default home page with url `/`. Copy a
|
|
145
|
+
swagger theme file `theme-newspaper.css` to be under `/public`.
|
|
146
|
+
|
|
147
|
+
Then configure the `swaggerThemeFile` field to be the relative path to home page
|
|
148
|
+
as `/theme-newspaper.css`:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
export class TodoListApplication extends BootMixin(
|
|
152
|
+
ServiceMixin(RepositoryMixin(RestApplication)),
|
|
153
|
+
) {
|
|
154
|
+
constructor(options: ApplicationConfig = {}) {
|
|
155
|
+
// ...
|
|
156
|
+
|
|
157
|
+
// customize the swagger-ui
|
|
158
|
+
this.configure(RestExplorerBindings.COMPONENT).to({
|
|
159
|
+
// Keep the theme file in the `public` dir of the app
|
|
160
|
+
// If required create a dir and keep the file, just specify the path
|
|
161
|
+
swaggerThemeFile: '/theme-newspaper.css',
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// ...
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
When the application runs, the explorer template will load the
|
|
170
|
+
`theme-newspaper.css` file as its theme.
|
|
171
|
+
|
|
172
|
+
Here is a repository that contains popular Swagger-UI themes:
|
|
173
|
+
https://github.com/ostranme/swagger-ui-themes.
|
|
174
|
+
|
|
142
175
|
## Contributions
|
|
143
176
|
|
|
144
177
|
- [Guidelines](https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md)
|
package/dist/index.js
CHANGED
|
@@ -17,4 +17,5 @@ const tslib_1 = require("tslib");
|
|
|
17
17
|
*/
|
|
18
18
|
tslib_1.__exportStar(require("./rest-explorer.component"), exports);
|
|
19
19
|
tslib_1.__exportStar(require("./rest-explorer.keys"), exports);
|
|
20
|
+
tslib_1.__exportStar(require("./rest-explorer.types"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,uCAAuC;AACvC,+CAA+C;AAC/C,gEAAgE;;;AAEhE;;;;;;;;;GASG;AAEH,oEAA0C;AAC1C,+DAAqC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,uCAAuC;AACvC,+CAA+C;AAC/C,gEAAgE;;;AAEhE;;;;;;;;;GASG;AAEH,oEAA0C;AAC1C,+DAAqC;AACrC,gEAAsC"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// This file is licensed under the MIT License.
|
|
5
5
|
// License text available at https://opensource.org/licenses/MIT
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RestExplorerComponent = void 0;
|
|
7
8
|
const tslib_1 = require("tslib");
|
|
8
9
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
10
|
const context_1 = require("@loopback/context");
|
|
@@ -15,32 +16,35 @@ const swaggerUI = require('swagger-ui-dist');
|
|
|
15
16
|
/**
|
|
16
17
|
* A component providing a self-hosted API Explorer.
|
|
17
18
|
*/
|
|
18
|
-
let RestExplorerComponent = class
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
let RestExplorerComponent = /** @class */ (() => {
|
|
20
|
+
let RestExplorerComponent = class RestExplorerComponent {
|
|
21
|
+
constructor(application, restExplorerConfig = {}) {
|
|
22
|
+
var _a;
|
|
23
|
+
this.application = application;
|
|
24
|
+
const explorerPath = (_a = restExplorerConfig.path) !== null && _a !== void 0 ? _a : '/explorer';
|
|
25
|
+
this.registerControllerRoute('get', explorerPath, 'indexRedirect');
|
|
26
|
+
this.registerControllerRoute('get', explorerPath + '/', 'index');
|
|
27
|
+
if (restExplorerConfig.useSelfHostedSpec !== false) {
|
|
28
|
+
this.registerControllerRoute('get', explorerPath + '/openapi.json', 'spec');
|
|
29
|
+
}
|
|
30
|
+
application.static(explorerPath, swaggerUI.getAbsoluteFSPath());
|
|
31
|
+
// Disable redirect to externally hosted API explorer
|
|
32
|
+
application.restServer.config.apiExplorer = { disabled: true };
|
|
27
33
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
tslib_1.__metadata("design:paramtypes", [rest_1.RestApplication, Object])
|
|
44
|
-
], RestExplorerComponent);
|
|
34
|
+
registerControllerRoute(verb, path, methodName) {
|
|
35
|
+
this.application.route(verb, path, {
|
|
36
|
+
'x-visibility': 'undocumented',
|
|
37
|
+
responses: {},
|
|
38
|
+
}, rest_explorer_controller_1.ExplorerController, rest_1.createControllerFactoryForClass(rest_explorer_controller_1.ExplorerController), methodName);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
RestExplorerComponent = tslib_1.__decorate([
|
|
42
|
+
context_1.bind({ tags: { [context_1.ContextTags.KEY]: rest_explorer_keys_1.RestExplorerBindings.COMPONENT.key } }),
|
|
43
|
+
tslib_1.__param(0, context_1.inject(core_1.CoreBindings.APPLICATION_INSTANCE)),
|
|
44
|
+
tslib_1.__param(1, context_1.config()),
|
|
45
|
+
tslib_1.__metadata("design:paramtypes", [rest_1.RestApplication, Object])
|
|
46
|
+
], RestExplorerComponent);
|
|
47
|
+
return RestExplorerComponent;
|
|
48
|
+
})();
|
|
45
49
|
exports.RestExplorerComponent = RestExplorerComponent;
|
|
46
50
|
//# sourceMappingURL=rest-explorer.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-explorer.component.js","sourceRoot":"","sources":["../src/rest-explorer.component.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,uCAAuC;AACvC,+CAA+C;AAC/C,gEAAgE
|
|
1
|
+
{"version":3,"file":"rest-explorer.component.js","sourceRoot":"","sources":["../src/rest-explorer.component.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,uCAAuC;AACvC,+CAA+C;AAC/C,gEAAgE;;;;AAEhE,6DAA6D;AAC7D,+CAAoE;AACpE,yCAAuD;AACvD,yCAAgF;AAChF,yEAA8D;AAC9D,6DAA0D;AAG1D,MAAM,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE7C;;GAEG;AAEH;IAAA,IAAa,qBAAqB,GAAlC,MAAa,qBAAqB;QAChC,YAEU,WAA4B,EAEpC,qBAAyC,EAAE;;YAFnC,gBAAW,GAAX,WAAW,CAAiB;YAIpC,MAAM,YAAY,SAAG,kBAAkB,CAAC,IAAI,mCAAI,WAAW,CAAC;YAE5D,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;YACnE,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,GAAG,EAAE,OAAO,CAAC,CAAC;YACjE,IAAI,kBAAkB,CAAC,iBAAiB,KAAK,KAAK,EAAE;gBAClD,IAAI,CAAC,uBAAuB,CAC1B,KAAK,EACL,YAAY,GAAG,eAAe,EAC9B,MAAM,CACP,CAAC;aACH;YAED,WAAW,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAC;YAEhE,qDAAqD;YACrD,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,GAAG,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC;QAC/D,CAAC;QAEO,uBAAuB,CAC7B,IAAY,EACZ,IAAY,EACZ,UAAkB;YAElB,IAAI,CAAC,WAAW,CAAC,KAAK,CACpB,IAAI,EACJ,IAAI,EACJ;gBACE,cAAc,EAAE,cAAc;gBAC9B,SAAS,EAAE,EAAE;aACd,EACD,6CAAkB,EAClB,sCAA+B,CAAC,6CAAkB,CAAC,EACnD,UAAU,CACX,CAAC;QACJ,CAAC;KACF,CAAA;IA1CY,qBAAqB;QADjC,cAAI,CAAC,EAAC,IAAI,EAAE,EAAC,CAAC,qBAAW,CAAC,GAAG,CAAC,EAAE,yCAAoB,CAAC,SAAS,CAAC,GAAG,EAAC,EAAC,CAAC;QAGjE,mBAAA,gBAAM,CAAC,mBAAY,CAAC,oBAAoB,CAAC,CAAA;QAEzC,mBAAA,gBAAM,EAAE,CAAA;iDADY,sBAAe;OAH3B,qBAAqB,CA0CjC;IAAD,4BAAC;KAAA;AA1CY,sDAAqB"}
|
|
@@ -8,6 +8,7 @@ export declare class ExplorerController {
|
|
|
8
8
|
static readonly OPENAPI_FORM: OpenApiSpecForm;
|
|
9
9
|
private openApiSpecUrl;
|
|
10
10
|
private useSelfHostedSpec;
|
|
11
|
+
private swaggerThemeFile;
|
|
11
12
|
constructor(restConfig: (Partial<import("@loopback/rest").RestServerResolvedOptions> & import("@loopback/http-server").HttpOptions) | (Partial<import("@loopback/rest").RestServerResolvedOptions> & import("@loopback/http-server").HttpsOptions) | undefined, explorerConfig: RestExplorerConfig | undefined, serverBasePath: string, restServer: RestServer, requestContext: RequestContext);
|
|
12
13
|
indexRedirect(): void;
|
|
13
14
|
index(): void;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// This file is licensed under the MIT License.
|
|
5
5
|
// License text available at https://opensource.org/licenses/MIT
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ExplorerController = void 0;
|
|
7
8
|
const tslib_1 = require("tslib");
|
|
8
9
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
10
|
const context_1 = require("@loopback/context");
|
|
@@ -16,79 +17,86 @@ const rest_explorer_keys_1 = require("./rest-explorer.keys");
|
|
|
16
17
|
const indexHtml = path_1.default.resolve(__dirname, '../templates/index.html.ejs');
|
|
17
18
|
const template = fs_1.default.readFileSync(indexHtml, 'utf-8');
|
|
18
19
|
const templateFn = ejs_1.default.compile(template);
|
|
19
|
-
let ExplorerController = class
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
let url = request.originalUrl || request.url;
|
|
30
|
-
// be safe against path-modifying reverse proxies by generating the redirect
|
|
31
|
-
// as a _relative_ URL
|
|
32
|
-
const lastSlash = url.lastIndexOf('/');
|
|
33
|
-
if (lastSlash >= 0) {
|
|
34
|
-
url = './' + url.substr(lastSlash + 1) + '/';
|
|
20
|
+
let ExplorerController = /** @class */ (() => {
|
|
21
|
+
let ExplorerController = class ExplorerController {
|
|
22
|
+
constructor(restConfig = {}, explorerConfig = {}, serverBasePath, restServer, requestContext) {
|
|
23
|
+
var _a;
|
|
24
|
+
this.serverBasePath = serverBasePath;
|
|
25
|
+
this.restServer = restServer;
|
|
26
|
+
this.requestContext = requestContext;
|
|
27
|
+
this.useSelfHostedSpec = explorerConfig.useSelfHostedSpec !== false;
|
|
28
|
+
this.openApiSpecUrl = this.getOpenApiSpecUrl(restConfig);
|
|
29
|
+
this.swaggerThemeFile = (_a = explorerConfig.swaggerThemeFile) !== null && _a !== void 0 ? _a : './swagger-ui.css';
|
|
35
30
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// OpenAPI endpoints ignore basePath but do honor mountPath
|
|
45
|
-
let rootPath = this.requestContext.request.baseUrl;
|
|
46
|
-
if (this.serverBasePath &&
|
|
47
|
-
this.serverBasePath !== '/' &&
|
|
48
|
-
rootPath.endsWith(this.serverBasePath)) {
|
|
49
|
-
rootPath = rootPath.slice(0, -this.serverBasePath.length);
|
|
31
|
+
indexRedirect() {
|
|
32
|
+
const { request, response } = this.requestContext;
|
|
33
|
+
let url = request.originalUrl || request.url;
|
|
34
|
+
// be safe against path-modifying reverse proxies by generating the redirect
|
|
35
|
+
// as a _relative_ URL
|
|
36
|
+
const lastSlash = url.lastIndexOf('/');
|
|
37
|
+
if (lastSlash >= 0) {
|
|
38
|
+
url = './' + url.substr(lastSlash + 1) + '/';
|
|
50
39
|
}
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
response.redirect(301, url);
|
|
41
|
+
}
|
|
42
|
+
index() {
|
|
43
|
+
const swaggerThemeFile = this.swaggerThemeFile;
|
|
44
|
+
let openApiSpecUrl = this.openApiSpecUrl;
|
|
45
|
+
// if using self-hosted openapi spec, then the path to use is always the
|
|
46
|
+
// exact relative path, and no base path logic needs to be applied
|
|
47
|
+
if (!this.useSelfHostedSpec) {
|
|
48
|
+
// baseURL is composed from mountPath and basePath
|
|
49
|
+
// OpenAPI endpoints ignore basePath but do honor mountPath
|
|
50
|
+
let rootPath = this.requestContext.request.baseUrl;
|
|
51
|
+
if (this.serverBasePath &&
|
|
52
|
+
this.serverBasePath !== '/' &&
|
|
53
|
+
rootPath.endsWith(this.serverBasePath)) {
|
|
54
|
+
rootPath = rootPath.slice(0, -this.serverBasePath.length);
|
|
55
|
+
}
|
|
56
|
+
if (rootPath && rootPath !== '/') {
|
|
57
|
+
openApiSpecUrl = rootPath + openApiSpecUrl;
|
|
58
|
+
}
|
|
53
59
|
}
|
|
60
|
+
const data = {
|
|
61
|
+
openApiSpecUrl,
|
|
62
|
+
swaggerThemeFile,
|
|
63
|
+
};
|
|
64
|
+
const homePage = templateFn(data);
|
|
65
|
+
this.requestContext.response
|
|
66
|
+
.status(200)
|
|
67
|
+
.contentType('text/html')
|
|
68
|
+
.send(homePage);
|
|
69
|
+
}
|
|
70
|
+
spec() {
|
|
71
|
+
return this.restServer.getApiSpec(this.requestContext);
|
|
54
72
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
.
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
spec() {
|
|
65
|
-
return this.restServer.getApiSpec(this.requestContext);
|
|
66
|
-
}
|
|
67
|
-
getOpenApiSpecUrl(restConfig) {
|
|
68
|
-
var _a, _b;
|
|
69
|
-
if (this.useSelfHostedSpec) {
|
|
70
|
-
return './' + ExplorerController.OPENAPI_RELATIVE_URL;
|
|
73
|
+
getOpenApiSpecUrl(restConfig) {
|
|
74
|
+
var _a, _b;
|
|
75
|
+
if (this.useSelfHostedSpec) {
|
|
76
|
+
return './' + ExplorerController.OPENAPI_RELATIVE_URL;
|
|
77
|
+
}
|
|
78
|
+
const openApiConfig = (_a = restConfig.openApiSpec) !== null && _a !== void 0 ? _a : {};
|
|
79
|
+
const endpointMapping = (_b = openApiConfig.endpointMapping) !== null && _b !== void 0 ? _b : {};
|
|
80
|
+
const endpoint = Object.keys(endpointMapping).find(k => isOpenApiV3Json(endpointMapping[k]));
|
|
81
|
+
return endpoint !== null && endpoint !== void 0 ? endpoint : '/openapi.json';
|
|
71
82
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
ExplorerController
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
tslib_1.__metadata("design:paramtypes", [Object, Object, String, rest_1.RestServer,
|
|
90
|
-
rest_1.RequestContext])
|
|
91
|
-
], ExplorerController);
|
|
83
|
+
};
|
|
84
|
+
ExplorerController.OPENAPI_RELATIVE_URL = 'openapi.json';
|
|
85
|
+
ExplorerController.OPENAPI_FORM = Object.freeze({
|
|
86
|
+
version: '3.0.0',
|
|
87
|
+
format: 'json',
|
|
88
|
+
});
|
|
89
|
+
ExplorerController = tslib_1.__decorate([
|
|
90
|
+
tslib_1.__param(0, context_1.inject(rest_1.RestBindings.CONFIG, { optional: true })),
|
|
91
|
+
tslib_1.__param(1, context_1.config({ fromBinding: rest_explorer_keys_1.RestExplorerBindings.COMPONENT })),
|
|
92
|
+
tslib_1.__param(2, context_1.inject(rest_1.RestBindings.BASE_PATH)),
|
|
93
|
+
tslib_1.__param(3, context_1.inject(rest_1.RestBindings.SERVER)),
|
|
94
|
+
tslib_1.__param(4, context_1.inject(rest_1.RestBindings.Http.CONTEXT)),
|
|
95
|
+
tslib_1.__metadata("design:paramtypes", [Object, Object, String, rest_1.RestServer,
|
|
96
|
+
rest_1.RequestContext])
|
|
97
|
+
], ExplorerController);
|
|
98
|
+
return ExplorerController;
|
|
99
|
+
})();
|
|
92
100
|
exports.ExplorerController = ExplorerController;
|
|
93
101
|
function isOpenApiV3Json(mapping) {
|
|
94
102
|
return (mapping.version === ExplorerController.OPENAPI_FORM.version &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-explorer.controller.js","sourceRoot":"","sources":["../src/rest-explorer.controller.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,uCAAuC;AACvC,+CAA+C;AAC/C,gEAAgE
|
|
1
|
+
{"version":3,"file":"rest-explorer.controller.js","sourceRoot":"","sources":["../src/rest-explorer.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BindingKey } from '@loopback/context';
|
|
1
|
+
import { BindingAddress, BindingKey } from '@loopback/context';
|
|
2
2
|
import { RestExplorerComponent } from './rest-explorer.component';
|
|
3
3
|
import { RestExplorerConfig } from './rest-explorer.types';
|
|
4
4
|
/**
|
|
@@ -15,5 +15,5 @@ export declare namespace RestExplorerBindings {
|
|
|
15
15
|
* We recommend `ctx.configure(RestExplorerBindings.COMPONENT)` to be used
|
|
16
16
|
* instead of `ctx.bind(RestExplorerBindings.CONFIG)`.
|
|
17
17
|
*/
|
|
18
|
-
const CONFIG:
|
|
18
|
+
const CONFIG: BindingAddress<RestExplorerConfig>;
|
|
19
19
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// This file is licensed under the MIT License.
|
|
5
5
|
// License text available at https://opensource.org/licenses/MIT
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RestExplorerBindings = void 0;
|
|
7
8
|
const context_1 = require("@loopback/context");
|
|
8
9
|
/**
|
|
9
10
|
* Binding keys used by this component.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-explorer.keys.js","sourceRoot":"","sources":["../src/rest-explorer.keys.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,uCAAuC;AACvC,+CAA+C;AAC/C,gEAAgE
|
|
1
|
+
{"version":3,"file":"rest-explorer.keys.js","sourceRoot":"","sources":["../src/rest-explorer.keys.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,uCAAuC;AACvC,+CAA+C;AAC/C,gEAAgE;;;AAEhE,+CAA6D;AAI7D;;GAEG;AACH,IAAiB,oBAAoB,CAgBpC;AAhBD,WAAiB,oBAAoB;IACnC;;OAEG;IACU,8BAAS,GAAG,oBAAU,CAAC,MAAM,CACxC,kCAAkC,CACnC,CAAC;IACF;;;;;OAKG;IACU,2BAAM,GAAuC,oBAAU,CAAC,iBAAiB,CAEpF,qBAAA,SAAS,CAAC,CAAC;AACf,CAAC,EAhBgB,oBAAoB,GAApB,4BAAoB,KAApB,4BAAoB,QAgBpC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopback/rest-explorer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "LoopBack's API Explorer",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
5
7
|
"engines": {
|
|
6
8
|
"node": ">=10"
|
|
7
9
|
},
|
|
@@ -16,20 +18,20 @@
|
|
|
16
18
|
"copyright.owner": "IBM Corp.",
|
|
17
19
|
"license": "MIT",
|
|
18
20
|
"dependencies": {
|
|
19
|
-
"@loopback/context": "^3.
|
|
20
|
-
"@loopback/core": "^2.
|
|
21
|
-
"@loopback/rest": "^
|
|
22
|
-
"ejs": "^3.
|
|
23
|
-
"swagger-ui-dist": "^3.25.
|
|
24
|
-
"tslib": "^
|
|
21
|
+
"@loopback/context": "^3.8.1",
|
|
22
|
+
"@loopback/core": "^2.7.0",
|
|
23
|
+
"@loopback/rest": "^5.0.1",
|
|
24
|
+
"ejs": "^3.1.3",
|
|
25
|
+
"swagger-ui-dist": "^3.25.3",
|
|
26
|
+
"tslib": "^2.0.0"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
|
-
"@loopback/build": "^5.
|
|
28
|
-
"@loopback/eslint-config": "^
|
|
29
|
-
"@loopback/testlab": "^3.1.
|
|
30
|
-
"@types/ejs": "^3.0.
|
|
29
|
+
"@loopback/build": "^5.4.1",
|
|
30
|
+
"@loopback/eslint-config": "^7.0.1",
|
|
31
|
+
"@loopback/testlab": "^3.1.5",
|
|
32
|
+
"@types/ejs": "^3.0.4",
|
|
31
33
|
"@types/express": "^4.17.6",
|
|
32
|
-
"@types/node": "^10.17.
|
|
34
|
+
"@types/node": "^10.17.24",
|
|
33
35
|
"express": "^4.17.1"
|
|
34
36
|
},
|
|
35
37
|
"keywords": [
|
|
@@ -39,8 +41,6 @@
|
|
|
39
41
|
],
|
|
40
42
|
"files": [
|
|
41
43
|
"README.md",
|
|
42
|
-
"index.js",
|
|
43
|
-
"index.d.ts",
|
|
44
44
|
"dist",
|
|
45
45
|
"src",
|
|
46
46
|
"!*/__tests__",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"url": "https://github.com/strongloop/loopback-next.git",
|
|
55
55
|
"directory": "packages/rest-explorer"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "62aea854bf85c5a5995b59e6908fe5409f7eea96"
|
|
58
58
|
}
|
|
@@ -32,6 +32,7 @@ export class ExplorerController {
|
|
|
32
32
|
|
|
33
33
|
private openApiSpecUrl: string;
|
|
34
34
|
private useSelfHostedSpec: boolean;
|
|
35
|
+
private swaggerThemeFile: string;
|
|
35
36
|
|
|
36
37
|
constructor(
|
|
37
38
|
@inject(RestBindings.CONFIG, {optional: true})
|
|
@@ -44,6 +45,8 @@ export class ExplorerController {
|
|
|
44
45
|
) {
|
|
45
46
|
this.useSelfHostedSpec = explorerConfig.useSelfHostedSpec !== false;
|
|
46
47
|
this.openApiSpecUrl = this.getOpenApiSpecUrl(restConfig);
|
|
48
|
+
this.swaggerThemeFile =
|
|
49
|
+
explorerConfig.swaggerThemeFile ?? './swagger-ui.css';
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
indexRedirect() {
|
|
@@ -59,6 +62,7 @@ export class ExplorerController {
|
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
index() {
|
|
65
|
+
const swaggerThemeFile = this.swaggerThemeFile;
|
|
62
66
|
let openApiSpecUrl = this.openApiSpecUrl;
|
|
63
67
|
|
|
64
68
|
// if using self-hosted openapi spec, then the path to use is always the
|
|
@@ -81,6 +85,7 @@ export class ExplorerController {
|
|
|
81
85
|
}
|
|
82
86
|
const data = {
|
|
83
87
|
openApiSpecUrl,
|
|
88
|
+
swaggerThemeFile,
|
|
84
89
|
};
|
|
85
90
|
|
|
86
91
|
const homePage = templateFn(data);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
-
import {BindingKey} from '@loopback/context';
|
|
6
|
+
import {BindingAddress, BindingKey} from '@loopback/context';
|
|
7
7
|
import {RestExplorerComponent} from './rest-explorer.component';
|
|
8
8
|
import {RestExplorerConfig} from './rest-explorer.types';
|
|
9
9
|
|
|
@@ -23,7 +23,7 @@ export namespace RestExplorerBindings {
|
|
|
23
23
|
* We recommend `ctx.configure(RestExplorerBindings.COMPONENT)` to be used
|
|
24
24
|
* instead of `ctx.bind(RestExplorerBindings.CONFIG)`.
|
|
25
25
|
*/
|
|
26
|
-
export const CONFIG = BindingKey.buildKeyForConfig<
|
|
27
|
-
|
|
28
|
-
);
|
|
26
|
+
export const CONFIG: BindingAddress<RestExplorerConfig> = BindingKey.buildKeyForConfig<
|
|
27
|
+
RestExplorerConfig
|
|
28
|
+
>(COMPONENT);
|
|
29
29
|
}
|
package/templates/index.html.ejs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="UTF-8">
|
|
7
7
|
<title>LoopBack API Explorer</title>
|
|
8
|
-
<link rel="stylesheet" type="text/css" href="
|
|
8
|
+
<link rel="stylesheet" type="text/css" href="<%- swaggerThemeFile %>">
|
|
9
9
|
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
|
10
10
|
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
|
11
11
|
<style>
|
package/index.d.ts
DELETED
package/index.js
DELETED