Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
[
"module-alias",
[
{
"expose": "root",
"src": "."
},
{
"expose": "components",
"src": "src/core/components"
Expand Down
31 changes: 30 additions & 1 deletion docs/customization/plugin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: {},
}
```

Expand Down Expand Up @@ -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

Expand Down
19 changes: 17 additions & 2 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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")
}
Expand Down
3 changes: 3 additions & 0 deletions src/core/plugins/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
File renamed without changes.
File renamed without changes.
36 changes: 8 additions & 28 deletions src/core/plugins/err/error-transformers/hook.js
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -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("")
}
3 changes: 1 addition & 2 deletions src/core/plugins/spec/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 0 additions & 17 deletions src/core/plugins/split-pane-mode/components/index.js

This file was deleted.

7 changes: 4 additions & 3 deletions src/core/plugins/split-pane-mode/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as components from "./components"

import SplitPaneMode from "./components/split-pane-mode"
export default function SplitPaneModePlugin() {
return {
// statePlugins: {
Expand All @@ -9,6 +8,8 @@ export default function SplitPaneModePlugin() {
// }
// },

components,
components: {
SplitPaneMode
}
}
}
2 changes: 1 addition & 1 deletion src/core/presets/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 8 additions & 0 deletions src/core/system.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
22 changes: 6 additions & 16 deletions src/plugins/index.js
Original file line number Diff line number Diff line change
@@ -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
}
27 changes: 27 additions & 0 deletions test/core/system/system.js
Original file line number Diff line number Diff line change
Expand Up @@ -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")
})
})
})