TestGatsbySanity/studio/plugins/dashboard-widget-structure-menu/src/lib/structure.js
2019-05-09 10:15:41 -05:00

99 lines
2.9 KiB
JavaScript

/* global __DEV__ */
import {defer, from as observableFrom, of as observableOf, throwError} from 'rxjs'
import {mergeMap} from 'rxjs/operators'
// eslint-disable-next-line import/no-commonjs
const {StructureBuilder} = require('@sanity/structure')
let prevStructureError = null
if (__DEV__) {
if (module.hot && module.hot.data) {
prevStructureError = module.hot.data.prevError
}
}
export function isSubscribable (thing) {
return thing && (typeof thing.then === 'function' || typeof thing.subscribe === 'function')
}
export function isStructure (structure) {
return (
structure &&
(typeof structure === 'function' ||
typeof structure.serialize !== 'function' ||
typeof structure.then !== 'function' ||
typeof structure.subscribe !== 'function' ||
typeof structure.type !== 'string')
)
}
export function serializeStructure (item, context, resolverArgs = []) {
// Lazy
if (typeof item === 'function') {
return serializeStructure(item(...resolverArgs), context, resolverArgs)
}
// Promise/observable returning a function, builder or plain JSON structure
if (isSubscribable(item)) {
return observableFrom(item).pipe(
mergeMap(val => serializeStructure(val, context, resolverArgs))
)
}
// Builder?
if (item && typeof item.serialize === 'function') {
return serializeStructure(item.serialize(context))
}
// Plain value?
return observableOf(item)
}
export function getDefaultStructure () {
const items = StructureBuilder.documentTypeListItems()
return StructureBuilder.list()
.id('__root__')
.title('Content')
.showIcons(items.some(item => item.getSchemaType().icon))
.items(items)
}
// We are lazy-requiring/resolving the structure inside of a function in order to catch errors
// on the root-level of the module. Any loading errors will be caught and emitted as errors
// eslint-disable-next-line complexity
export function loadStructure () {
let structure
try {
const mod = require('part:@sanity/desk-tool/structure?') || getDefaultStructure()
structure = mod && mod.__esModule ? mod.default : mod
// On invalid modules, when HMR kicks in, we sometimes get an empty object back when the
// source has changed without fixing the problem. In this case, keep showing the error
if (
__DEV__ &&
prevStructureError &&
structure &&
structure.constructor.name === 'Object' &&
Object.keys(structure).length === 0
) {
return throwError(prevStructureError)
}
prevStructureError = null
} catch (err) {
prevStructureError = err
return throwError(err)
}
if (!isStructure(structure)) {
return throwError(
new Error(
`Structure needs to export a function, an observable, a promise or a stucture builder, got ${typeof structure}`
)
)
}
// Defer to catch immediately thrown errors on serialization
return defer(() => serializeStructure(structure))
}