|
| 1 | +export function createSnapshot (doc) { |
| 2 | + // defaults everything to false, so no need to set |
| 3 | + return Object.defineProperty(doc.data(), 'id', { |
| 4 | + value: doc.id, |
| 5 | + }) |
| 6 | +} |
| 7 | + |
| 8 | +const isObject = o => o && typeof o === 'object' |
| 9 | + |
| 10 | +export function extractRefs (doc, oldDoc, path = '', result = [{}, {}]) { |
| 11 | + // must be set here because walkGet can return null or undefined |
| 12 | + oldDoc = oldDoc || {} |
| 13 | + const idDescriptor = Object.getOwnPropertyDescriptor(doc, 'id') |
| 14 | + if (idDescriptor && !idDescriptor.enumerable) { |
| 15 | + Object.defineProperty(result[0], 'id', idDescriptor) |
| 16 | + } |
| 17 | + return Object.keys(doc).reduce((tot, key) => { |
| 18 | + const ref = doc[key] |
| 19 | + // if it's a ref |
| 20 | + if (ref && typeof ref.isEqual === 'function') { |
| 21 | + tot[0][key] = oldDoc[key] || ref.path |
| 22 | + tot[1][path + key] = ref |
| 23 | + } else if (Array.isArray(ref)) { |
| 24 | + tot[0][key] = Array(ref.length).fill(null) |
| 25 | + extractRefs(ref, oldDoc[key], path + key + '.', [tot[0][key], tot[1]]) |
| 26 | + } else if (isObject(ref)) { |
| 27 | + tot[0][key] = {} |
| 28 | + extractRefs(ref, oldDoc[key], path + key + '.', [tot[0][key], tot[1]]) |
| 29 | + } else { |
| 30 | + tot[0][key] = ref |
| 31 | + } |
| 32 | + return tot |
| 33 | + }, result) |
| 34 | +} |
| 35 | + |
| 36 | +export function callOnceWithArg (fn, argFn) { |
| 37 | + let called |
| 38 | + return () => { |
| 39 | + if (!called) { |
| 40 | + called = true |
| 41 | + return fn(argFn()) |
| 42 | + } |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +export function walkGet (obj, path) { |
| 47 | + return path.split('.').reduce((target, key) => target[key], obj) |
| 48 | +} |
| 49 | + |
| 50 | +export function walkSet (obj, path, value) { |
| 51 | + // path can be a number |
| 52 | + const keys = ('' + path).split('.') |
| 53 | + const key = keys.pop() |
| 54 | + const target = keys.reduce((target, key) => target[key], obj) |
| 55 | + // global isFinite is different from Number.isFinite |
| 56 | + // it converts values to numbers |
| 57 | + if (isFinite(key)) target.splice(key, 1, value) |
| 58 | + else target[key] = value |
| 59 | +} |
0 commit comments