Move db in DataReference into [_private]

This makes DataReferences not include any non-private fields, which matches firebase's DataSnapshot class
This commit is contained in:
Fahrzin Hemmati 2023-08-02 13:12:19 -07:00 committed by GitHub
parent 62166b07f2
commit dcf5b5a6d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -144,7 +144,7 @@ export class DataReference<T = any> {
/**
* Creates a reference to a node
*/
constructor (public readonly db: AceBaseBase, path: string, vars?: PathVariables) {
constructor (db: AceBaseBase, path: string, vars?: PathVariables) {
if (!path) { path = ''; }
path = path.replace(/^\/|\/$/g, ''); // Trim slashes
const pathInfo = PathInfo.get(path);
@ -154,6 +154,7 @@ export class DataReference<T = any> {
get path() { return path; },
get key() { return key; },
get callbacks() { return callbacks; },
db: db,
vars: vars || {},
context: {},
pushed: false,
@ -273,7 +274,7 @@ export class DataReference<T = any> {
if (info.parentPath === null) {
return null;
}
return new DataReference(this.db, info.parentPath).context(this[_private].context);
return new DataReference(this[_private].db, info.parentPath).context(this[_private].context);
}
/**
@ -293,7 +294,7 @@ export class DataReference<T = any> {
childPath = typeof childPath === 'number' ? childPath : childPath.replace(/^\/|\/$/g, '');
const currentPath = PathInfo.fillVariables2(this.path, this.vars);
const targetPath = PathInfo.getChildPath(currentPath, childPath);
return new DataReference(this.db, targetPath).context(this[_private].context); // `${this.path}/${childPath}`
return new DataReference(this[_private].db, targetPath).context(this[_private].context); // `${this.path}/${childPath}`
}
/**
@ -313,11 +314,11 @@ export class DataReference<T = any> {
if (typeof value === 'undefined') {
throw new TypeError(`Cannot store undefined value in "/${this.path}"`);
}
if (!this.db.isReady) {
await this.db.ready();
if (!this[_private].db.isReady) {
await this[_private].db.ready();
}
value = this.db.types.serialize(this.path, value);
const { cursor } = await this.db.api.set(this.path, value, { context: this[_private].context });
value = this[_private].db.types.serialize(this.path, value);
const { cursor } = await this[_private].db.api.set(this.path, value, { context: this[_private].context });
this.cursor = cursor;
if (typeof onComplete === 'function') {
try { onComplete(null, this);} catch(err) { console.error('Error in onComplete callback:', err); }
@ -346,8 +347,8 @@ export class DataReference<T = any> {
if (this.isWildcardPath) {
throw new Error(`Cannot update the value of wildcard path "/${this.path}"`);
}
if (!this.db.isReady) {
await this.db.ready();
if (!this[_private].db.isReady) {
await this[_private].db.ready();
}
if (typeof updates !== 'object' || updates instanceof Array || updates instanceof ArrayBuffer || updates instanceof Date) {
await this.set(updates as any);
@ -356,8 +357,8 @@ export class DataReference<T = any> {
console.warn(`update called on path "/${this.path}", but there is nothing to update`);
}
else {
updates = this.db.types.serialize(this.path, updates);
const { cursor } = await this.db.api.update(this.path, updates, { context: this[_private].context });
updates = this[_private].db.types.serialize(this.path, updates);
const { cursor } = await this[_private].db.api.update(this.path, updates, { context: this[_private].context });
this.cursor = cursor;
}
if (typeof onComplete === 'function') {
@ -386,12 +387,12 @@ export class DataReference<T = any> {
if (this.isWildcardPath) {
throw new Error(`Cannot start a transaction on wildcard path "/${this.path}"`);
}
if (!this.db.isReady) {
await this.db.ready();
if (!this[_private].db.isReady) {
await this[_private].db.ready();
}
let throwError;
const cb = (currentValue: any) => {
currentValue = this.db.types.deserialize(this.path, currentValue);
currentValue = this[_private].db.types.deserialize(this.path, currentValue);
const snap = new DataSnapshot(this, currentValue);
let newValue;
try {
@ -405,7 +406,7 @@ export class DataReference<T = any> {
if (newValue instanceof Promise) {
return newValue
.then((val) => {
return this.db.types.serialize(this.path, val);
return this[_private].db.types.serialize(this.path, val);
})
.catch(err => {
throwError = err; // Remember error
@ -413,10 +414,10 @@ export class DataReference<T = any> {
});
}
else {
return this.db.types.serialize(this.path, newValue);
return this[_private].db.types.serialize(this.path, newValue);
}
};
const { cursor } = await this.db.api.transaction(this.path, cb, { context: this[_private].context });
const { cursor } = await this[_private].db.api.transaction(this.path, cb, { context: this[_private].context });
this.cursor = cursor;
if (throwError) {
// Rethrow error from callback code
@ -468,10 +469,10 @@ export class DataReference<T = any> {
ourCallback: (err, path, newValue, oldValue, eventContext) => {
if (err) {
// TODO: Investigate if this ever happens?
this.db.debug.error(`Error getting data for event ${event} on path "${path}"`, err);
this[_private].db.debug.error(`Error getting data for event ${event} on path "${path}"`, err);
return;
}
const ref = this.db.ref(path);
const ref = this[_private].db.ref(path);
ref[_private].vars = PathInfo.extractVariables(this.path, path);
let callbackObject;
@ -481,8 +482,8 @@ export class DataReference<T = any> {
}
else {
const values = {
previous: this.db.types.deserialize(path, oldValue),
current: this.db.types.deserialize(path, newValue),
previous: this[_private].db.types.deserialize(path, oldValue),
current: this[_private].db.types.deserialize(path, newValue),
};
if (event === 'child_removed') {
callbackObject = new DataSnapshot(ref, values.previous, true, values.previous, eventContext);
@ -527,17 +528,17 @@ export class DataReference<T = any> {
// Cancel subscription
const callbacks = this[_private].callbacks;
callbacks.splice(callbacks.indexOf(cb), 1);
this.db.api.unsubscribe(this.path, event, cb.ourCallback);
this[_private].db.api.unsubscribe(this.path, event, cb.ourCallback);
// Call cancelCallbacks
this.db.debug.error(`Subscription "${event}" on path "/${this.path}" canceled because of an error: ${err.message}`);
this[_private].db.debug.error(`Subscription "${event}" on path "/${this.path}" canceled because of an error: ${err.message}`);
eventPublisher.cancel(err.message);
};
const authorized = this.db.api.subscribe(this.path, event, cb.ourCallback, { newOnly: advancedOptions.newOnly, cancelCallback: cancelSubscription, syncFallback: advancedOptions.syncFallback });
const authorized = this[_private].db.api.subscribe(this.path, event, cb.ourCallback, { newOnly: advancedOptions.newOnly, cancelCallback: cancelSubscription, syncFallback: advancedOptions.syncFallback });
const allSubscriptionsStoppedCallback = () => {
const callbacks = this[_private].callbacks;
callbacks.splice(callbacks.indexOf(cb), 1);
return this.db.api.unsubscribe(this.path, event, cb.ourCallback);
return this[_private].db.api.unsubscribe(this.path, event, cb.ourCallback);
};
if (authorized instanceof Promise) {
// Web API now returns a promise that resolves if the request is allowed
@ -578,7 +579,7 @@ export class DataReference<T = any> {
const step = 100, limit = step;
let skip = 0;
const more = async () => {
const children = await this.db.api.reflect(this.path, 'children', { limit, skip });
const children = await this[_private].db.api.reflect(this.path, 'children', { limit, skip });
children.list.forEach(child => {
const childRef = this.child(child.key);
eventPublisher.publish(childRef);
@ -594,11 +595,11 @@ export class DataReference<T = any> {
}
};
if (this.db.isReady) {
if (this[_private].db.isReady) {
subscribe();
}
else {
this.db.ready(subscribe);
this[_private].db.ready(subscribe);
}
return eventStream;
@ -616,7 +617,7 @@ export class DataReference<T = any> {
const subscriptions = this[_private].callbacks;
const stopSubs = subscriptions.filter(sub => (!event || sub.event === event) && (!callback || sub.userCallback === callback));
if (stopSubs.length === 0) {
this.db.debug.warn(`Can't find event subscriptions to stop (path: "${this.path}", event: ${event || '(any)'}, callback: ${callback})`);
this[_private].db.debug.warn(`Can't find event subscriptions to stop (path: "${this.path}", event: ${event || '(any)'}, callback: ${callback})`);
}
stopSubs.forEach(sub => {
sub.stream.stop();
@ -650,8 +651,8 @@ export class DataReference<T = any> {
get<Value = T>(options:DataRetrievalOptions, callback: EventCallback<DataSnapshot<Value>>): void
get<Value = T>(optionsOrCallback?:DataRetrievalOptions|EventCallback<DataSnapshot<Value>>, callback?: EventCallback<DataSnapshot<Value>>): Promise<DataSnapshot<Value>>|void;
get<Value = T>(optionsOrCallback?:DataRetrievalOptions|EventCallback<DataSnapshot<Value>>, callback?: EventCallback<DataSnapshot<Value>>): Promise<DataSnapshot<Value>>|void {
if (!this.db.isReady) {
const promise = this.db.ready().then(() => this.get(optionsOrCallback, callback) as any);
if (!this[_private].db.isReady) {
const promise = this[_private].db.ready().then(() => this.get(optionsOrCallback, callback) as any);
return typeof optionsOrCallback !== 'function' && typeof callback !== 'function' ? promise : undefined; // only return promise if no callback is used
}
@ -669,14 +670,14 @@ export class DataReference<T = any> {
}
const options = new DataRetrievalOptions(typeof optionsOrCallback === 'object' ? optionsOrCallback : { cache_mode: 'allow' });
const promise = this.db.api.get(this.path, options).then(result => {
const promise = this[_private].db.api.get(this.path, options).then(result => {
const isNewApiResult = ('context' in result && 'value' in result);
if (!isNewApiResult) {
// acebase-core version package was updated but acebase or acebase-client package was not? Warn, but don't throw an error.
console.warn('AceBase api.get method returned an old response value. Update your acebase or acebase-client package');
result = { value: result, context: {} };
}
const value = this.db.types.deserialize(this.path, result.value);
const value = this[_private].db.types.deserialize(this.path, result.value);
const snapshot = new DataSnapshot(this, value, undefined, undefined, result.context);
if (result.context?.acebase_cursor) {
this.cursor = result.context.acebase_cursor;
@ -786,10 +787,10 @@ export class DataReference<T = any> {
if (this.isWildcardPath) {
throw new Error(`Cannot check wildcard path "/${this.path}" existence`);
}
if (!this.db.isReady) {
await this.db.ready();
if (!this[_private].db.isReady) {
await this[_private].db.ready();
}
return this.db.api.exists(this.path);
return this[_private].db.api.exists(this.path);
}
get isWildcardPath() {
@ -860,10 +861,10 @@ export class DataReference<T = any> {
if (this.isWildcardPath) {
throw new Error(`Cannot reflect on wildcard path "/${this.path}"`);
}
if (!this.db.isReady) {
await this.db.ready();
if (!this[_private].db.isReady) {
await this[_private].db.ready();
}
return this.db.api.reflect(this.path, type, args);
return this[_private].db.api.reflect(this.path, type, args);
}
/**
@ -881,11 +882,11 @@ export class DataReference<T = any> {
if (this.isWildcardPath) {
throw new Error(`Cannot export wildcard path "/${this.path}"`);
}
if (!this.db.isReady) {
await this.db.ready();
if (!this[_private].db.isReady) {
await this[_private].db.ready();
}
const writeFn = typeof write === 'function' ? write : write.write.bind(write);
return this.db.api.export(this.path, writeFn, options);
return this[_private].db.api.export(this.path, writeFn, options);
}
/**
@ -898,10 +899,10 @@ export class DataReference<T = any> {
if (this.isWildcardPath) {
throw new Error(`Cannot import to wildcard path "/${this.path}"`);
}
if (!this.db.isReady) {
await this.db.ready();
if (!this[_private].db.isReady) {
await this[_private].db.ready();
}
return this.db.api.import(this.path, read, options);
return this[_private].db.api.import(this.path, read, options);
}
/**
@ -933,7 +934,7 @@ export class DataReference<T = any> {
proxy<T = any>(options?: LiveDataProxyOptions<T>) {
const isOptionsArg = typeof options === 'object' && (typeof options.cursor !== 'undefined' || typeof options.defaultValue !== 'undefined');
if (typeof options !== 'undefined' && !isOptionsArg) {
this.db.debug.warn('Warning: live data proxy is being initialized with a deprecated method signature. Use ref.proxy(options) instead of ref.proxy(defaultValue)');
this[_private].db.debug.warn('Warning: live data proxy is being initialized with a deprecated method signature. Use ref.proxy(options) instead of ref.proxy(defaultValue)');
options = { defaultValue: options as T };
}
return LiveDataProxy.create(this, options);
@ -1114,7 +1115,7 @@ export class DataReference<T = any> {
async getMutations(cursorOrDate?: string|Date|null): Promise<{ used_cursor: string, new_cursor: string, mutations: ValueMutation[] }> {
const cursor = typeof cursorOrDate === 'string' ? cursorOrDate : undefined;
const timestamp = cursorOrDate === null || typeof cursorOrDate === 'undefined' ? 0 : cursorOrDate instanceof Date ? cursorOrDate.getTime() : undefined;
return this.db.api.getMutations({ path: this.path, cursor, timestamp });
return this[_private].db.api.getMutations({ path: this.path, cursor, timestamp });
}
/**
@ -1130,7 +1131,7 @@ export class DataReference<T = any> {
async getChanges(cursorOrDate?: string|Date|null): Promise<{ used_cursor: string, new_cursor: string, changes: ValueChange[] }> {
const cursor = typeof cursorOrDate === 'string' ? cursorOrDate : undefined;
const timestamp = cursorOrDate === null || typeof cursorOrDate === 'undefined' ? 0 : cursorOrDate instanceof Date ? cursorOrDate.getTime() : undefined;
return this.db.api.getChanges({ path: this.path, cursor, timestamp });
return this[_private].db.api.getChanges({ path: this.path, cursor, timestamp });
}
}