dashboard/plugins/steve/resource-proxy.js

84 lines
1.9 KiB
JavaScript

import ResourceInstance from './resource-instance';
import { lookup } from './model-loader';
export const SELF = '__[[SELF]]__';
export const ALREADY_A_PROXY = '__[[PROXY]]__';
export const PRIVATE = '__[[PRIVATE]]__';
const FAKE_CONSTRUCTOR = function() {};
FAKE_CONSTRUCTOR.toString = function() {
return 'ResourceProxy';
};
export function proxyFor(ctx, obj, isClone = false) {
// Attributes associated to the proxy, but not stored on the actual backing object
let priv;
if ( obj[ALREADY_A_PROXY] ) {
return obj;
}
if ( process.server ) {
Object.defineProperty(obj, '__rehydrate', {
value: true,
enumerable: true,
configurable: true
});
if ( isClone ) {
Object.defineProperty(obj, '__clone', {
value: true,
enumerable: true,
configurable: true,
writable: true
});
}
}
const model = lookup(obj.type) || ResourceInstance;
const proxy = new Proxy(obj, {
get(target, name) {
if ( name === ALREADY_A_PROXY ) {
return true;
} else if ( name === SELF ) {
return obj;
} else if ( name === Symbol.toStringTag ) {
name = 'toString';
} else if ( typeof name !== 'string' ) {
return target[name];
} else if ( name === 'constructor' ) {
// To satisfy vue-devtools
return FAKE_CONSTRUCTOR;
} else if ( name.startsWith('$') ) {
return ctx[name.substr(1)];
} else if ( name === PRIVATE ) {
if ( !priv ) {
priv = {};
}
return priv;
}
let fn;
if ( model && Object.prototype.hasOwnProperty.call(model, name) ) {
fn = model[name];
}
if ( !fn ) {
fn = ResourceInstance[name];
}
if ( fn && fn.call ) {
return fn.call(proxy);
}
return target[name];
},
});
return proxy;
}