From 7ee8703ff51d3c13cf8490e5a33a3fd61a2ed7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 1 Jul 2015 18:09:38 +0200 Subject: [PATCH] Rework the module to a loopback component Rework the exported function to conform to the component convention: var loopback = require('loopback'); var explorer = require('loopback-explorer'); var app = loopback(); explorer(app, options); Allow users to mount explorer as a middleware too: app.use('/explorer', explorer.routes(app, options)); - drop dependency on express - drop support for loopback 1.x - add a new option "mountPath" to specify where to mount the explorer UI and swagger metadata - describe upgrading from v1.x in README --- README.md | 40 ++++++++++++++++++++++++++++++++++++++-- index.js | 37 ++++++++++++++++++++++++------------- package.json | 1 - test/explorer.test.js | 35 ++++++++++++++++++++++++++++------- test/swagger.test.js | 3 +-- 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 9ef49eb..de39f8b 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,43 @@ var Product = loopback.Model.extend('product'); Product.attachTo(loopback.memory()); app.model(Product); -app.use('/explorer', explorer(app, {basePath: '/api'})); app.use('/api', loopback.rest()); + +// Register explorer using component-centric API: +explorer(app, { basePath: '/api', mountPath: '/explorer' }); +// Alternatively, register as a middleware: +app.use('/explorer', explorer.routes(app, { basePath: '/api' })); + console.log("Explorer mounted at localhost:" + port + "/explorer"); app.listen(port); ``` +## Upgrading from v1.x + +To upgrade your application using loopback-explorer version 1.x, just replace +`explorer()` with `explorer.routes()` in your server script: + +```js +var explorer = require('loopback-explorer'); + +// v1.x - does not work anymore +app.use('/explorer', explorer(app, options); +// v2.x +app.use('/explorer', explorer.routes(app, options)); +``` + +In applications scaffolded by `slc loopback`, the idiomatic way is to register +loopback-explorer via `component-config.json`: + +```json +{ + "loopback-explorer": { + "mountPath": "/explorer" + } +} +``` + ## Advanced Usage Many aspects of the explorer are configurable. @@ -32,7 +62,7 @@ See [options](#options) for a description of these options: ```js // Mount middleware before calling `explorer()` to add custom headers, auth, etc. app.use('/explorer', loopback.basicAuth('user', 'password')); -app.use('/explorer', explorer(app, { +explorer(app, { basePath: '/custom-api-root', uiDirs: [ path.resolve(__dirname, 'public'), @@ -60,6 +90,12 @@ Options are passed to `explorer(app, options)`. > to a path different than '/api', e.g. with > `loopback.use('/custom-api-root', loopback.rest()); +`mountPath`: **String** + +> Default: `/explorer` + +> Set the path where to mount the explorer component. + `protocol`: **String** > Default: `null` diff --git a/index.js b/index.js index 975e318..fbe716d 100644 --- a/index.js +++ b/index.js @@ -6,35 +6,46 @@ var url = require('url'); var path = require('path'); var urlJoin = require('./lib/url-join'); var _defaults = require('lodash').defaults; -var express = require('express'); var swagger = require('./lib/swagger'); var SWAGGER_UI_ROOT = require('strong-swagger-ui').dist; var STATIC_ROOT = path.join(__dirname, 'public'); module.exports = explorer; +explorer.routes = routes; /** * Example usage: * * var explorer = require('loopback-explorer'); - * app.use('/explorer', explorer(app, options)); + * explorer(app, options); */ function explorer(loopbackApplication, options) { + var mountPath = options.mountPath || '/explorer'; + loopbackApplication.use(mountPath, routes(loopbackApplication, options)); +} + +function routes(loopbackApplication, options) { + var loopback = loopbackApplication.loopback; + var loopbackMajor = loopback && loopback.version && + loopback.version.split('.')[0] || 1; + + if (loopbackMajor < 2) { + throw new Error('loopback-explorer requires loopback 2.0 or newer'); + } + options = _defaults({}, options, { resourcePath: 'resources', apiInfo: loopbackApplication.get('apiInfo') || {} }); - var app = express(); + var router = new loopback.Router(); - swagger(loopbackApplication, app, options); - - app.disable('x-powered-by'); + swagger(loopbackApplication, router, options); // config.json is loaded by swagger-ui. The server should respond // with the relative URI of the resource doc. - app.get('/config.json', function(req, res) { + router.get('/config.json', function(req, res) { // Get the path we're mounted at. It's best to get this from the referer // in case we're proxied at a deep path. var source = url.parse(req.headers.referer || '').pathname; @@ -53,10 +64,10 @@ function explorer(loopbackApplication, options) { // to worry about constantly pulling in JS updates. if (options.uiDirs) { if (typeof options.uiDirs === 'string') { - app.use(express.static(options.uiDirs)); + router.use(loopback.static(options.uiDirs)); } else if (Array.isArray(options.uiDirs)) { options.uiDirs.forEach(function(dir) { - app.use(express.static(dir)); + router.use(loopback.static(dir)); }); } } @@ -64,14 +75,14 @@ function explorer(loopbackApplication, options) { if (options.swaggerDistRoot) { console.warn('loopback-explorer: `swaggerDistRoot` is deprecated,' + ' use `uiDirs` instead'); - app.use(express.static(options.swaggerDistRoot)); + router.use(loopback.static(options.swaggerDistRoot)); } // File in node_modules are overridden by a few customizations - app.use(express.static(STATIC_ROOT)); + router.use(loopback.static(STATIC_ROOT)); // Swagger UI distribution - app.use(express.static(SWAGGER_UI_ROOT)); + router.use(loopback.static(SWAGGER_UI_ROOT)); - return app; + return router; } diff --git a/package.json b/package.json index 073f5d8..31246c3 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "dependencies": { "cors": "^2.7.1", "debug": "^2.2.0", - "express": "4.x", "lodash": "^3.10.0", "strong-swagger-ui": "^20.0.2" } diff --git a/test/explorer.test.js b/test/explorer.test.js index 431fd3f..c3dd9bb 100644 --- a/test/explorer.test.js +++ b/test/explorer.test.js @@ -106,9 +106,9 @@ describe('explorer', function() { var app; beforeEach(function setupExplorerWithUiDirs() { app = loopback(); - app.use('/explorer', explorer(app, { + explorer(app, { uiDirs: [ path.resolve(__dirname, 'fixtures', 'dummy-swagger-ui') ] - })); + }); }); it('overrides swagger-ui files', function(done) { @@ -128,6 +128,27 @@ describe('explorer', function() { }); }); + describe('explorer.routes API', function() { + var app; + beforeEach(function() { + app = loopback(); + var Product = loopback.PersistedModel.extend('product'); + Product.attachTo(loopback.memory()); + app.model(Product); + }); + + it('creates explorer routes', function(done) { + app.use('/explorer', explorer.routes(app)); + app.use(app.get('restApiRoot') || '/', loopback.rest()); + + request(app) + .get('/explorer/config.json') + .expect('Content-Type', /json/) + .expect(200) + .end(done); + }); + }); + describe('when specifying custom static file root directories', function() { var app; beforeEach(function() { @@ -135,9 +156,9 @@ describe('explorer', function() { }); it('should allow `uiDirs` to be defined as an Array', function(done) { - app.use('/explorer', explorer(app, { + explorer(app, { uiDirs: [ path.resolve(__dirname, 'fixtures', 'dummy-swagger-ui') ] - })); + }); request(app).get('/explorer/') .expect(200) @@ -147,9 +168,9 @@ describe('explorer', function() { }); it('should allow `uiDirs` to be defined as an String', function(done) { - app.use('/explorer', explorer(app, { + explorer(app, { uiDirs: path.resolve(__dirname, 'fixtures', 'dummy-swagger-ui') - })); + }); request(app).get('/explorer/') .expect(200) @@ -172,7 +193,7 @@ describe('explorer', function() { Product.attachTo(loopback.memory()); app.model(Product); - app.use(explorerBase || '/explorer', explorer(app)); + explorer(app, { mountPath: explorerBase }); app.use(app.get('restApiRoot') || '/', loopback.rest()); } }); diff --git a/test/swagger.test.js b/test/swagger.test.js index 18e3430..063ebf7 100644 --- a/test/swagger.test.js +++ b/test/swagger.test.js @@ -3,7 +3,6 @@ var url = require('url'); var urlJoin = require('../lib/url-join'); var loopback = require('loopback'); -var express = require('express'); var swagger = require('../lib/swagger'); var request = require('supertest'); @@ -387,7 +386,7 @@ describe('swagger definition', function() { } function mountExplorer(app, options) { - var swaggerApp = express(); + var swaggerApp = loopback(); swagger(app, swaggerApp, options); app.use(app.get('explorerRoot') || '/explorer', swaggerApp); return app;