From ca7f7ea78b5a75c7212d0f9d5bc5465b0077df97 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Thu, 14 Dec 2017 18:40:48 -0800 Subject: [PATCH 01/12] Stop using require.context in error transformers --- .../plugins/err/error-transformers/hook.js | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/core/plugins/err/error-transformers/hook.js b/src/core/plugins/err/error-transformers/hook.js index badec81db58..5c0c7ed9964 100644 --- a/src/core/plugins/err/error-transformers/hook.js +++ b/src/core/plugins/err/error-transformers/hook.js @@ -1,26 +1,13 @@ import reduce from "lodash/reduce" -let request = require.context("./transformers/", true, /\.js$/) -let errorTransformers = [] - -request.keys().forEach( function( key ){ - if( key === "./hook.js" ) { - return - } - - if( !key.match(/js$/) ) { - return - } - - if( key.slice(2).indexOf("/") > -1) { - // skip files in subdirs - return - } - - errorTransformers.push({ - name: toTitleCase(key).replace(".js", "").replace("./", ""), - transform: request(key).transform - }) -}) +import { transform as NotOfType } from "./transformers/not-of-type" +import { transform as ParameterOneOf } from "./transformers/parameter-oneof" +import { transform as StripInstance } from "./transformers/strip-instance" + +const errorTransformers = [ + NotOfType, + ParameterOneOf, + StripInstance +] export default function transformErrors (errors, system) { let inputs = { From b5c713a72b3077b97e536c22d30d39d2449da05b Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Thu, 14 Dec 2017 18:51:48 -0800 Subject: [PATCH 02/12] Eliminate require.context usage --- .../split-pane-mode/components/index.js | 17 -------------- src/core/plugins/split-pane-mode/index.js | 7 +++--- src/plugins/index.js | 22 +++++-------------- 3 files changed, 10 insertions(+), 36 deletions(-) delete mode 100644 src/core/plugins/split-pane-mode/components/index.js diff --git a/src/core/plugins/split-pane-mode/components/index.js b/src/core/plugins/split-pane-mode/components/index.js deleted file mode 100644 index 7149382d05b..00000000000 --- a/src/core/plugins/split-pane-mode/components/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import { pascalCaseFilename } from "core/utils" - -const request = require.context(".", true, /\.jsx?$/) - -request.keys().forEach( function( key ){ - if( key === "./index.js" ) { - return - } - - // if( key.slice(2).indexOf("/") > -1) { - // // skip files in subdirs - // return - // } - - let mod = request(key) - module.exports[pascalCaseFilename(key)] = mod.default ? mod.default : mod -}) diff --git a/src/core/plugins/split-pane-mode/index.js b/src/core/plugins/split-pane-mode/index.js index 9b4d285e504..913738c48ca 100644 --- a/src/core/plugins/split-pane-mode/index.js +++ b/src/core/plugins/split-pane-mode/index.js @@ -1,5 +1,4 @@ -import * as components from "./components" - +import SplitPaneMode from "./components/split-pane-mode" export default function SplitPaneModePlugin() { return { // statePlugins: { @@ -9,6 +8,8 @@ export default function SplitPaneModePlugin() { // } // }, - components, + components: { + SplitPaneMode + } } } diff --git a/src/plugins/index.js b/src/plugins/index.js index 5cbd4b9c404..f143ff0b3c9 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -1,17 +1,7 @@ -import { pascalCaseFilename } from "js/utils" +import Configs from "./configs" +import Topbar from "./topbar" -const request = require.context(".", true, /\.jsx?$/) - -request.keys().forEach( function( key ){ - if( key === "./index.js" ) { - return - } - - // if( key.slice(2).indexOf("/") > -1) { - // // skip files in subdirs - // return - // } - - let mod = request(key) - module.exports[pascalCaseFilename(key)] = mod.default ? mod.default : mod -}) +export default { + Configs, + Topbar +} From 85c83931c40dfbf8fc73b545554262835173e66a Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Thu, 14 Dec 2017 18:58:36 -0800 Subject: [PATCH 03/12] Move configs plugin to core --- .babelrc | 4 ++++ src/{ => core}/plugins/configs/actions.js | 0 src/{ => core}/plugins/configs/index.js | 2 +- src/{ => core}/plugins/configs/reducers.js | 0 src/{ => core}/plugins/configs/selectors.js | 0 src/core/presets/base.js | 2 +- 6 files changed, 6 insertions(+), 2 deletions(-) rename src/{ => core}/plugins/configs/actions.js (100%) rename src/{ => core}/plugins/configs/index.js (96%) rename src/{ => core}/plugins/configs/reducers.js (100%) rename src/{ => core}/plugins/configs/selectors.js (100%) diff --git a/.babelrc b/.babelrc index bdd506769f3..9a606b0b15c 100644 --- a/.babelrc +++ b/.babelrc @@ -9,6 +9,10 @@ [ "module-alias", [ + { + "expose": "root", + "src": "." + }, { "expose": "components", "src": "src/core/components" diff --git a/src/plugins/configs/actions.js b/src/core/plugins/configs/actions.js similarity index 100% rename from src/plugins/configs/actions.js rename to src/core/plugins/configs/actions.js diff --git a/src/plugins/configs/index.js b/src/core/plugins/configs/index.js similarity index 96% rename from src/plugins/configs/index.js rename to src/core/plugins/configs/index.js index 58edbfa1a01..0ab33c96808 100644 --- a/src/plugins/configs/index.js +++ b/src/core/plugins/configs/index.js @@ -1,5 +1,5 @@ import YAML from "js-yaml" -import yamlConfig from "../../../swagger-config.yaml" +import yamlConfig from "root/swagger-config.yaml" import * as actions from "./actions" import * as selectors from "./selectors" import reducers from "./reducers" diff --git a/src/plugins/configs/reducers.js b/src/core/plugins/configs/reducers.js similarity index 100% rename from src/plugins/configs/reducers.js rename to src/core/plugins/configs/reducers.js diff --git a/src/plugins/configs/selectors.js b/src/core/plugins/configs/selectors.js similarity index 100% rename from src/plugins/configs/selectors.js rename to src/core/plugins/configs/selectors.js diff --git a/src/core/presets/base.js b/src/core/presets/base.js index 133df134ad9..30e18ffaf0d 100644 --- a/src/core/presets/base.js +++ b/src/core/presets/base.js @@ -10,7 +10,7 @@ import auth from "core/plugins/auth" import util from "core/plugins/util" import SplitPaneModePlugin from "core/plugins/split-pane-mode" import downloadUrlPlugin from "core/plugins/download-url" -import configsPlugin from "plugins/configs" +import configsPlugin from "core/plugins/configs" import deepLinkingPlugin from "core/plugins/deep-linking" import OperationContainer from "core/containers/OperationContainer" From c1ae4c133d3a546b86f4a2de813deeeec552d784 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Thu, 14 Dec 2017 21:01:37 -0800 Subject: [PATCH 04/12] Add `afterLoad` plugin interface --- docs/customization/plugin-api.md | 31 ++++++++++++++++++++++++++++++- src/core/system.js | 8 ++++++++ test/core/system/system.js | 27 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/docs/customization/plugin-api.md b/docs/customization/plugin-api.md index 245b5a14433..ee08ba07026 100644 --- a/docs/customization/plugin-api.md +++ b/docs/customization/plugin-api.md @@ -19,7 +19,8 @@ A plugin return value may contain any of these keys, where `myStateKey` is a nam }, components: {}, wrapComponents: {}, - fn: {} + afterLoad: (system) => {} + fn: {}, } ``` @@ -363,7 +364,35 @@ const MyWrapComponentPlugin = function(system) { } ``` +##### `afterLoad` +The `afterLoad` plugin method allows you to get a reference to the system after your plugin has been registered with the system. + +This interface is used in the core code to attach methods that are driven by bound selectors or actions directly to the system. + +```javascript +const MyMethodProvidingPlugin = function() { + return { + afterLoad(system) { + // at this point in time, your actions have been bound into the system + // so you can do things with them + system.myMethod = system.exampleActions.updateFavoriteColor + }, + statePlugins: { + example: { + actions: { + updateFavoriteColor: (str) => { + return { + type: "EXAMPLE_SET_FAV_COLOR", + payload: str + } + } + } + } + } + } +} +``` ##### fn diff --git a/src/core/system.js b/src/core/system.js index 22707ae4d38..87a258877c1 100644 --- a/src/core/system.js +++ b/src/core/system.js @@ -68,6 +68,14 @@ export default class Store { if(rebuild) { this.buildSystem() } + + if(Array.isArray(plugins)) { + plugins.forEach(plugin => { + if(plugin.afterLoad) { + plugin.afterLoad(this.getSystem()) + } + }) + } } buildSystem(buildReducer=true) { diff --git a/test/core/system/system.js b/test/core/system/system.js index 073390fa132..205fc8a603b 100644 --- a/test/core/system/system.js +++ b/test/core/system/system.js @@ -683,4 +683,31 @@ describe("bound system", function(){ }) }) + describe("afterLoad", function() { + it("should call an plugin's `afterLoad` method after the plugin is loaded", function() { + // Given + const system = new System({ + plugins: [ + { + afterLoad(system) { + system.wow = system.dogeSelectors.wow + }, + statePlugins: { + doge: { + selectors: { + wow: () => (system) => { + return "so selective" + } + } + } + } + } + ] + }) + + // When + var res = system.getSystem().wow() + expect(res).toEqual("so selective") + }) + }) }) From 2dd25abbdd01fd3490fdb57d543aa8c3021b0505 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 15 Dec 2017 14:16:44 -0800 Subject: [PATCH 05/12] Move initOAuth attacher out of core constructor --- src/core/index.js | 2 -- src/core/plugins/auth/index.js | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/index.js b/src/core/index.js index c34b91b67b0..544f16d886c 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -104,8 +104,6 @@ module.exports = function SwaggerUI(opts) { var system = store.getSystem() - system.initOAuth = system.authActions.configureAuth - const downloadSpec = (fetchedConfig) => { if(typeof constructorConfig !== "object") { return system diff --git a/src/core/plugins/auth/index.js b/src/core/plugins/auth/index.js index 0937f805cb1..7e9413f4a53 100644 --- a/src/core/plugins/auth/index.js +++ b/src/core/plugins/auth/index.js @@ -5,6 +5,9 @@ import * as specWrapActionReplacements from "./spec-wrap-actions" export default function() { return { + afterLoad(system) { + system.initOAuth = system.authActions.configureAuth + }, statePlugins: { auth: { reducers, From a2f8d289a0b22b6ff91d5b2b70d38663ddf8b5d7 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 15 Dec 2017 14:17:12 -0800 Subject: [PATCH 06/12] Fix error transformer imports --- src/core/plugins/err/error-transformers/hook.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/plugins/err/error-transformers/hook.js b/src/core/plugins/err/error-transformers/hook.js index 5c0c7ed9964..fa99ab3568c 100644 --- a/src/core/plugins/err/error-transformers/hook.js +++ b/src/core/plugins/err/error-transformers/hook.js @@ -1,7 +1,7 @@ import reduce from "lodash/reduce" -import { transform as NotOfType } from "./transformers/not-of-type" -import { transform as ParameterOneOf } from "./transformers/parameter-oneof" -import { transform as StripInstance } from "./transformers/strip-instance" +import * as NotOfType from "./transformers/not-of-type" +import * as ParameterOneOf from "./transformers/parameter-oneof" +import * as StripInstance from "./transformers/strip-instance" const errorTransformers = [ NotOfType, From e07b105b29d911d28f5c383e73b9664f0fef68ea Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 19 Dec 2017 23:45:35 -0600 Subject: [PATCH 07/12] Remove layout from default initial state --- src/core/index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/core/index.js b/src/core/index.js index 10d8339547a..6497c0a8136 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -81,10 +81,6 @@ module.exports = function SwaggerUI(opts) { }, plugins: constructorConfig.presets, state: deepExtend({ - layout: { - layout: constructorConfig.layout, - filter: constructorConfig.filter - }, spec: { spec: "", url: constructorConfig.url From 150ebf3bc0b378f4273158f039f09a85e8e0553c Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 19 Dec 2017 23:46:09 -0600 Subject: [PATCH 08/12] Add ability to explicitly skip rendering --- src/core/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/index.js b/src/core/index.js index 6497c0a8136..22eea8d74f7 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -132,6 +132,9 @@ module.exports = function SwaggerUI(opts) { } else if(mergedConfig.dom_id) { let domNode = document.querySelector(mergedConfig.dom_id) system.render(domNode, "App") + } else if(mergedConfig.dom_id === null || mergedConfig.domNode === null) { + // do nothing + // this is useful for testing that does not need to do any rendering } else { console.error("Skipped rendering: no `dom_id` or `domNode` was specified") } From 68c689e4915098dc4aa042a5992184e3eeb20e61 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Wed, 20 Dec 2017 13:59:22 -0600 Subject: [PATCH 09/12] Type-check `errors` before iterating over them --- src/core/plugins/spec/actions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/plugins/spec/actions.js b/src/core/plugins/spec/actions.js index 6ec1ed9cc84..ae95b7ec0f0 100644 --- a/src/core/plugins/spec/actions.js +++ b/src/core/plugins/spec/actions.js @@ -105,8 +105,7 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio errActions.clear({ type: "thrown" }) - - if(errors.length > 0) { + if(Array.isArray(errors) && errors.length > 0) { let preparedErrors = errors .map(err => { console.error(err) From a9ebdb8a7afd540d9f602df6aae0305be1bbc12d Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 22 Dec 2017 22:29:55 -0600 Subject: [PATCH 10/12] Add layout back to initalState --- src/core/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/index.js b/src/core/index.js index 22eea8d74f7..8a94c97ee46 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -81,6 +81,10 @@ module.exports = function SwaggerUI(opts) { }, plugins: constructorConfig.presets, state: deepExtend({ + layout: { + layout: constructorConfig.layout, + filter: constructorConfig.filter + }, spec: { spec: "", url: constructorConfig.url From b03bf906640148a9e73721b4ab760417992a1efc Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 22 Dec 2017 22:39:39 -0600 Subject: [PATCH 11/12] Allow initialState key deletion --- src/core/index.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/core/index.js b/src/core/index.js index 8a94c97ee46..15f0e798e56 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -92,6 +92,20 @@ module.exports = function SwaggerUI(opts) { }, constructorConfig.initialState) } + if(constructorConfig.initialState) { + // if the user sets a key as `undefined`, that signals to us that we + // should delete the key entirely. + // known usage: Swagger-Editor validate plugin tests + for (var key in constructorConfig.initialState) { + if( + constructorConfig.initialState.hasOwnProperty(key) + && constructorConfig.initialState[key] === undefined + ) { + delete storeConfigs.state[key] + } + } + } + let inlinePlugin = ()=> { return { fn: constructorConfig.fn, From 27156bb79d78982bd23c75e27ee34f16e1ffa224 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 22 Dec 2017 22:58:37 -0600 Subject: [PATCH 12/12] Linter fixes --- src/core/plugins/err/error-transformers/hook.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/core/plugins/err/error-transformers/hook.js b/src/core/plugins/err/error-transformers/hook.js index fa99ab3568c..e33dbb6f614 100644 --- a/src/core/plugins/err/error-transformers/hook.js +++ b/src/core/plugins/err/error-transformers/hook.js @@ -34,10 +34,3 @@ export default function transformErrors (errors, system) { }) } - -function toTitleCase(str) { - return str - .split("-") - .map(substr => substr[0].toUpperCase() + substr.slice(1)) - .join("") -}