UNPKG

@v4fire/client

Version:

V4Fire client core library

264 lines (212 loc) • 5.13 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ import { deprecate } from 'core/functools/deprecation'; import { ComponentInterface } from 'core/component/interface'; import { propRgxp, attrRgxp, storeRgxp, hasSeparator } from 'core/component/reflection/const'; import type { PropertyInfo } from 'core/component/reflection/interface'; /** * Returns an information object of a component property by the specified path * * @param path * @param component - component instance * * @example * ```js * @component() * class bButton { * @system() * fooStore = {bla: 'bar'}; * * get foo() { * return this.fooStore; * } * * created() { * // { * // name: 'fooStore', * // path: 'fooStore.bar', * // fullPath: '$root.$refs.button.fooStore.bar', * // topPath: '$root.$refs.button.fooStore', * // originalPath: '$root.$refs.button.foo.bar', * // originalTopPath: '$root.$refs.button.foo', * // type: 'system', * // accessor: 'foo', * // accessorType: 'computed' * // } * console.log(getPropertyInfo('$root.$refs.button.foo.bar', this)); * } * } * ``` */ export function getPropertyInfo(path: string, component: ComponentInterface): PropertyInfo { const originalPath = path; let name = path, fullPath = path, topPath = path, originalTopPath = path; let chunks, rootI = 0; if (hasSeparator.test(path)) { chunks = path.split('.'); let obj: Nullable<ComponentInterface> = component; for (let i = 0; i < chunks.length; i++) { if (obj == null) { break; } obj = obj[chunks[i]]; if (obj?.instance instanceof ComponentInterface) { component = obj; rootI = i === chunks.length - 1 ? i : i + 1; } } path = chunks.slice(rootI).join('.'); topPath = chunks.slice(0, rootI + 1).join('.'); originalTopPath = topPath; name = chunks[rootI]; } const {props, fields, systemFields, computedFields, accessors, params: {deprecatedProps}} = component.unsafe.meta; const alternative = deprecatedProps?.[name]; if (alternative != null) { deprecate({type: 'property', name, renamedTo: alternative}); name = alternative; if (chunks != null) { chunks[rootI] = name; path = chunks.slice(rootI).join('.'); topPath = chunks.slice(0, rootI + 1).join('.'); originalTopPath = topPath; fullPath = chunks.join('.'); } else { path = name; fullPath = name; topPath = name; originalTopPath = name; } } const info: PropertyInfo = { name, type: 'field', ctx: resolveCtx(component), path, fullPath, originalPath, topPath, originalTopPath }; if (RegExp.test(propRgxp, name)) { info.type = 'prop'; return info; } if (RegExp.test(attrRgxp, name)) { info.type = 'attr'; return info; } if (RegExp.test(storeRgxp, name)) { if (fields[name] != null) { return info; } info.type = 'system'; return info; } if (fields[name] != null) { return info; } if (props[name] != null) { info.type = 'prop'; return info; } if (systemFields[name] != null) { info.type = 'system'; return info; } const storeName = `${name}Store`, hasStoreField = fields[storeName] != null || systemFields[storeName] != null, propName = hasStoreField ? null : `${name}Prop`; let accessorType, accessor; if (computedFields[name] != null) { accessorType = 'computed'; accessor = name; } else if (accessors[name] != null) { accessorType = 'accessor'; accessor = name; } if (hasStoreField || propName != null && props[propName]) { name = propName ?? storeName; if (chunks != null) { chunks[rootI] = name; path = chunks.slice(rootI).join('.'); fullPath = chunks.join('.'); topPath = chunks.slice(0, rootI + 1).join('.'); } else { path = name; fullPath = name; topPath = name; } let type: PropertyInfo['type'] = 'field'; if (propName != null) { type = 'prop'; } else if (systemFields[storeName] != null) { type = 'system'; } return { ...info, name, type, path, fullPath, topPath, accessor, accessorType }; } if (accessorType != null) { if ((computedFields[name] ?? accessors[name])!.watchable) { let ctxPath; if (chunks != null) { ctxPath = chunks.slice(0, rootI + 1); path = chunks.slice(rootI + 1).join('.'); topPath = chunks.slice(0, rootI + 2).join('.'); originalTopPath = topPath; } else { ctxPath = path; path = ''; topPath = ''; originalTopPath = ''; } return { ...info, type: 'mounted', ctx: resolveCtx(Object.get(component, ctxPath) ?? {}), path, originalPath, topPath, originalTopPath }; } info.type = accessorType; return info; } info.type = 'system'; return info; function resolveCtx(component: object): ComponentInterface { if (Object.cast<Dictionary>(component).$remoteParent != null) { return Object.getPrototypeOf(component); } return Object.cast(component); } }