Repository URL to install this package:
|
Version:
1.1.17 ▾
|
import { types } from 'xmobx/mobx-state-tree'
// import { Typed } from 'modules/modeler'
import { forOwn } from 'chain'
// import {
// transformWhereObj,
// curry,
// overStaticMethods,
// getStaticMethods,
// prop,
// overArgs,
// before,
// } from 'modules/deps'
import {
toEmpty,
isNumberish,
isMap,
toKindOf,
isPrimitive,
isFrozen,
isObj,
isArray,
isFunction,
isNumber,
isBoolean,
isString,
toBoolean,
toString,
toNumber,
toArray,
toObject,
} from 'exotic'
import 'modules/thisless/statetree'
import { selfless, thisless } from 'modules/thisless'
import UniqueDictionary from './UniqueDictionary'
import { bindToSelf } from './deps/bindToSelf'
import { toEmptyRecursive } from './deps/empty'
import {
toMobArray,
toMobArrayOfAny,
toMobModel,
toMobArrayModel,
toMobString,
toMobBoolean,
toMobNumber,
toMobFrozen,
toMobDate,
toMobSet,
toMobIdentity,
toMobLate,
toMobMap,
looseyType,
} from './state-tree-types'
// const spread = Typed.spread(Object, Array, Function, Number, String, Boolean)
// const {
// isObj,
// isArray,
// isFunction,
// isNumber,
// isBoolean,
// isString,
// toBoolean,
// toString,
// toNumber,
// toArray,
// toObject,
// } = spread
const fromNativeToMobx = (x, name) => _toMobx(toEmpty(x), name)
const stringify = x => JSON.stringify(x, null, 2)
// debugging unique dictionary with all types we ever use in all places
const modelDictionary = new UniqueDictionary()
/**
* @private
* @param {*} x any type schema
* @param {string} [modelName=undefined] name of this type as-a-model
* @return {StateTreeModel}
*/
function _toMobx(x, modelName = undefined) {
let typed = -100
if (x && x.isType) {
return x
}
if (modelName === undefined) {
console.log('did not pass in a name', x)
modelName =
typeof x === 'object' ? Object.keys(x).join('_') : stringify(x)
}
/**
* @param {*} tapped
* @example
* addToDictionary(...)
* //=> 'UserModel [object]': {tapped: MobxType, value: OriginalValue}
*/
const addToDictionary = tapped => {
modelDictionary.add(modelName + ' [' + toKindOf(x) + ']', {
// mob: _toMobx(toEmpty(x), modelName),
tapped,
value: x,
// kind: x,
// name: modelName,
})
}
/**
* @return {StateTree|undefined} used to use returns for dictionary
*/
const tapWrap = () => {
/**
* @TODO @FIXME @james
* @NOTE this currently will coerce BuiltInNativeFunctions -> mobx
*/
if (isFunction(x)) {
return fromNativeToMobx(x, modelName)
}
if (isNumber(x)) {
return toMobNumber(x, modelName)
}
if (isString(x)) {
return toMobString(x, modelName)
}
if (isBoolean(x)) {
return toMobBoolean(x, modelName)
}
if (isObj(x)) {
if (isFrozen(x)) {
return toMobFrozen(x, modelName)
}
if (isMap(x)) {
return toMobMap(x, modelName)
}
/**
* @NOTE opinionated
* assumes all values in array are the same
* because this simplifies things
*/
if (isArray(x)) {
const ArrayItemModel = _toMobx(x[0], modelName + 'ArrayItem')
typed = toMobArray(ArrayItemModel, modelName)
return undefined
} else {
const model = {}
forOwn(x, (value, key) => {
model[key] = _toMobx(value, key)
})
typed = toMobModel(model, modelName)
return undefined
}
} else {
throw new Error('what else?' + stringify({ x, modelName }))
return undefined
}
}
const tapped = tapWrap()
addToDictionary(tapped)
if (tapped === undefined) {
if (typed === -100) {
const last = modelDictionary.last()
const msg = 'invalid type [' + modelName + '] ' + stringify(last) + stringify(x)
const error = new Error(msg)
throw error
return types.late(() => {
console.log({ error, last })
throw error
})
}
return typed
} else {
return tapped
}
}
/**
* @param {Schema} x ExoticSchema to transform
* @return {Array} MobxModel, EmptyState, SchemaDataTransformer
*
* @TODO
* const Transformer = transformWhereObj(x)
*/
const toMobx = (x, name) => {
const Mobx = _toMobx(x, name)
const Empty = toEmptyRecursive(x)
// @TODO should move this back with thisless
const creates = Object.getPrototypeOf(Mobx).create
// @TODO need to document exposed dictionary for debug
// console.log(modelDictionary)
return [Mobx, Empty, modelDictionary]
}
// @NOTE currently unused
// @Typed
// class StateTreeType {
// // static coercers = [
// // // recursive
// // [Object, types.model],
// // // [Object.Property, types.model],
// // [Array, types.array],
// // // simple
// // [Function, types.frozen],
// // [Number, types.number],
// // [String, types.string],
// // [Boolean, types.boolean],
// // ]
// }
/**
* @TODO - want to use this to generate a model from fixture json
*/
const shapeToMobx = (SchemaShape, name = undefined) => {
const nameFromKeys = name || Object.keys(SchemaShape).join('_')
const [Model, Empty] = toMobx(SchemaShape, nameFromKeys)
// console.log({ Model })
return Model
}
const OptionalArray = x => types.maybe(types.array(types.maybe(x)))
export { OptionalArray, toMobx, toMobx as toStateTree, shapeToMobx }
// --- export default exports