Skip to content

Instantly share code, notes, and snippets.

@samuelmaddock
Last active February 29, 2020 16:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save samuelmaddock/fb54ddc47b7a958ded1f799861239a87 to your computer and use it in GitHub Desktop.
Save samuelmaddock/fb54ddc47b7a958ded1f799861239a87 to your computer and use it in GitHub Desktop.
Dumps a TypeScript-like JSON interface of runtime JavaScript objects.
; (function (targetObj) {
const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm
const ARGUMENT_NAMES = /([^\s,]+)/g
const getParamNames = func => {
var fnStr = func.toString().replace(STRIP_COMMENTS, '')
var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES)
if (result === null) result = []
return result
}
const isClassName = str => str.length > 0 ? str[0] === str[0].toUpperCase() : false
const isPrivateName = str => str.length <= 2
const constructorType = func => `(${getParamNames(func).join(', ')}) => any`
const jsonFunctionType = (name, func) => {
const interfaceObj = {}
// Constructor
if (typeof name === 'string' && isClassName(name)) {
interfaceObj['new'] = constructorType(func)
}
// Statics
const keys = Object.keys(func)
const statics = keys.reduce((obj, k) => {
if (isPrivateName(k)) return obj
return { ...obj, [k]: func[k] }
}, {})
Object.assign(interfaceObj, statics)
// Prototype methods
if (func.prototype) {
const { prototype } = func
const protoKeys = Object.keys(prototype)
const methods = protoKeys.reduce((obj, k) => {
if (k === 'constructor') return obj
if (isPrivateName(k)) return obj
return { ...obj, [k]: prototype[k] }
}, {})
Object.assign(interfaceObj, methods)
}
// Simple function
if (Object.keys(interfaceObj).length === 0) {
return constructorType(func)
}
return interfaceObj
}
const cache = new WeakSet()
const replacer = (key, value) => {
const isObj = typeof value === 'object' && value !== null
// Circular check
if (isObj && cache.has(value)) {
return '[Circular]'
}
if (key.length && isPrivateName(key)) return
if (typeof value === 'function') {
return jsonFunctionType(key, value)
}
if (isObj) {
cache.add(value)
}
return value
}
const json = JSON.stringify(targetObj, replacer, ' ')
console.log(json)
if (typeof window.copy === 'function') {
window.copy(json)
}
})(cast.framework)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment