From e7d1a6322130f409e4683b127b24f0f7c3065f32 Mon Sep 17 00:00:00 2001 From: Sebastian Noack Date: Fri, 5 Jan 2024 21:24:40 -0500 Subject: [PATCH] Make the type of the scope a generic --- src/nodefire.ts | 62 ++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/nodefire.ts b/src/nodefire.ts index 834cfb9..922b62d 100644 --- a/src/nodefire.ts +++ b/src/nodefire.ts @@ -7,7 +7,7 @@ import {Simulator} from 'firefight'; import {Agent} from 'http'; export type InterceptOperationsCallback = ( - op: {ref: NodeFire, method: string, args: any[]}, + op: {ref: NodeFire, method: string, args: any[]}, options: any ) => Promise | void; @@ -30,6 +30,8 @@ export interface Scope { [key: string]: any; } +type EmptyScope = {}; // eslint-disable-line @typescript-eslint/ban-types + export interface NodeFireError extends Error { inputValues?: any; timeout?: number; @@ -56,13 +58,13 @@ declare module '@firebase/database-types' { * standard option is `timeout`, which will cause an operation to time out after the given number of * milliseconds. Other operation-specific options are described in their respective doc comments. */ -export default class NodeFire { +export default class NodeFire { /** * Flag that indicates whether to log transactions and the number of tries needed. */ static LOG_TRANSACTIONS = false; $ref: admin.database.Reference | admin.database.Query; - $scope: Scope; + $scope: TScope; private _path?: string; /** @@ -71,7 +73,7 @@ export default class NodeFire { * @param ref A fully authenticated Firebase Admin reference or query. * @param scope Optional dictionary that will be used for interpolating paths. */ - constructor(ref: admin.database.Reference | admin.database.Query, scope?: Scope) { + constructor(ref: admin.database.Reference | admin.database.Query, scope?: TScope) { const refIsNonNullObject = typeof ref === 'object' && ref !== null; if (!refIsNonNullObject || typeof ref.ref !== 'object' || typeof ref.ref.transaction !== 'function') { @@ -80,7 +82,7 @@ export default class NodeFire { but got "${ref}".` ); } - this.$scope = scope || {}; + this.$scope = scope || {} as TScope; this.$ref = ref; this._path = undefined; // initialized lazily @@ -131,7 +133,7 @@ export default class NodeFire { * Returns a NodeFire reference at the same location as this query or reference. * @return A NodeFire reference at the same location as this query or reference. */ - get ref(): NodeFire { + get ref(): NodeFire { if (this.$ref.isEqual(this.$ref.ref)) return this; return new NodeFire(this.$ref.ref, this.$scope); } @@ -140,7 +142,7 @@ export default class NodeFire { * Returns a NodeFire reference to the root of the database. * @return {NodeFire} The root reference of the database. */ - get root(): NodeFire { + get root(): NodeFire { if (this.$ref.isEqual(this.$ref.ref.root)) return this; return new NodeFire(this.$ref.ref.root, this.$scope); } @@ -150,7 +152,7 @@ export default class NodeFire { * reference is `null`. * @return {NodeFire|null} The parent location of this reference. */ - get parent(): NodeFire | null { + get parent(): NodeFire | null { if (this.$ref.ref.parent === null) return null; return new NodeFire(this.$ref.ref.parent, this.$scope); } @@ -213,7 +215,7 @@ export default class NodeFire { * @param {Nodefire} otherRef Another NodeFire instance against which to compare. * @return {boolean} */ - isEqual(otherRef: NodeFire): boolean { + isEqual(otherRef: NodeFire): boolean { return this.$ref.isEqual(otherRef.$ref); } @@ -231,7 +233,7 @@ export default class NodeFire { * precedence over) the one carried by this NodeFire object. * @return A new NodeFire object with the same reference and new scope. */ - scope(scope: Scope): NodeFire { + scope(scope: TSource): NodeFire { return new NodeFire(this.$ref, _.assign(_.clone(this.$scope), scope)); } @@ -244,7 +246,9 @@ export default class NodeFire { * scope. * @return {NodeFire} A new NodeFire object on the child reference, and with the augmented scope. */ - child(path: string, scope?: Scope): NodeFire { + child( + path: string, scope?: TSource): + NodeFire { const child = this.scope(scope); return new NodeFire(this.$ref.ref.child(child.interpolate(path)), child.$scope); } @@ -345,7 +349,7 @@ export default class NodeFire { * @return A promise that is resolved to a new NodeFire object that refers to the newly * pushed value (with the same scope as this object), or rejected with an error. */ - push(value: Value, options?: { timeout?: number }): Promise { + push(value: Value, options?: { timeout?: number }): Promise> { if (value === undefined || value === null) { return Promise.resolve(new NodeFire(this.$ref.ref.push(), this.$scope)); } @@ -709,35 +713,35 @@ export default class NodeFire { }); } - orderByChild(path: string): NodeFire { + orderByChild(path: string): NodeFire { return new NodeFire(this.$ref.orderByChild(path), this.$scope); } - equalTo(value: PrimitiveValue): NodeFire { + equalTo(value: PrimitiveValue): NodeFire { return new NodeFire(this.$ref.equalTo(value), this.$scope); } - limitToFirst(limit: number): NodeFire { + limitToFirst(limit: number): NodeFire { return new NodeFire(this.$ref.limitToFirst(limit), this.$scope); } - limitToLast(limit: number): NodeFire { + limitToLast(limit: number): NodeFire { return new NodeFire(this.$ref.limitToLast(limit), this.$scope); } - startAt(value: PrimitiveValue, key?: string): NodeFire { + startAt(value: PrimitiveValue, key?: string): NodeFire { return new NodeFire(this.$ref.startAt(value, key), this.$scope); } - endAt(value: PrimitiveValue, key?: string): NodeFire { + endAt(value: PrimitiveValue, key?: string): NodeFire { return new NodeFire(this.$ref.endAt(value, key), this.$scope); } - orderByKey(): NodeFire { + orderByKey(): NodeFire { return new NodeFire(this.$ref.orderByKey(), this.$scope); } - orderByValue(): NodeFire { + orderByValue(): NodeFire { return new NodeFire(this.$ref.orderByValue(), this.$scope); } } @@ -748,10 +752,10 @@ export default class NodeFire { ref returns a NodeFire instance, val() normalizes the value, and child() takes an optional refining scope. */ -export class Snapshot { +export class Snapshot { $snap: admin.database.DataSnapshot; - $nodeFire: NodeFire; - constructor(snap: admin.database.DataSnapshot, nodeFire: NodeFire) { + $nodeFire: NodeFire; + constructor(snap: admin.database.DataSnapshot, nodeFire: NodeFire) { this.$snap = snap; this.$nodeFire = nodeFire; } @@ -760,7 +764,7 @@ export class Snapshot { return this.$snap.key; } - get ref(): NodeFire { + get ref(): NodeFire { return new NodeFire(this.$snap.ref, this.$nodeFire.$scope); } @@ -768,12 +772,12 @@ export class Snapshot { return getNormalValue(this.$snap); } - child(path: string, scope: Scope): Snapshot { + child(path: string, scope: TSource): Snapshot { const childNodeFire = this.$nodeFire.scope(scope); return new Snapshot(this.$snap.child(childNodeFire.interpolate(path)), childNodeFire); } - forEach(callback: (snapshot: Snapshot) => any): any { + forEach(callback: (snapshot: Snapshot) => any): any { this.$snap.forEach(child => { return callback(new Snapshot(child, this.$nodeFire)); }); @@ -805,7 +809,7 @@ type CapturableCallback = // wrappers is equal to the number of on()s for that callback, and we can safely pop one with each // call to off(). function captureCallback( - nodeFire: NodeFire, + nodeFire: NodeFire, eventType: admin.database.EventType, callback: CapturableCallback, ): (a: admin.database.DataSnapshot, b?: string) => any { @@ -821,7 +825,7 @@ function captureCallback( } function popCallback( - nodeFire: NodeFire, eventType: admin.database.EventType, callback: CapturableCallback + nodeFire: NodeFire, eventType: admin.database.EventType, callback: CapturableCallback ): NodeFireCallback { const key = eventType + '::' + nodeFire.toString(); return callback.$nodeFireCallbacks[key].pop(); @@ -846,7 +850,7 @@ function delegateSnapshot(method) { }; } -function wrapReject(nodefire: NodeFire, method, value, reject?) { +function wrapReject(nodefire: NodeFire, method, value, reject?) { let hasValue = true; if (!reject) { reject = value;