Merge pull request #4049 from shockey/support/editor-validation-refactor

Supporting changes for Swagger-Editor semantic validation changes
This commit is contained in:
kyle
2017-12-23 00:25:30 -06:00
committed by GitHub
16 changed files with 110 additions and 71 deletions

View File

@@ -9,6 +9,10 @@
[
"module-alias",
[
{
"expose": "root",
"src": "."
},
{
"expose": "components",
"src": "src/core/components"

View File

@@ -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

View File

@@ -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,
@@ -105,8 +119,6 @@ module.exports = function SwaggerUI(opts) {
var system = store.getSystem()
system.initOAuth = system.authActions.configureAuth
const downloadSpec = (fetchedConfig) => {
if(typeof constructorConfig !== "object") {
return system
@@ -138,6 +150,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")
}

View File

@@ -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,

View File

@@ -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"

View File

@@ -1,26 +1,13 @@
import reduce from "lodash/reduce"
let request = require.context("./transformers/", true, /\.js$/)
let errorTransformers = []
import * as NotOfType from "./transformers/not-of-type"
import * as ParameterOneOf from "./transformers/parameter-oneof"
import * as StripInstance from "./transformers/strip-instance"
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
})
})
const errorTransformers = [
NotOfType,
ParameterOneOf,
StripInstance
]
export default function transformErrors (errors, system) {
let inputs = {
@@ -47,10 +34,3 @@ export default function transformErrors (errors, system) {
})
}
function toTitleCase(str) {
return str
.split("-")
.map(substr => substr[0].toUpperCase() + substr.slice(1))
.join("")
}

View File

@@ -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)

View File

@@ -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
})

View File

@@ -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
}
}
}

View File

@@ -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"

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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")
})
})
})