From d792ec64517d171fdb6d5473aad0932bfc5d8668 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Thu, 14 May 2026 15:53:32 -0500 Subject: [PATCH] refactor(perf)!: migrate to TypeScript BREAKING CHANGE: perf types now match firebase-js-sdk as closely as possible Please see https://rnfirebase.io/migrating-to-v25 for help migrating if needed. react-native-firebase has a goal to be a drop-in replacement for firebase-js-sdk, with native extensions and performance. It has always worked that way at the javascript level but the typescript types have been divergent. We are fixing that as we refactor to typescript. Please bear with us as we get closer to our goal of react-native-firebase matching firebase-js-sdk both in functionality where possible, but also in exact typescript typing. Specifics for Performance: - changed modular `initializePerformance(app, settings)` to return `FirebasePerformance` synchronously instead of `Promise`, matching firebase-js-sdk; TypeScript consumers that call `.then(...)` on it will need to use the returned instance directly. - aligned the modular `FirebasePerformance` type with firebase-js-sdk, so it no longer exposes older namespaced instance-style methods such as `newTrace`, `startTrace`, `newHttpMetric`, `newScreenTrace`, `startScreenTrace`, or `setPerformanceCollectionEnabled` in the modular typings; use `trace(perf, name)`, `httpMetric(perf, url, method)`, `newScreenTrace(perf, name)`, `startScreenTrace(perf, name)`, and the `dataCollectionEnabled` property instead. - changed `PerformanceSettings` to the firebase-js-sdk shape, with optional `dataCollectionEnabled` and `instrumentationEnabled`. - changed modular trace and metric `getAttribute(...)` typings from `string | null` to `string | undefined`, matching firebase-js-sdk. - kept React Native-only modular exports for native functionality: `httpMetric`, `newScreenTrace`, `startScreenTrace`, plus `HttpMethod`, `HttpMetric`, and `ScreenTrace`. - kept the deprecated namespaced API under `FirebasePerformanceTypes`, but split it from the modular public types and marked it as deprecated for compatibility. --- .../compare-types/configs/perf-config.ts | 67 ++ .../packages/perf/firebase-sdk.d.ts | 162 +++++ .github/scripts/compare-types/src/registry.ts | 13 +- packages/perf/__tests__/perf.test.ts | 4 + .../perf/lib/{HttpMetric.js => HttpMetric.ts} | 29 +- ...hAttributes.js => MetricWithAttributes.ts} | 18 +- .../lib/{ScreenTrace.js => ScreenTrace.ts} | 14 +- packages/perf/lib/{Trace.js => Trace.ts} | 30 +- packages/perf/lib/index.d.ts | 583 ------------------ packages/perf/lib/index.ts | 25 + packages/perf/lib/modular.ts | 116 ++++ packages/perf/lib/modular/index.d.ts | 89 --- packages/perf/lib/modular/index.js | 103 ---- packages/perf/lib/{index.js => namespaced.ts} | 88 ++- packages/perf/lib/types/internal.ts | 80 +++ packages/perf/lib/types/namespaced.ts | 162 +++++ packages/perf/lib/types/perf.ts | 99 +++ packages/perf/package.json | 44 +- packages/perf/tsconfig.json | 20 + packages/perf/type-test.ts | 5 +- packages/perf/typedoc.json | 4 +- tests/ios/Podfile.lock | 4 +- tsconfig.json | 4 +- yarn.lock | 269 ++++++-- 24 files changed, 1146 insertions(+), 886 deletions(-) create mode 100644 .github/scripts/compare-types/configs/perf-config.ts create mode 100644 .github/scripts/compare-types/packages/perf/firebase-sdk.d.ts rename packages/perf/lib/{HttpMetric.js => HttpMetric.ts} (78%) rename packages/perf/lib/{MetricWithAttributes.js => MetricWithAttributes.ts} (76%) rename packages/perf/lib/{ScreenTrace.js => ScreenTrace.ts} (79%) rename packages/perf/lib/{Trace.js => Trace.ts} (81%) delete mode 100644 packages/perf/lib/index.d.ts create mode 100644 packages/perf/lib/index.ts create mode 100644 packages/perf/lib/modular.ts delete mode 100644 packages/perf/lib/modular/index.d.ts delete mode 100644 packages/perf/lib/modular/index.js rename packages/perf/lib/{index.js => namespaced.ts} (64%) create mode 100644 packages/perf/lib/types/internal.ts create mode 100644 packages/perf/lib/types/namespaced.ts create mode 100644 packages/perf/lib/types/perf.ts create mode 100644 packages/perf/tsconfig.json diff --git a/.github/scripts/compare-types/configs/perf-config.ts b/.github/scripts/compare-types/configs/perf-config.ts new file mode 100644 index 0000000000..6da32fe60a --- /dev/null +++ b/.github/scripts/compare-types/configs/perf-config.ts @@ -0,0 +1,67 @@ +/** + * Known differences between the firebase-js-sdk @firebase/performance modular + * API and the @react-native-firebase/perf modular API. + */ + +import type { PackageConfig } from '../../src/types'; + +const config: PackageConfig = { + missingInRN: [], + extraInRN: [ + { + name: 'HttpMethod', + reason: + 'String union of HTTP verbs used by React Native HTTP metrics. The web Performance ' + + 'modular API does not expose HTTP metrics in the public tree-shakeable surface.', + }, + { + name: 'ScreenTrace', + reason: + 'React Native screen trace type for slow/frozen frame reporting. No equivalent exists ' + + 'in the firebase-js-sdk modular Performance API.', + }, + { + name: 'HttpMetric', + reason: + 'React Native HTTP request metric type backed by native instrumentation. The web SDK ' + + 'does not expose this type on the modular public surface.', + }, + { + name: 'httpMetric', + reason: + 'React Native modular helper that constructs an `HttpMetric`. No equivalent exists in ' + + 'the firebase-js-sdk modular Performance API.', + }, + { + name: 'newScreenTrace', + reason: + 'React Native modular helper that constructs a `ScreenTrace`. No equivalent exists in ' + + 'the firebase-js-sdk modular Performance API.', + }, + { + name: 'startScreenTrace', + reason: + 'React Native modular helper that creates and starts a `ScreenTrace`. No equivalent ' + + 'exists in the firebase-js-sdk modular Performance API.', + }, + ], + differentShape: [ + { + name: 'FirebasePerformance', + reason: + 'React Native extends the service interface with native collection state (`isPerformanceCollectionEnabled`), ' + + 'a deprecated `setPerformanceCollectionEnabled` bridge helper, and factory methods for traces, ' + + 'screen traces, and HTTP metrics. The firebase-js-sdk web type only exposes `app`, ' + + '`instrumentationEnabled`, and `dataCollectionEnabled`.', + }, + { + name: 'PerformanceTrace', + reason: + 'React Native uses async `start`/`stop` (`Promise`) because work crosses the native bridge. ' + + 'The web SDK uses synchronous `start`/`stop` and exposes `record()`. RN Firebase exposes ' + + '`getMetrics` and `removeMetric` for native-backed custom metrics instead of the web shape.', + }, + ], +}; + +export default config; diff --git a/.github/scripts/compare-types/packages/perf/firebase-sdk.d.ts b/.github/scripts/compare-types/packages/perf/firebase-sdk.d.ts new file mode 100644 index 0000000000..2b0aae0bf1 --- /dev/null +++ b/.github/scripts/compare-types/packages/perf/firebase-sdk.d.ts @@ -0,0 +1,162 @@ +/** + * Public types snapshot from the Firebase JS SDK (@firebase/performance). + * + * Source: firebase-js-sdk `node_modules/@firebase/performance/dist/src/index.d.ts` + * and `node_modules/@firebase/performance/dist/src/public_types.d.ts` + * Modality: modular (tree-shakeable) API only + * + * This file is the reference snapshot used to detect API drift between the + * firebase-js-sdk and the @react-native-firebase/perf modular API. + * + * When a new version of the firebase-js-sdk ships with type changes, update + * this file with the new public modular types from @firebase/performance. + */ + +import { FirebaseApp } from '@firebase/app'; + +/** + * Defines configuration options for the Performance Monitoring SDK. + * + * @public + */ +export interface PerformanceSettings { + /** Whether to collect custom events. */ + dataCollectionEnabled?: boolean; + /** Whether to collect out of the box events. */ + instrumentationEnabled?: boolean; +} + +/** + * The Firebase Performance Monitoring service interface. + * + * @public + */ +export interface FirebasePerformance { + /** + * The {@link @firebase/app#FirebaseApp} this `FirebasePerformance` instance is associated with. + */ + app: FirebaseApp; + /** + * Controls the logging of automatic traces and HTTP/S network monitoring. + */ + instrumentationEnabled: boolean; + /** + * Controls the logging of custom traces. + */ + dataCollectionEnabled: boolean; +} + +/** + * The interface representing a `Trace`. + * + * @public + */ +export interface PerformanceTrace { + /** + * Starts the timing for the trace instance. + */ + start(): void; + /** + * Stops the timing of the trace instance and logs the data of the instance. + */ + stop(): void; + /** + * Records a trace from given parameters. This provides a direct way to use trace without a need to + * start/stop. This is useful for use cases in which the trace cannot directly be used + * (e.g. if the duration was captured before the Performance SDK was loaded). + * + * @param startTime - trace start time since epoch in millisec. + * @param duration - The duration of the trace in millisec. + * @param options - An object which can optionally hold maps of custom metrics and + * custom attributes. + */ + record( + startTime: number, + duration: number, + options?: { + metrics?: { + [key: string]: number; + }; + attributes?: { + [key: string]: string; + }; + }, + ): void; + /** + * Adds to the value of a custom metric. If a custom metric with the provided name does not + * exist, it creates one with that name and the value equal to the given number. The value will be floored down to an + * integer. + * + * @param metricName - The name of the custom metric. + * @param num - The number to be added to the value of the custom metric. If not provided, it + * uses a default value of one. + */ + incrementMetric(metricName: string, num?: number): void; + /** + * Sets the value of the specified custom metric to the given number regardless of whether + * a metric with that name already exists on the trace instance or not. The value will be floored down to an + * integer. + * + * @param metricName - Name of the custom metric. + * @param num - Value to of the custom metric. + */ + putMetric(metricName: string, num: number): void; + /** + * Returns the value of the custom metric by that name. If a custom metric with that name does + * not exist will return zero. + * + * @param metricName - Name of the custom metric. + */ + getMetric(metricName: string): number; + /** + * Set a custom attribute of a trace to a certain value. + * + * @param attr - Name of the custom attribute. + * @param value - Value of the custom attribute. + */ + putAttribute(attr: string, value: string): void; + /** + * Retrieves the value which a custom attribute is set to. + * + * @param attr - Name of the custom attribute. + */ + getAttribute(attr: string): string | undefined; + /** + * Removes the specified custom attribute from a trace instance. + * + * @param attr - Name of the custom attribute. + */ + removeAttribute(attr: string): void; + /** + * Returns a map of all custom attributes of a trace instance. + */ + getAttributes(): { + [key: string]: string; + }; +} + +/** + * Returns a {@link FirebasePerformance} instance for the given app. + * @param app - The {@link @firebase/app#FirebaseApp} to use. + * @public + */ +export declare function getPerformance(app?: FirebaseApp): FirebasePerformance; + +/** + * Returns a {@link FirebasePerformance} instance for the given app. Can only be called once. + * @param app - The {@link @firebase/app#FirebaseApp} to use. + * @param settings - Optional settings for the {@link FirebasePerformance} instance. + * @public + */ +export declare function initializePerformance( + app: FirebaseApp, + settings?: PerformanceSettings, +): FirebasePerformance; + +/** + * Returns a new `PerformanceTrace` instance. + * @param performance - The {@link FirebasePerformance} instance to use. + * @param name - The name of the trace. + * @public + */ +export declare function trace(performance: FirebasePerformance, name: string): PerformanceTrace; diff --git a/.github/scripts/compare-types/src/registry.ts b/.github/scripts/compare-types/src/registry.ts index 851ed89851..c936186094 100644 --- a/.github/scripts/compare-types/src/registry.ts +++ b/.github/scripts/compare-types/src/registry.ts @@ -18,6 +18,7 @@ import appCheckConfig from '../configs/app-check'; import firestoreConfig from '../configs/firestore'; import firestorePipelinesConfig from '../configs/firestore-pipelines'; import remoteConfigConfig from '../configs/remote-config'; +import perfConfig from '../configs/perf-config'; const SCRIPT_DIR = path.resolve(__dirname, '..'); const REPO_ROOT = path.resolve(SCRIPT_DIR, '..', '..', '..'); @@ -247,6 +248,14 @@ export const packages: PackageEntry[] = [ ], config: firestorePipelinesConfig, })), + { + name: 'perf', + firebaseSdkTypesPaths: [requiredFirebaseTypes('performance')], + rnFirebaseModularFiles: [ + path.join(rnDist('perf'), 'types', 'perf.d.ts'), + path.join(rnDist('perf'), 'modular.d.ts'), + ], + rnFirebaseSupportFiles: [], + config: perfConfig, + }, ]; - - diff --git a/packages/perf/__tests__/perf.test.ts b/packages/perf/__tests__/perf.test.ts index ad6bbe1eb1..133685a052 100644 --- a/packages/perf/__tests__/perf.test.ts +++ b/packages/perf/__tests__/perf.test.ts @@ -200,6 +200,7 @@ describe('Performance Monitoring', function () { const perf = getPerformance(); perfV9Deprecation( () => trace(perf, 'invertase'), + // @ts-expect-error Combines modular and namespace API () => perf.newTrace('invertase'), 'newTrace', ); @@ -209,6 +210,7 @@ describe('Performance Monitoring', function () { const perf = getPerformance(); perfV9Deprecation( () => httpMetric(perf, 'https://invertase.io', 'GET'), + // @ts-expect-error Combines modular and namespace API () => perf.newHttpMetric('https://invertase.io', 'GET'), 'newHttpMetric', ); @@ -218,6 +220,7 @@ describe('Performance Monitoring', function () { const perf = getPerformance(); perfV9Deprecation( () => newScreenTrace(perf, 'invertase'), + // @ts-expect-error Combines modular and namespace API () => perf.newScreenTrace('invertase'), 'newScreenTrace', ); @@ -227,6 +230,7 @@ describe('Performance Monitoring', function () { const perf = getPerformance(); perfV9Deprecation( () => startScreenTrace(perf, 'invertase'), + // @ts-expect-error Combines modular and namespace API () => perf.startScreenTrace('invertase'), 'startScreenTrace', ); diff --git a/packages/perf/lib/HttpMetric.js b/packages/perf/lib/HttpMetric.ts similarity index 78% rename from packages/perf/lib/HttpMetric.js rename to packages/perf/lib/HttpMetric.ts index f4e52de31b..19912cfe31 100644 --- a/packages/perf/lib/HttpMetric.js +++ b/packages/perf/lib/HttpMetric.ts @@ -16,10 +16,23 @@ */ import { isNull, isNumber, isString } from '@react-native-firebase/app/dist/module/common'; + import MetricWithAttributes from './MetricWithAttributes'; +import type { RNFBPerfHttpMetricData, RNFBPerfNativeModule } from './types/internal'; +import type { HttpMethod } from './types/perf'; + export default class HttpMetric extends MetricWithAttributes { - constructor(native, url, httpMethod) { + private readonly _url: string; + private readonly _httpMethod: HttpMethod; + private _httpResponseCode: number | null; + private _requestPayloadSize: number | null; + private _responsePayloadSize: number | null; + private _responseContentType: string | null; + private _started: boolean; + private _stopped: boolean; + + constructor(native: RNFBPerfNativeModule, url: string, httpMethod: HttpMethod) { super(native); this._url = url; @@ -34,7 +47,7 @@ export default class HttpMetric extends MetricWithAttributes { this._stopped = false; } - setHttpResponseCode(code) { + setHttpResponseCode(code: number | null): void { if (!isNumber(code) && !isNull(code)) { throw new Error( "firebase.perf.HttpMetric.setHttpResponseCode(*) 'code' must be a number or null.", @@ -44,7 +57,7 @@ export default class HttpMetric extends MetricWithAttributes { this._httpResponseCode = code; } - setRequestPayloadSize(bytes) { + setRequestPayloadSize(bytes: number | null): void { if (!isNumber(bytes) && !isNull(bytes)) { throw new Error( "firebase.perf.HttpMetric.setRequestPayloadSize(*) 'bytes' must be a number or null.", @@ -54,7 +67,7 @@ export default class HttpMetric extends MetricWithAttributes { this._requestPayloadSize = bytes; } - setResponsePayloadSize(bytes) { + setResponsePayloadSize(bytes: number | null): void { if (!isNumber(bytes) && !isNull(bytes)) { throw new Error( "firebase.perf.HttpMetric.setResponsePayloadSize(*) 'bytes' must be a number or null.", @@ -64,7 +77,7 @@ export default class HttpMetric extends MetricWithAttributes { this._responsePayloadSize = bytes; } - setResponseContentType(contentType) { + setResponseContentType(contentType: string | null): void { if (!isString(contentType) && !isNull(contentType)) { throw new Error( "firebase.perf.HttpMetric.setResponseContentType(*) 'contentType' must be a string or null.", @@ -74,7 +87,7 @@ export default class HttpMetric extends MetricWithAttributes { this._responseContentType = contentType; } - start() { + start(): Promise { if (this._started) { return Promise.resolve(null); } @@ -83,13 +96,13 @@ export default class HttpMetric extends MetricWithAttributes { return this.native.startHttpMetric(this._id, this._url, this._httpMethod); } - stop() { + stop(): Promise { if (this._stopped) { return Promise.resolve(null); } this._stopped = true; - const metricData = { + const metricData: RNFBPerfHttpMetricData = { attributes: Object.assign({}, this._attributes), }; diff --git a/packages/perf/lib/MetricWithAttributes.js b/packages/perf/lib/MetricWithAttributes.ts similarity index 76% rename from packages/perf/lib/MetricWithAttributes.js rename to packages/perf/lib/MetricWithAttributes.ts index 5eaa768236..ca86b4d3b4 100644 --- a/packages/perf/lib/MetricWithAttributes.js +++ b/packages/perf/lib/MetricWithAttributes.ts @@ -17,23 +17,33 @@ import { hasOwnProperty, isString } from '@react-native-firebase/app/dist/module/common'; +import type { RNFBPerfNativeModule } from './types/internal'; + let id = 0; export default class MetricWithAttributes { - constructor(native) { + protected readonly native: RNFBPerfNativeModule; + protected readonly _id: number; + protected _attributes: Record; + + constructor(native: RNFBPerfNativeModule) { this._id = id++; this.native = native; this._attributes = {}; } - getAttribute(attribute) { + getAttribute(attribute: string): string | null { if (!isString(attribute)) { throw new Error("firebase.perf.*.getAttribute(*) 'attribute' must be a string."); } - return this._attributes[attribute] || null; + return hasOwnProperty(this._attributes, attribute) ? this._attributes[attribute]! : null; + } + + getAttributes(): Record { + return Object.assign({}, this._attributes); } - putAttribute(attribute, value) { + putAttribute(attribute: string, value: string): void { // TODO(VALIDATION): attribute: no leading or trailing whitespace, no leading underscore '_' if (!isString(attribute) || attribute.length > 40) { throw new Error( diff --git a/packages/perf/lib/ScreenTrace.js b/packages/perf/lib/ScreenTrace.ts similarity index 79% rename from packages/perf/lib/ScreenTrace.js rename to packages/perf/lib/ScreenTrace.ts index 2016830c72..af46df07ad 100644 --- a/packages/perf/lib/ScreenTrace.js +++ b/packages/perf/lib/ScreenTrace.ts @@ -17,10 +17,18 @@ import { isIOS } from '@react-native-firebase/app/dist/module/common'; +import type { RNFBPerfNativeModule } from './types/internal'; + let id = 0; export default class ScreenTrace { - constructor(native, identifier) { + readonly native: RNFBPerfNativeModule; + private readonly _identifier: string; + private readonly _id: number; + private _started: boolean; + private _stopped: boolean; + + constructor(native: RNFBPerfNativeModule, identifier: string) { this.native = native; this._identifier = identifier; this._id = id++; @@ -28,7 +36,7 @@ export default class ScreenTrace { this._stopped = false; } - start() { + start(): Promise { if (isIOS) { return Promise.reject(new Error('Custom screentraces are currently not supported on iOS.')); } @@ -40,7 +48,7 @@ export default class ScreenTrace { return this.native.startScreenTrace(this._id, this._identifier); } - stop() { + stop(): Promise { if (!this._started || this._stopped) { return Promise.resolve(null); } diff --git a/packages/perf/lib/Trace.js b/packages/perf/lib/Trace.ts similarity index 81% rename from packages/perf/lib/Trace.js rename to packages/perf/lib/Trace.ts index 8d37b1a84d..f973afc79c 100644 --- a/packages/perf/lib/Trace.js +++ b/packages/perf/lib/Trace.ts @@ -16,10 +16,18 @@ */ import { hasOwnProperty, isNumber, isString } from '@react-native-firebase/app/dist/module/common'; + import MetricWithAttributes from './MetricWithAttributes'; +import type { RNFBPerfNativeModule } from './types/internal'; + export default class Trace extends MetricWithAttributes { - constructor(native, identifier) { + private readonly _identifier: string; + private readonly _metrics: Record; + private _started: boolean; + private _stopped: boolean; + + constructor(native: RNFBPerfNativeModule, identifier: string) { super(native); this._identifier = identifier; @@ -29,19 +37,19 @@ export default class Trace extends MetricWithAttributes { this._stopped = false; } - getMetric(metricName) { + getMetric(metricName: string): number { if (!isString(metricName)) { throw new Error("firebase.perf.Trace.getMetric(*) 'metricName' must be a string."); } - return hasOwnProperty(this._metrics, metricName) ? this._metrics[metricName] : 0; + return hasOwnProperty(this._metrics, metricName) ? this._metrics[metricName]! : 0; } - getMetrics() { + getMetrics(): Record { return Object.assign({}, this._metrics); } - putMetric(metricName, value) { + putMetric(metricName: string, value: number): void { // TODO(VALIDATION): metricName: no leading or trailing whitespace, no leading underscore '_' character, max length is 32 characters // TODO(VALIDATION): value: >= 0 if (!isString(metricName)) { @@ -55,21 +63,23 @@ export default class Trace extends MetricWithAttributes { this._metrics[metricName] = value; } - incrementMetric(metricName, incrementBy) { + incrementMetric(metricName: string, num?: number): void { // TODO(VALIDATION): metricName: no leading or trailing whitespace, no leading underscore '_' character, max length is 32 characters // TODO(VALIDATION): value: >= 0 if (!isString(metricName)) { throw new Error("firebase.perf.Trace.incrementMetric(*, _) 'metricName' must be a string."); } + const incrementBy = num ?? 1; + if (!isNumber(incrementBy)) { - throw new Error("firebase.perf.Trace.incrementMetric(_, *) 'incrementBy' must be a number."); + throw new Error("firebase.perf.Trace.incrementMetric(_, *) 'num' must be a number."); } this._metrics[metricName] = this.getMetric(metricName) + incrementBy; } - removeMetric(metric) { + removeMetric(metric: string): void { if (!isString(metric)) { throw new Error("firebase.perf.Trace.removeMetric(*) 'metric' must be a string."); } @@ -77,7 +87,7 @@ export default class Trace extends MetricWithAttributes { delete this._metrics[metric]; } - start() { + start(): Promise { if (this._started) { return Promise.resolve(null); } @@ -86,7 +96,7 @@ export default class Trace extends MetricWithAttributes { return this.native.startTrace(this._id, this._identifier); } - stop() { + stop(): Promise { if (this._stopped) { return Promise.resolve(null); } diff --git a/packages/perf/lib/index.d.ts b/packages/perf/lib/index.d.ts deleted file mode 100644 index aa25dede79..0000000000 --- a/packages/perf/lib/index.d.ts +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import { ReactNativeFirebase } from '@react-native-firebase/app'; - -/** - * Firebase Performance Monitoring package for React Native. - * - * #### Example 1 - * - * Access the firebase export from the `perf` package: - * - * ```js - * import { firebase } from '@react-native-firebase/perf'; - * - * // firebase.perf().X - * ``` - * - * #### Example 2 - * - * Using the default export from the `perf` package: - * - * ```js - * import perf from '@react-native-firebase/perf'; - * - * // perf().X - * ``` - * - * #### Example 3 - * - * Using the default export from the `app` package: - * - * ```js - * import firebase from '@react-native-firebase/app'; - * import '@react-native-firebase/perf'; - * - * // firebase.perf().X - * ``` - * - * @firebase perf - */ -export namespace FirebasePerformanceTypes { - /** - * Type alias describing the valid HTTP methods accepted when creating a new {@link perf.HttpMetric} instance. - * - * #### Example - * - * ```js - * const metric = perf().newHttpMetric('https://api.com/user', 'PATCH'); - * ``` - */ - import FirebaseModule = ReactNativeFirebase.FirebaseModule; - - /** - * Valid HTTP methods. - */ - export type HttpMethod = - | 'GET' - | 'HEAD' - | 'PUT' - | 'POST' - | 'PATCH' - | 'TRACE' - | 'DELETE' - | 'CONNECT' - | 'OPTIONS'; - - /** - * Trace allows you to time the beginning to end of a certain action in your app with additional metric values and attributes. - */ - export class Trace { - /** - * Returns the value of an attribute. Returns null if it does not exist. - * - * #### Example - * - * ```js - * const attribute = trace.getAttribute('userId'); - * ``` - * - * @param attribute Name of the attribute to fetch the value of. - */ - getAttribute(attribute: string): string | null; - - /** - * Sets a String value for the specified attribute. Updates the value of the attribute if it already exists. - * The maximum number of attributes that can be added is 5. - * - * #### Example - * - * ```js - * trace.putAttribute('userId', '123456789'); - * ``` - * - * @param attribute Name of the attribute. Max length is 40 chars. - * @param value Value of the attribute. Max length is 100 chars. - */ - putAttribute(attribute: string, value: string): void; - - /** - * Gets the value of the metric with the given name in the current trace. If the metric - * doesn't exist, it will not be created and a 0 is returned. - * - * #### Example - * - * ```js - * const metric = trace.getMetric('hits'); - * ``` - * - * @param metricName Name of the metric to get. - */ - getMetric(metricName: string): number; - - /** - * Returns an object of all the currently added metrics and their number values. - * - * #### Example - * - * ```js - * const metrics = trace.getMetrics(); - * - * metrics.forEach(($) => { - * console.log($); - * }); - * ``` - */ - getMetrics(): { [key: string]: number }; - - /** - * Sets the value of the named metric with the provided number. - * - * If a metric with the given name exists it will be overwritten. - * If a metric with the given name doesn't exist, a new one will be created. - * - * #### Example - * - * ```js - * trace.putMetric('hits', 1); - * ``` - * - * @param metricName Name of the metric to set. Must not have a leading or trailing whitespace, no leading underscore '_' character and have a max length of 32 characters. - * @param value The value the metric should be set to. - */ - putMetric(metricName: string, value: number): void; - - /** - * Increments the named metric by the `incrementBy` value. - * - * If a metric with the given name doesn't exist, a new one will be created starting with the value of `incrementBy`. - * - * ```js - * trace.incrementMetric('hits', 1); - * ``` - * - * @param metricName Name of the metric to increment. Must not have a leading or trailing whitespace, no leading underscore '_' character and have a max length of 32 characters. - * @param incrementBy The value the metric should be incremented by. - */ - incrementMetric(metricName: string, incrementBy: number): void; - - /** - * Removes a metric by name if it exists. - * - * #### Example - * - * ```js - * trace.removeMetric('hits'); - * ``` - * - * @param metricName Name of the metric to remove. - */ - removeMetric(metricName: string): void; - - /** - * Marks the start time of the trace. Does nothing if already started. - * - * #### Example - * - * ```js - * const trace = firebase.perf().newTrace('example'); - * await trace.start(); - * ``` - */ - start(): Promise; - - /** - * Marks the end time of the trace and queues the metric on the device for transmission. Does nothing if already stopped. - * - * * #### Example - * - * ```js - * const trace = firebase.perf().newTrace('example'); - * await trace.start(); - * trace.putMetric('hits', 1); - * await trace.stop(); - * ``` - */ - stop(): Promise; - } - - /** - * ScreenTrace allows you to record a custom screen rendering trace of slow and frozen frames. - * Throws on constructor if hardware acceleration is off or if Android is 9.0 or 9.1. - * - * @platform android Android !== 9.0.0 && Adnroid !== 9.1.0 - */ - export class ScreenTrace { - /** - * Starts a new screen trace. Does nothing if already started. - * - * #### Example - * - * ```js - * try { - * const trace = firebase.perf().newScreenTrace('FooScreen'); - * await trace.start(); - * } catch (e) { - * - * } - * ``` - * @platform android Android >= 9.0.0 - */ - start(): Promise; - /** - * Stops and sends the screen trace. - * - * #### Example - * - * ```js - * try { - * const trace = firebase.perf().newScreenTrace('FooScreen'); - * await trace.start(); - * await trace.stop(); - * } catch (e) { - * - * } - * ``` - * @platform android Android >= 9.0.0 - */ - stop(): Promise; - } - - /** - * Metric used to collect data for network requests/responses. A new instance must be used for every request/response. - */ - export class HttpMetric { - /** - * Returns the value of an attribute. Returns null if it does not exist. - * - * #### Example - * - * ```js - * const attribute = metric.getAttribute('user_role'); - * ``` - * - * @param attribute Name of the attribute to fetch the value of - */ - getAttribute(attribute: string): string | null; - - /** - * Returns an object of all the currently added attributes. - * - * #### Example - * - * ```js - * const attributes = metric.getAttributes(); - * - * attributes.forEach(($) => { - * console.log($); - * }); - * ``` - */ - getAttributes(): { [key: string]: string }; - - /** - * Sets a String value for the specified attribute. Updates the value of the attribute if it already exists. - * The maximum number of attributes that can be added is 5. - * - * #### Example - * - * ```js - * metric.putAttribute('user_role', 'admin'); - * ``` - * - * @param attribute Name of the attribute. Max length is 40 chars. - * @param value Value of the attribute. Max length is 100 chars. - */ - putAttribute(attribute: string, value: string): void; - - /** - * Removes an already added attribute. Does nothing if attribute does not exist. - * - * #### Example - * - * ```js - * metric.removeAttribute('user_role'); - * ``` - * - * @param attribute Name of the attribute to be removed. - */ - removeAttribute(attribute: string): void; - - /** - * Sets the httpResponse code of the request. - * - * #### Example - * - * ```js - * const response = await fetch(url); - * metric.setHttpResponseCode(response.status); - * ``` - * > This is required for every request, if you do not provide this your metric will not be captured. - * - * - * @param code Value must be greater than 0. Set to null to remove. Invalid usage will be logged natively. - */ - setHttpResponseCode(code: number | null): void; - - /** - * Sets the size of the request payload. - * - * #### Example - * - * ```js - * const response = await fetch(url); - * metric.setRequestPayloadSize(response.headers.get('Content-Type')); - * ``` - * - * @param bytes Value must be greater than 0. Set to null to remove. Invalid usage will be logged natively. - */ - setRequestPayloadSize(bytes: number | null): void; - - /** - * Sets the size of the response payload. - * - * #### Example - * - * ```js - * const response = await fetch(url); - * metric.setResponsePayloadSize(response.headers.get('Content-Length')); - * ``` - * - * @param bytes Value must be greater than 0. Set to null to remove. Invalid usage will be logged natively. - */ - setResponsePayloadSize(bytes: number | null): void; - - /** - * Content type of the response e.g. `text/html` or `application/json`. - * - * #### Example - * - * ```js - * const response = await fetch(url); - * metric.setResponsePayloadSize(response.headers.get('Content-Type')); - * ``` - * - * @param contentType Valid string of MIME type. Set to null to remove. Invalid usage will be logged natively. - */ - setResponseContentType(contentType: string | null): void; - - /** - * Marks the start time of the request. Does nothing if already started. - * - * #### Example - * - * ```js - * const metric = firebase.perf().newHttpMetric('https://api.com/login', 'POST'); - * await metric.start(); - * ``` - */ - start(): Promise; - - /** - * Marks the end time of the response and queues the network request metric on the device for transmission. Does nothing if already stopped. - * - * #### Example - * - * ```js - * const metric = firebase.perf().newHttpMetric('https://api.com/login', 'POST'); - * await metric.start(); - * metric.putAttribute('user_role', 'admin'); - * await metric.stop(); - * ``` - */ - stop(): Promise; - } - - export interface Statics { - SDK_VERSION: string; - } - - /** - * The Firebase Performance Monitoring service interface. - * - * > This module is available for the default app only. - * - * #### Example - * - * Get the Performance Monitoring service for the default app: - * - * ```js - * const defaultAppPerf = firebase.perf(); - * ``` - */ - export class Module extends FirebaseModule { - /** - * The current `FirebaseApp` instance for this Firebase service. - */ - app: ReactNativeFirebase.FirebaseApp; - /** - * Determines whether performance monitoring is enabled or disabled. - * - * #### Example - * - * ```js - * const isEnabled = firebase.perf().isPerformanceCollectionEnabled; - * console.log('Performance collection enabled: ', isEnabled); - * ``` - */ - isPerformanceCollectionEnabled: boolean; - /** - * Determines whether to collect 'out of the box' (i.e already setup for Firebase Performance) events. - * This can be set for iOS. Android will always return "true" as it has to be set at gradle level. - */ - instrumentationEnabled: boolean; - /** - * Determines whether performance monitoring is enabled or disabled. - * - * #### Example - * - * ```js - * const isEnabled = firebase.perf().dataCollectionEnabled; - * console.log('Performance collection enabled: ', isEnabled); - * ``` - */ - dataCollectionEnabled: boolean; - /** - * Enables or disables performance monitoring. - * - * #### Example - * - * ```js - * // Disable performance monitoring collection - * await firebase.perf().setPerformanceCollectionEnabled(false); - * ``` - * @deprecated prefer setting `dataCollectionEnabled = boolean`. - * @param enabled Should performance monitoring be enabled. For iOS only, this also toggles whether instrumentation - * is enabled. See: https://firebase.google.com/docs/reference/ios/firebaseperformance/api/reference/Classes/FIRPerformance#instrumentationenabled - */ - setPerformanceCollectionEnabled(enabled: boolean): Promise; - - /** - * Creates a Trace instance with the given identifier. - * - * #### Example - * - * ```js - * const trace = firebase.perf().newTrace('user_profile'); - * await trace.start(); - * ``` - * - * @param identifier Name of the trace, no leading or trailing whitespace allowed, no leading underscore '_' character allowed, max length is 100. - */ - newTrace(identifier: string): Trace; - - /** - * Creates a Trace instance with the given identifier and immediately starts it. - * - * #### Example - * - * ```js - * const trace = await firebase.perf().startTrace('user_profile'); - * ``` - * - * @param identifier Name of the trace, no leading or trailing whitespace allowed, no leading underscore '_' character allowed, max length is 100. - */ - startTrace(identifier: string): Promise; - - /** - * Creates a ScreenTrace instance with the given identifier. - * Throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. - * - * #### Example - * - * ```js - * try { - * const trace = firebase.perf().newScreenTrace('FooScreen'); - * await trace.start(); - * } catch (e) { - * - * } - * ``` - * - * @param identifier Name of the trace, no leading or trailing whitespace allowed, no leading underscore '_' character allowed, max length is 100. - */ - newScreenTrace(identifier: string): ScreenTrace; - - /** - * Creates a ScreenTrace instance with the given identifier and immediately starts it. - * Throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. - * - * #### Example - * - * ```js - * try { - * const trace = await firebase.perf().startScreenTrace('FooScreen'); - * await trace.stop(); - * } catch (e) { - * - * } - * ``` - * @platform android Android !== 9.0.0 && Android !== 9.1.0 - * - * @param identifier Name of the screen - */ - startScreenTrace(identifier: string): Promise; - - /** - * Creates a HttpMetric instance for collecting network performance data for a single request/response - * - * #### Example - * - * ```js - * const metric = firebase.perf().newHttpMetric('https://api.com/user/1', 'GET'); - * await metric.start(); - * ``` - * - * @param url A valid url String, cannot be empty - * @param httpMethod One of the values GET, PUT, POST, DELETE, HEAD, PATCH, OPTIONS, TRACE, or CONNECT - */ - newHttpMetric(url: string, httpMethod: HttpMethod): HttpMetric; - } -} - -type PerfNamespace = ReactNativeFirebase.FirebaseModuleWithStatics< - FirebasePerformanceTypes.Module, - FirebasePerformanceTypes.Statics -> & { - firebase: ReactNativeFirebase.Module; - app(name?: string): ReactNativeFirebase.FirebaseApp; -}; - -declare const defaultExport: PerfNamespace; - -export const firebase: ReactNativeFirebase.Module & { - perf: typeof defaultExport; - app(name?: string): ReactNativeFirebase.FirebaseApp & { perf(): FirebasePerformanceTypes.Module }; -}; - -export default defaultExport; - -export * from './modular'; - -/** - * Attach namespace to `firebase.` and `FirebaseApp.`. - */ -declare module '@react-native-firebase/app' { - namespace ReactNativeFirebase { - import FirebaseModuleWithStatics = ReactNativeFirebase.FirebaseModuleWithStatics; - interface Module { - perf: FirebaseModuleWithStatics< - FirebasePerformanceTypes.Module, - FirebasePerformanceTypes.Statics - >; - } - interface FirebaseApp { - perf(): FirebasePerformanceTypes.Module; - } - } -} diff --git a/packages/perf/lib/index.ts b/packages/perf/lib/index.ts new file mode 100644 index 0000000000..b1f7adf0bc --- /dev/null +++ b/packages/perf/lib/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export type * from './types/perf'; + +export * from './modular'; + +export type { FirebasePerformanceTypes } from './types/namespaced'; + +export * from './namespaced'; +export { default } from './namespaced'; diff --git a/packages/perf/lib/modular.ts b/packages/perf/lib/modular.ts new file mode 100644 index 0000000000..b5d713e373 --- /dev/null +++ b/packages/perf/lib/modular.ts @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { getApp } from '@react-native-firebase/app'; +import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; + +import type { FirebaseApp } from '@react-native-firebase/app'; +import type { + FirebasePerformance, + HttpMetric, + HttpMethod, + PerformanceSettings, + PerformanceTrace, + ScreenTrace, +} from './types/perf'; + +import type { PerfInternal } from './types/internal'; + +function perfInternal(performance: FirebasePerformance): PerfInternal { + return performance as PerfInternal; +} + +/** + * Returns a {@link FirebasePerformance} instance for the given app. + * @param app - The FirebaseApp to use. Optional; defaults to the default app. + */ +export function getPerformance(app?: FirebaseApp): FirebasePerformance { + if (app) { + return getApp(app.name).perf() as FirebasePerformance; + } + + return getApp().perf() as FirebasePerformance; +} + +/** + * Returns a {@link FirebasePerformance} instance for the given app (aligned with the Firebase JS SDK). + * Can only be called once per app during initialization in typical usage. + * + * @param app - The FirebaseApp to use. + * @param settings - Optional {@link PerformanceSettings}. + */ +export function initializePerformance( + app: FirebaseApp, + settings?: PerformanceSettings, +): FirebasePerformance { + const perf = getPerformance(app); + + if (settings?.dataCollectionEnabled !== undefined) { + perf.dataCollectionEnabled = settings.dataCollectionEnabled; + } + if (settings?.instrumentationEnabled !== undefined) { + perf.instrumentationEnabled = settings.instrumentationEnabled; + } + + return perf; +} + +/** + * Returns a new {@link PerformanceTrace} instance. + * @param performance - The {@link FirebasePerformance} instance to use. + * @param name - The name of the trace. + */ +export function trace(performance: FirebasePerformance, name: string): PerformanceTrace { + return perfInternal(performance).newTrace(name, MODULAR_DEPRECATION_ARG); +} + +/** + * Creates an {@link HttpMetric} for a URL and HTTP method (React Native). + * @param performance - The {@link FirebasePerformance} instance to use. + * @param url - Request URL. + * @param httpMethod - HTTP method. + */ +export function httpMetric( + performance: FirebasePerformance, + url: string, + httpMethod: HttpMethod, +): HttpMetric { + return perfInternal(performance).newHttpMetric(url, httpMethod, MODULAR_DEPRECATION_ARG); +} + +/** + * Creates a {@link ScreenTrace} with the given screen name. + * Android only; throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. + * @param performance - The {@link FirebasePerformance} instance to use. + * @param screenName - Screen name; no leading/trailing whitespace, no leading `_`, max length 100. + */ +export function newScreenTrace(performance: FirebasePerformance, screenName: string): ScreenTrace { + return perfInternal(performance).newScreenTrace(screenName, MODULAR_DEPRECATION_ARG); +} + +/** + * Creates a {@link ScreenTrace} and starts it immediately. + * Android only; throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. + * @param performance - The {@link FirebasePerformance} instance to use. + * @param screenName - Name of the screen. + */ +export function startScreenTrace( + performance: FirebasePerformance, + screenName: string, +): Promise { + return perfInternal(performance).startScreenTrace(screenName, MODULAR_DEPRECATION_ARG); +} diff --git a/packages/perf/lib/modular/index.d.ts b/packages/perf/lib/modular/index.d.ts deleted file mode 100644 index 04a5be1ca8..0000000000 --- a/packages/perf/lib/modular/index.d.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { ReactNativeFirebase } from '@react-native-firebase/app'; -import { FirebasePerformanceTypes } from '..'; - -import Performance = FirebasePerformanceTypes.Module; - -import Trace = FirebasePerformanceTypes.Module.Trace; -import HttpMethod = FirebasePerformanceTypes.HttpMethod; -import HttpMetric = FirebasePerformanceTypes.HttpMetric; -import ScreenTrace = FirebasePerformanceTypes.ScreenTrace; -import FirebaseApp = ReactNativeFirebase.FirebaseApp; - -/** - * Returns a Performance instance for the given app. - * @param app - FirebaseApp. Optional. - * @returns {Performance} - */ -export function getPerformance(app?: FirebaseApp): Performance; - -type PerformanceSettings = { - dataCollectionEnabled: boolean; -}; - -/** - * Returns a Performance instance for the given app. - * @param app - FirebaseApp. Required. - * @param settings - Optional PerformanceSettings. Set "dataCollectionEnabled" which will enable/disable Performance collection. - * @returns {Promise} - */ -export function initializePerformance( - app: FirebaseApp, - settings?: PerformanceSettings, -): Promise; - -/** - * Returns a Trace instance. - * @param perf - Performance instance. - * @param identifier - A String to identify the Trace instance. - * @returns {Trace} - */ -export function trace(perf: Performance, identifier: string): Trace; - -/** - * Returns a HttpMetric instance. - * @param perf - Performance instance. - * @param identifier - A String to identify the HttpMetric instance. - * @param httpMethod - The HTTP method for the HttpMetric instance. - * @returns {HttpMetric} - */ -export function httpMetric( - perf: Performance, - identifier: string, - httpMethod: HttpMethod, -): HttpMetric; - -/** - * Creates a ScreenTrace instance with the given identifier. - * Throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. - * @platform android Android !== 9.0.0 && Android !== 9.1.0 - * @param perf - Performance instance. - * @param identifier - Name of the trace, no leading or trailing whitespace allowed, no leading underscore '_' character allowed, max length is 100. - * @returns {ScreenTrace} - */ -export function newScreenTrace(perf: Performance, identifier: string): ScreenTrace; - -/** - * Creates a ScreenTrace instance with the given identifier and immediately starts it. - * Throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. - * @platform android Android !== 9.0.0 && Android !== 9.1.0 - * @param perf - Performance instance. - * @param identifier - Name of the screen. - * @returns {Promise} - */ -export function startScreenTrace(perf: Performance, identifier: string): Promise; diff --git a/packages/perf/lib/modular/index.js b/packages/perf/lib/modular/index.js deleted file mode 100644 index 138b4b4d06..0000000000 --- a/packages/perf/lib/modular/index.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * @typedef {import('@firebase/app').FirebaseApp} FirebaseApp - * @typedef {import('..').FirebasePerformanceTypes.Module} Performance - * @typedef {import('..').FirebasePerformanceTypes.Trace} Trace - * @typedef {import('..').FirebasePerformanceTypes.ScreenTrace} ScreenTrace - * @typedef {import('..').FirebasePerformanceTypes.HttpMetric} HttpMetric - */ - -import { getApp } from '@react-native-firebase/app'; - -import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; - -/** - * Returns a Performance instance for the given app. - * @param app - FirebaseApp. Optional. - * @returns {Performance} - */ -export function getPerformance(app) { - if (app) { - return getApp(app.name).perf(); - } - - return getApp().perf(); -} - -/** - * Returns a Performance instance for the given app. - * @param app - FirebaseApp. Required. - * @param settings - Optional PerformanceSettings. Set "dataCollectionEnabled" which will enable/disable Performance collection. - * @returns {Performance} - */ -export async function initializePerformance(app, settings) { - const perf = getApp(app.name).perf(); - - if (settings && settings.dataCollectionEnabled !== undefined) { - perf.dataCollectionEnabled = settings.dataCollectionEnabled; - } - if (settings && settings.instrumentationEnabled !== undefined) { - perf.instrumentationEnabled = settings.instrumentationEnabled; - } - - return perf; -} - -/** - * Returns a Trace instance. - * @param perf - Performance instance - * @param identifier - A String to identify the Trace instance - * @returns {Trace} - */ -export function trace(perf, identifier) { - return perf.newTrace.call(perf, identifier, MODULAR_DEPRECATION_ARG); -} - -/** - * Returns a HttpMetric instance. - * @param perf - Performance instance - * @param identifier - A String to identify the HttpMetric instance - * @returns {HttpMetric} - */ -export function httpMetric(perf, identifier, httpMethod) { - return perf.newHttpMetric.call(perf, identifier, httpMethod, MODULAR_DEPRECATION_ARG); -} - -/** - * Creates a ScreenTrace instance with the given identifier. - * Throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. - * @platform android Android !== 9.0.0 && Android !== 9.1.0 - * @param perf - Performance instance - * @param identifier Name of the trace, no leading or trailing whitespace allowed, no leading underscore '_' character allowed, max length is 100. - * @returns {ScreenTrace} - */ -export function newScreenTrace(perf, identifier) { - return perf.newScreenTrace.call(perf, identifier, MODULAR_DEPRECATION_ARG); -} -/** - * Creates a ScreenTrace instance with the given identifier and immediately starts it. - * Throws if hardware acceleration is disabled or if Android is 9.0 or 9.1. - * @platform android Android !== 9.0.0 && Android !== 9.1.0 - * @param perf - Performance instance - * @param identifier Name of the screen - * @returns {Promise} - */ -export function startScreenTrace(perf, identifier) { - return perf.startScreenTrace.call(perf, identifier, MODULAR_DEPRECATION_ARG); -} diff --git a/packages/perf/lib/index.js b/packages/perf/lib/namespaced.ts similarity index 64% rename from packages/perf/lib/index.js rename to packages/perf/lib/namespaced.ts index 96f9d2e57f..e14770f275 100644 --- a/packages/perf/lib/index.js +++ b/packages/perf/lib/namespaced.ts @@ -20,20 +20,27 @@ import { createModuleNamespace, FirebaseModule, getFirebaseRoot, + type ModuleConfig, } from '@react-native-firebase/app/dist/module/internal'; import { Platform } from 'react-native'; + import HttpMetric from './HttpMetric'; -import Trace from './Trace'; import ScreenTrace from './ScreenTrace'; -import version from './version'; +import Trace from './Trace'; +import { version } from './version'; + +import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import type { FirebasePerformanceTypes } from './types/namespaced'; -const statics = {}; +const statics: FirebasePerformanceTypes.Statics = { + SDK_VERSION: version, +}; const namespace = 'perf'; -const nativeModuleName = 'RNFBPerfModule'; +const nativeModuleName = 'RNFBPerfModule' as const; -const VALID_HTTP_METHODS = [ +const VALID_HTTP_METHODS: FirebasePerformanceTypes.HttpMethod[] = [ 'CONNECT', 'DELETE', 'GET', @@ -45,26 +52,33 @@ const VALID_HTTP_METHODS = [ 'TRACE', ]; -class FirebasePerfModule extends FirebaseModule { - constructor(...args) { - super(...args); +class FirebasePerfModule extends FirebaseModule { + private _isPerformanceCollectionEnabled: boolean; + private _instrumentationEnabled: boolean; + + constructor( + app: ReactNativeFirebase.FirebaseAppBase, + config: ModuleConfig, + customUrlOrRegion?: string | null, + ) { + super(app, config, customUrlOrRegion); this._isPerformanceCollectionEnabled = this.native.isPerformanceCollectionEnabled; this._instrumentationEnabled = this.native.isInstrumentationEnabled; } - get isPerformanceCollectionEnabled() { + get isPerformanceCollectionEnabled(): boolean { return this._isPerformanceCollectionEnabled; } - get instrumentationEnabled() { + get instrumentationEnabled(): boolean { return this._instrumentationEnabled; } - set instrumentationEnabled(enabled) { + set instrumentationEnabled(enabled: boolean) { if (!isBoolean(enabled)) { throw new Error("firebase.perf().instrumentationEnabled = 'enabled' must be a boolean."); } - if (Platform.OS == 'ios') { + if (Platform.OS === 'ios') { // We don't change for android as it cannot be set from code, it is set at gradle build time. this._instrumentationEnabled = enabled; // No need to await, as it only takes effect on the next app run. @@ -72,26 +86,27 @@ class FirebasePerfModule extends FirebaseModule { } } - get dataCollectionEnabled() { + get dataCollectionEnabled(): boolean { return this._isPerformanceCollectionEnabled; } - set dataCollectionEnabled(enabled) { + set dataCollectionEnabled(enabled: boolean) { if (!isBoolean(enabled)) { throw new Error("firebase.perf().dataCollectionEnabled = 'enabled' must be a boolean."); } this._isPerformanceCollectionEnabled = enabled; - this.native.setPerformanceCollectionEnabled(enabled); + // Keep setter behavior fire-and-forget; callers that need completion should use setPerformanceCollectionEnabled(). + void this.native.setPerformanceCollectionEnabled(enabled); } - async setPerformanceCollectionEnabled(enabled) { + async setPerformanceCollectionEnabled(enabled: boolean): Promise { if (!isBoolean(enabled)) { throw new Error( "firebase.perf().setPerformanceCollectionEnabled(*) 'enabled' must be a boolean.", ); } - if (Platform.OS == 'ios') { + if (Platform.OS === 'ios') { // '_instrumentationEnabled' is updated here as well to maintain backward compatibility. See: // https://github.com/invertase/react-native-firebase/commit/b705622e64d6ebf4ee026d50841e2404cf692f85 this._instrumentationEnabled = enabled; @@ -102,7 +117,7 @@ class FirebasePerfModule extends FirebaseModule { return this.native.setPerformanceCollectionEnabled(enabled); } - newTrace(identifier) { + newTrace(identifier: string): Trace { // TODO(VALIDATION): identifier: no leading or trailing whitespace, no leading underscore '_' if (!isString(identifier) || identifier.length > 100) { throw new Error( @@ -113,12 +128,12 @@ class FirebasePerfModule extends FirebaseModule { return new Trace(this.native, identifier); } - startTrace(identifier) { - const trace = this.newTrace(identifier); - return trace.start().then(() => trace); + startTrace(identifier: string): Promise { + const traceInstance = this.newTrace(identifier); + return traceInstance.start().then(() => traceInstance); } - newScreenTrace(identifier) { + newScreenTrace(identifier: string): ScreenTrace { if (!isString(identifier) || identifier.length > 100) { throw new Error( "firebase.perf().newScreenTrace(*) 'identifier' must be a string with a maximum length of 100 characters.", @@ -128,17 +143,17 @@ class FirebasePerfModule extends FirebaseModule { return new ScreenTrace(this.native, identifier); } - startScreenTrace(identifier) { + startScreenTrace(identifier: string): Promise { const screenTrace = this.newScreenTrace(identifier); return screenTrace.start().then(() => screenTrace); } - newHttpMetric(url, httpMethod) { + newHttpMetric(url: string, httpMethod: FirebasePerformanceTypes.HttpMethod): HttpMetric { if (!isString(url)) { throw new Error("firebase.perf().newHttpMetric(*, _) 'url' must be a string."); } - if (!isString(url) || !isOneOf(httpMethod, VALID_HTTP_METHODS)) { + if (!isOneOf(httpMethod, VALID_HTTP_METHODS)) { throw new Error( `firebase.perf().newHttpMetric(_, *) 'httpMethod' must be one of ${VALID_HTTP_METHODS.join( ', ', @@ -153,9 +168,15 @@ class FirebasePerfModule extends FirebaseModule { // import { SDK_VERSION } from '@react-native-firebase/perf'; export const SDK_VERSION = version; -// import perf from '@react-native-firebase/perf'; -// perf().X(...); -export default createModuleNamespace({ +export type PerfNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebasePerformanceTypes.Module, + FirebasePerformanceTypes.Statics +> & { + firebase: ReactNativeFirebase.Module; + app(name?: string): ReactNativeFirebase.FirebaseApp; +}; + +const defaultExport = createModuleNamespace({ statics, version, namespace, @@ -164,11 +185,16 @@ export default createModuleNamespace({ hasMultiAppSupport: false, hasCustomUrlOrRegionSupport: false, ModuleClass: FirebasePerfModule, -}); +}) as unknown as PerfNamespace; -export * from './modular'; +export default defaultExport; // import perf, { firebase } from '@react-native-firebase/perf'; // perf().X(...); // firebase.perf().X(...); -export const firebase = getFirebaseRoot(); +export const firebase = + getFirebaseRoot() as unknown as ReactNativeFirebase.FirebaseNamespacedExport< + 'perf', + FirebasePerformanceTypes.Module, + FirebasePerformanceTypes.Statics + >; diff --git a/packages/perf/lib/types/internal.ts b/packages/perf/lib/types/internal.ts new file mode 100644 index 0000000000..52bc86f14b --- /dev/null +++ b/packages/perf/lib/types/internal.ts @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import type { + FirebasePerformance, + HttpMetric, + HttpMethod, + PerformanceTrace, + ScreenTrace, +} from './perf'; + +export type PerfModularDeprecationArg = string; + +/** + * Namespaced perf instance used by modular entrypoints; methods accept an optional modular deprecation token. + */ +export interface PerfInternal extends FirebasePerformance { + /** + * @deprecated Prefer assigning {@link FirebasePerformance.dataCollectionEnabled}. + */ + setPerformanceCollectionEnabled(enabled: boolean): Promise; + newTrace(name: string, deprecationArg?: PerfModularDeprecationArg): PerformanceTrace; + startTrace(name: string, deprecationArg?: PerfModularDeprecationArg): Promise; + newScreenTrace(screenName: string, deprecationArg?: PerfModularDeprecationArg): ScreenTrace; + startScreenTrace( + screenName: string, + deprecationArg?: PerfModularDeprecationArg, + ): Promise; + newHttpMetric( + url: string, + httpMethod: HttpMethod, + deprecationArg?: PerfModularDeprecationArg, + ): HttpMetric; +} + +export interface RNFBPerfTraceData { + metrics: Record; + attributes: Record; +} + +export interface RNFBPerfHttpMetricData { + attributes: Record; + httpResponseCode?: number; + requestPayloadSize?: number; + responsePayloadSize?: number; + responseContentType?: string; +} + +export interface RNFBPerfNativeModule { + isPerformanceCollectionEnabled: boolean; + isInstrumentationEnabled: boolean; + setPerformanceCollectionEnabled(enabled: boolean): Promise; + instrumentationEnabled(enabled: boolean): Promise; + startTrace(id: number, identifier: string): Promise; + stopTrace(id: number, traceData: RNFBPerfTraceData): Promise; + startHttpMetric(id: number, url: string, httpMethod: HttpMethod): Promise; + stopHttpMetric(id: number, metricData: RNFBPerfHttpMetricData): Promise; + startScreenTrace(id: number, identifier: string): Promise; + stopScreenTrace(id: number): Promise; +} + +declare module '@react-native-firebase/app/dist/module/internal/NativeModules' { + interface ReactNativeFirebaseNativeModules { + RNFBPerfModule: RNFBPerfNativeModule; + } +} diff --git a/packages/perf/lib/types/namespaced.ts b/packages/perf/lib/types/namespaced.ts new file mode 100644 index 0000000000..bea342e5a6 --- /dev/null +++ b/packages/perf/lib/types/namespaced.ts @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import type { ReactNativeFirebase } from '@react-native-firebase/app'; + +/** + * Firebase Performance Monitoring package for React Native. + * + * #### Example 1 + * + * Access the firebase export from the `perf` package: + * + * ```js + * import { firebase } from '@react-native-firebase/perf'; + * + * // firebase.perf().X + * ``` + * + * #### Example 2 + * + * Using the default export from the `perf` package: + * + * ```js + * import perf from '@react-native-firebase/perf'; + * + * // perf().X + * ``` + * + * #### Example 3 + * + * Using the default export from the `app` package: + * + * ```js + * import firebase from '@react-native-firebase/app'; + * import '@react-native-firebase/perf'; + * + * // firebase.perf().X + * ``` + * + * @firebase perf + */ +/** + * @deprecated Use the modular type exports from `@react-native-firebase/perf` instead. + * `FirebasePerformanceTypes` is kept for backwards compatibility with the namespaced API. + */ +/* eslint-disable @typescript-eslint/no-namespace */ +export namespace FirebasePerformanceTypes { + type FirebaseModule = ReactNativeFirebase.FirebaseModule; + + /** + * @deprecated Use the `HttpMethod` type from the modular package exports instead. + */ + export type HttpMethod = + | 'GET' + | 'HEAD' + | 'PUT' + | 'POST' + | 'PATCH' + | 'TRACE' + | 'DELETE' + | 'CONNECT' + | 'OPTIONS'; + + /** + * @deprecated Use the `PerformanceTrace` type from the modular package exports instead. + */ + export interface Trace { + getAttribute(attribute: string): string | undefined; + putAttribute(attribute: string, value: string): void; + getMetric(metricName: string): number; + getMetrics(): { [key: string]: number }; + putMetric(metricName: string, value: number): void; + incrementMetric(metricName: string, incrementBy?: number): void; + removeMetric(metricName: string): void; + start(): Promise; + stop(): Promise; + } + + /** + * @deprecated Use the `ScreenTrace` type from the modular package exports instead. + */ + export interface ScreenTrace { + start(): Promise; + stop(): Promise; + } + + /** + * @deprecated Use the `HttpMetric` type from the modular package exports instead. + */ + export interface HttpMetric { + getAttribute(attribute: string): string | undefined; + getAttributes(): { [key: string]: string }; + putAttribute(attribute: string, value: string): void; + removeAttribute(attribute: string): void; + setHttpResponseCode(code: number | null): void; + setRequestPayloadSize(bytes: number | null): void; + setResponsePayloadSize(bytes: number | null): void; + setResponseContentType(contentType: string | null): void; + start(): Promise; + stop(): Promise; + } + + /** + * @deprecated Use static exports from the package root instead. + */ + export interface Statics { + SDK_VERSION: string; + } + + /** + * @deprecated Use the `FirebasePerformance` type from the modular package exports instead. + */ + export interface Module extends FirebaseModule { + app: ReactNativeFirebase.FirebaseApp; + isPerformanceCollectionEnabled: boolean; + instrumentationEnabled: boolean; + dataCollectionEnabled: boolean; + /** + * @deprecated prefer setting `dataCollectionEnabled = boolean`. + */ + setPerformanceCollectionEnabled(enabled: boolean): Promise; + newTrace(identifier: string): Trace; + startTrace(identifier: string): Promise; + newScreenTrace(identifier: string): ScreenTrace; + startScreenTrace(identifier: string): Promise; + newHttpMetric(url: string, httpMethod: HttpMethod): HttpMetric; + } +} +/* eslint-enable @typescript-eslint/no-namespace */ + +/** + * Attach namespace to `firebase.` and `FirebaseApp.`. + */ +declare module '@react-native-firebase/app' { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace ReactNativeFirebase { + import FirebaseModuleWithStatics = ReactNativeFirebase.FirebaseModuleWithStatics; + interface Module { + perf: FirebaseModuleWithStatics< + FirebasePerformanceTypes.Module, + FirebasePerformanceTypes.Statics + >; + } + interface FirebaseApp { + perf(): FirebasePerformanceTypes.Module; + } + } +} diff --git a/packages/perf/lib/types/perf.ts b/packages/perf/lib/types/perf.ts new file mode 100644 index 0000000000..247132ab43 --- /dev/null +++ b/packages/perf/lib/types/perf.ts @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import type { FirebaseApp } from '@react-native-firebase/app'; + +/** + * Configuration options for Performance Monitoring (aligned with {@link https://firebase.google.com/docs/reference/js/performance.performancesettings | PerformanceSettings} in the Firebase JS SDK). + */ +export interface PerformanceSettings { + /** Whether to collect custom events. */ + dataCollectionEnabled?: boolean; + /** Whether to collect out-of-the-box events. */ + instrumentationEnabled?: boolean; +} + +/** + * Valid HTTP methods for HTTP metrics. + */ +export type HttpMethod = + | 'GET' + | 'HEAD' + | 'PUT' + | 'POST' + | 'PATCH' + | 'TRACE' + | 'DELETE' + | 'CONNECT' + | 'OPTIONS'; + +/** + * A performance trace (aligned with {@link https://firebase.google.com/docs/reference/js/performance.performancetrace | PerformanceTrace} in the Firebase JS SDK). + * + * @remarks React Native uses async `start`/`stop` (native bridge). The web SDK uses synchronous `start`/`stop`. React Native also exposes `getMetrics` and `removeMetric`, which are not on the web `PerformanceTrace` type. + */ +export interface PerformanceTrace { + getAttribute(attr: string): string | undefined; + putAttribute(attr: string, value: string): void; + getMetric(metricName: string): number; + getMetrics(): { [key: string]: number }; + putMetric(metricName: string, num: number): void; + incrementMetric(metricName: string, num?: number): void; + removeMetric(metricName: string): void; + start(): Promise; + stop(): Promise; +} + +/** + * Screen trace for slow/frozen frames (React Native). + */ +export interface ScreenTrace { + start(): Promise; + stop(): Promise; +} + +/** + * Network request metric (React Native; not part of the web Performance modular surface). + */ +export interface HttpMetric { + getAttribute(attr: string): string | undefined; + getAttributes(): { [key: string]: string }; + putAttribute(attr: string, value: string): void; + removeAttribute(attr: string): void; + setHttpResponseCode(code: number | null): void; + setRequestPayloadSize(bytes: number | null): void; + setResponsePayloadSize(bytes: number | null): void; + setResponseContentType(contentType: string | null): void; + start(): Promise; + stop(): Promise; +} + +/** + * Firebase Performance Monitoring service (aligned with {@link https://firebase.google.com/docs/reference/js/performance.firebaseperformance | FirebasePerformance} in the Firebase JS SDK). + * + * @remarks React Native adds collection/read APIs backed by native (`isPerformanceCollectionEnabled`, custom traces, HTTP metrics, screen traces). + */ +export interface FirebasePerformance { + /** The FirebaseApp this Performance instance is associated with. */ + app: FirebaseApp; + /** Controls logging of automatic traces and HTTP/S network monitoring. */ + instrumentationEnabled: boolean; + /** Controls logging of custom traces. */ + dataCollectionEnabled: boolean; + /** Whether performance data collection is enabled for this app instance (native). */ + isPerformanceCollectionEnabled: boolean; +} diff --git a/packages/perf/package.json b/packages/perf/package.json index ae2506734c..affe491822 100644 --- a/packages/perf/package.json +++ b/packages/perf/package.json @@ -3,14 +3,15 @@ "version": "24.0.0", "author": "Invertase (http://invertase.io)", "description": "React Native Firebase - React Native Firebase provides native integration with Performance Monitoring to gain insight into key performance characteristics within your React Native application.", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "./dist/module/index.js", + "types": "./dist/typescript/lib/index.d.ts", "scripts": { - "build": "genversion --semi lib/version.js", + "build": "genversion --esm --semi lib/version.ts", "build:clean": "rimraf android/build && rimraf ios/build", "build:plugin": "rimraf plugin/build && tsc --build plugin", + "compile": "bob build", "lint:plugin": "eslint plugin/src/*", - "prepare": "yarn run build && yarn run build:plugin" + "prepare": "yarn run build && yarn compile && yarn run build:plugin" }, "repository": { "type": "git", @@ -33,7 +34,8 @@ "expo": ">=47.0.0" }, "devDependencies": { - "expo": "^55.0.18" + "expo": "^55.0.18", + "react-native-builder-bob": "^0.40.13" }, "peerDependenciesMeta": { "expo": { @@ -43,5 +45,35 @@ "publishConfig": { "access": "public", "provenance": true - } + }, + "exports": { + ".": { + "source": "./lib/index.ts", + "types": "./dist/typescript/lib/index.d.ts", + "default": "./dist/module/index.js" + }, + "./package.json": "./package.json" + }, + "react-native-builder-bob": { + "source": "lib", + "output": "dist", + "targets": [ + [ + "module", + { + "esm": true + } + ], + [ + "typescript", + { + "tsc": "../../node_modules/.bin/tsc" + } + ] + ] + }, + "eslintIgnore": [ + "node_modules/", + "dist/" + ] } diff --git a/packages/perf/tsconfig.json b/packages/perf/tsconfig.json new file mode 100644 index 0000000000..4e2b0c4906 --- /dev/null +++ b/packages/perf/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.packages.base.json", + "compilerOptions": { + "rootDir": ".", + "paths": { + "@react-native-firebase/app/dist/module/common/*": ["../app/dist/typescript/lib/common/*"], + "@react-native-firebase/app/dist/module/common": ["../app/dist/typescript/lib/common"], + "@react-native-firebase/app/dist/module/internal/*": [ + "../app/dist/typescript/lib/internal/*" + ], + "@react-native-firebase/app/dist/module/internal": ["../app/dist/typescript/lib/internal"], + "@react-native-firebase/app": ["../app/dist/typescript/lib"], + "@react-native-firebase/app/dist/module/types/internal": [ + "../app/dist/typescript/lib/types/internal" + ] + } + }, + "include": ["lib/**/*"], + "exclude": ["node_modules", "dist", "__tests__", "**/*.test.ts"] +} diff --git a/packages/perf/type-test.ts b/packages/perf/type-test.ts index 6e552c0361..38d3f556f3 100644 --- a/packages/perf/type-test.ts +++ b/packages/perf/type-test.ts @@ -111,9 +111,8 @@ console.log(modularPerf1.app.name); const modularPerf2 = getPerformance(firebase.app()); console.log(modularPerf2.app.name); -initializePerformance(firebase.app(), { dataCollectionEnabled: true }).then(initializedPerf => { - console.log(initializedPerf.app.name); -}); +const initializedPerf = initializePerformance(firebase.app(), { dataCollectionEnabled: true }); +console.log(initializedPerf.app.name); const modularTrace = trace(modularPerf1, 'modular-trace'); modularTrace.putAttribute('modular-key', 'modular-value'); diff --git a/packages/perf/typedoc.json b/packages/perf/typedoc.json index ce7104d0e0..55ee480416 100644 --- a/packages/perf/typedoc.json +++ b/packages/perf/typedoc.json @@ -1,5 +1,5 @@ { "$schema": "https://typedoc.org/schema.json", - "entryPoints": ["lib/index.d.ts"], - "intentionallyNotExported": ["PerfNamespace"] + "entryPoints": ["lib/modular.ts", "lib/types/perf.ts"], + "tsconfig": "tsconfig.json" } diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index dc06c43808..de81b0b5dc 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -250,7 +250,7 @@ PODS: - GoogleUtilities/UserDefaults (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - GTMSessionFetcher/Core (5.2.0) + - GTMSessionFetcher/Core (5.3.0) - hermes-engine (0.78.3): - hermes-engine/Pre-built (= 0.78.3) - hermes-engine/Pre-built (0.78.3) @@ -2533,7 +2533,7 @@ SPEC CHECKSUMS: GoogleAppMeasurement: 3b4687de50ab25ee2d4d541849f10ca8df862a12 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 - GTMSessionFetcher: 904bdd2a82c635bcd6f44edf94cc8775c5d1d6e6 + GTMSessionFetcher: 127211aeec0b1e904fc49f4f6f895dcc535b0ecf hermes-engine: b5c9cfbe6415f1b0b24759f2942c8f33e9af6347 leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 diff --git a/tsconfig.json b/tsconfig.json index a922dda15e..45891f2d0f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,8 +21,6 @@ "packages/installations/lib/modular/index.d.ts", "packages/ml/lib/index.d.ts", "packages/ml/lib/modular/index.d.ts", - "packages/perf/lib/index.d.ts", - "packages/perf/lib/modular/index.d.ts", "packages/functions/type-test.ts", "packages/app/type-test.ts", "packages/app-check/type-test.ts", @@ -69,7 +67,7 @@ ], "@react-native-firebase/firestore/pipelines": [ "./packages/firestore/dist/typescript/lib/pipelines/index.d.ts" - ], + ] } }, "exclude": ["node_modules", "**/*.spec.ts", "packages/**/dist"] diff --git a/yarn.lock b/yarn.lock index 4832e300ed..425ee1acc5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1233,7 +1233,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-flow-strip-types@npm:^7.25.2, @babel/plugin-transform-flow-strip-types@npm:^7.27.1": +"@babel/plugin-transform-flow-strip-types@npm:^7.25.2, @babel/plugin-transform-flow-strip-types@npm:^7.26.5, @babel/plugin-transform-flow-strip-types@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-flow-strip-types@npm:7.27.1" dependencies: @@ -1375,6 +1375,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-systemjs@npm:^7.29.4": + version: 7.29.4 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.4" + dependencies: + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.29.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/79269e6ec8ec831bb63bf1c7cc1a980e28da785e92b36d42612f0139e4044499b99aa109fca849e1a156c092aabf6c24d145f4cabf2ac9ea84ef468852fe4c03 + languageName: node + linkType: hard + "@babel/plugin-transform-modules-umd@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-modules-umd@npm:7.27.1" @@ -1804,7 +1818,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-strict-mode@npm:^7.27.1": +"@babel/plugin-transform-strict-mode@npm:^7.24.7, @babel/plugin-transform-strict-mode@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-strict-mode@npm:7.27.1" dependencies: @@ -1899,6 +1913,87 @@ __metadata: languageName: node linkType: hard +"@babel/preset-env@npm:^7.25.2": + version: 7.29.5 + resolution: "@babel/preset-env@npm:7.29.5" + dependencies: + "@babel/compat-data": "npm:^7.29.3" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.28.5" + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.27.1" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.27.1" + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "npm:^7.29.3" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.27.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.28.6" + "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions": "npm:^7.28.6" + "@babel/plugin-syntax-import-attributes": "npm:^7.28.6" + "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" + "@babel/plugin-transform-arrow-functions": "npm:^7.27.1" + "@babel/plugin-transform-async-generator-functions": "npm:^7.29.0" + "@babel/plugin-transform-async-to-generator": "npm:^7.28.6" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.27.1" + "@babel/plugin-transform-block-scoping": "npm:^7.28.6" + "@babel/plugin-transform-class-properties": "npm:^7.28.6" + "@babel/plugin-transform-class-static-block": "npm:^7.28.6" + "@babel/plugin-transform-classes": "npm:^7.28.6" + "@babel/plugin-transform-computed-properties": "npm:^7.28.6" + "@babel/plugin-transform-destructuring": "npm:^7.28.5" + "@babel/plugin-transform-dotall-regex": "npm:^7.28.6" + "@babel/plugin-transform-duplicate-keys": "npm:^7.27.1" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-dynamic-import": "npm:^7.27.1" + "@babel/plugin-transform-explicit-resource-management": "npm:^7.28.6" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.28.6" + "@babel/plugin-transform-export-namespace-from": "npm:^7.27.1" + "@babel/plugin-transform-for-of": "npm:^7.27.1" + "@babel/plugin-transform-function-name": "npm:^7.27.1" + "@babel/plugin-transform-json-strings": "npm:^7.28.6" + "@babel/plugin-transform-literals": "npm:^7.27.1" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.28.6" + "@babel/plugin-transform-member-expression-literals": "npm:^7.27.1" + "@babel/plugin-transform-modules-amd": "npm:^7.27.1" + "@babel/plugin-transform-modules-commonjs": "npm:^7.28.6" + "@babel/plugin-transform-modules-systemjs": "npm:^7.29.4" + "@babel/plugin-transform-modules-umd": "npm:^7.27.1" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-new-target": "npm:^7.27.1" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.28.6" + "@babel/plugin-transform-numeric-separator": "npm:^7.28.6" + "@babel/plugin-transform-object-rest-spread": "npm:^7.28.6" + "@babel/plugin-transform-object-super": "npm:^7.27.1" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.28.6" + "@babel/plugin-transform-optional-chaining": "npm:^7.28.6" + "@babel/plugin-transform-parameters": "npm:^7.27.7" + "@babel/plugin-transform-private-methods": "npm:^7.28.6" + "@babel/plugin-transform-private-property-in-object": "npm:^7.28.6" + "@babel/plugin-transform-property-literals": "npm:^7.27.1" + "@babel/plugin-transform-regenerator": "npm:^7.29.0" + "@babel/plugin-transform-regexp-modifiers": "npm:^7.28.6" + "@babel/plugin-transform-reserved-words": "npm:^7.27.1" + "@babel/plugin-transform-shorthand-properties": "npm:^7.27.1" + "@babel/plugin-transform-spread": "npm:^7.28.6" + "@babel/plugin-transform-sticky-regex": "npm:^7.27.1" + "@babel/plugin-transform-template-literals": "npm:^7.27.1" + "@babel/plugin-transform-typeof-symbol": "npm:^7.27.1" + "@babel/plugin-transform-unicode-escapes": "npm:^7.27.1" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.28.6" + "@babel/plugin-transform-unicode-regex": "npm:^7.27.1" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.28.6" + "@babel/preset-modules": "npm:0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2: "npm:^0.4.15" + babel-plugin-polyfill-corejs3: "npm:^0.14.0" + babel-plugin-polyfill-regenerator: "npm:^0.6.6" + core-js-compat: "npm:^3.48.0" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/2e54630764b6650d81df5ce5a47fa260acd3695dc95a6b989b713bf6c0713fb320e3ae3f76f0c636bfda058ee5c582a3de7f5d58d691c68ca566129c7d3d0f0a + languageName: node + linkType: hard + "@babel/preset-env@npm:^7.29.2, @babel/preset-env@npm:^7.29.3": version: 7.29.3 resolution: "@babel/preset-env@npm:7.29.3" @@ -2006,7 +2101,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-react@npm:^7.22.15, @babel/preset-react@npm:^7.28.5": +"@babel/preset-react@npm:^7.22.15, @babel/preset-react@npm:^7.24.7, @babel/preset-react@npm:^7.28.5": version: 7.28.5 resolution: "@babel/preset-react@npm:7.28.5" dependencies: @@ -6058,6 +6153,7 @@ __metadata: resolution: "@react-native-firebase/perf@workspace:packages/perf" dependencies: expo: "npm:^55.0.18" + react-native-builder-bob: "npm:^0.40.13" peerDependencies: "@react-native-firebase/app": 24.0.0 expo: ">=47.0.0" @@ -8139,7 +8235,7 @@ __metadata: languageName: node linkType: hard -"arktype@npm:^2.2.0": +"arktype@npm:^2.1.15, arktype@npm:^2.2.0": version: 2.2.0 resolution: "arktype@npm:2.2.0" dependencies: @@ -8204,6 +8300,13 @@ __metadata: languageName: node linkType: hard +"array-union@npm:^2.1.0": + version: 2.1.0 + resolution: "array-union@npm:2.1.0" + checksum: 10/5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d + languageName: node + linkType: hard + "array.prototype.findlast@npm:^1.2.5": version: 1.2.5 resolution: "array.prototype.findlast@npm:1.2.5" @@ -8599,7 +8702,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-syntax-hermes-parser@npm:0.28.1": +"babel-plugin-syntax-hermes-parser@npm:0.28.1, babel-plugin-syntax-hermes-parser@npm:^0.28.0": version: 0.28.1 resolution: "babel-plugin-syntax-hermes-parser@npm:0.28.1" dependencies: @@ -9043,6 +9146,21 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.20.4, browserslist@npm:^4.28.1, browserslist@npm:^4.28.2": + version: 4.28.2 + resolution: "browserslist@npm:4.28.2" + dependencies: + baseline-browser-mapping: "npm:^2.10.12" + caniuse-lite: "npm:^1.0.30001782" + electron-to-chromium: "npm:^1.5.328" + node-releases: "npm:^2.0.36" + update-browserslist-db: "npm:^1.2.3" + bin: + browserslist: cli.js + checksum: 10/cff88386e5b5ba5614c9063bd32ef94865bba22b6a381844c7d09ea1eea62a2247e7106e516abdbfda6b75b9986044c991dfe45f92f10add5ad63dccc07589ec + languageName: node + linkType: hard + "browserslist@npm:^4.24.0, browserslist@npm:^4.25.0, browserslist@npm:^4.28.0": version: 4.28.1 resolution: "browserslist@npm:4.28.1" @@ -9058,21 +9176,6 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.28.1, browserslist@npm:^4.28.2": - version: 4.28.2 - resolution: "browserslist@npm:4.28.2" - dependencies: - baseline-browser-mapping: "npm:^2.10.12" - caniuse-lite: "npm:^1.0.30001782" - electron-to-chromium: "npm:^1.5.328" - node-releases: "npm:^2.0.36" - update-browserslist-db: "npm:^1.2.3" - bin: - browserslist: cli.js - checksum: 10/cff88386e5b5ba5614c9063bd32ef94865bba22b6a381844c7d09ea1eea62a2247e7106e516abdbfda6b75b9986044c991dfe45f92f10add5ad63dccc07589ec - languageName: node - linkType: hard - "bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" @@ -10763,6 +10866,13 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^0.7.0": + version: 0.7.0 + resolution: "dedent@npm:0.7.0" + checksum: 10/87de191050d9a40dd70cad01159a0bcf05ecb59750951242070b6abf9569088684880d00ba92a955b4058804f16eeaf91d604f283929b4f614d181cd7ae633d2 + languageName: node + linkType: hard + "dedent@npm:^1.6.0": version: 1.7.0 resolution: "dedent@npm:1.7.0" @@ -10883,6 +10993,22 @@ __metadata: languageName: node linkType: hard +"del@npm:^6.1.1": + version: 6.1.1 + resolution: "del@npm:6.1.1" + dependencies: + globby: "npm:^11.0.1" + graceful-fs: "npm:^4.2.4" + is-glob: "npm:^4.0.1" + is-path-cwd: "npm:^2.2.0" + is-path-inside: "npm:^3.0.2" + p-map: "npm:^4.0.0" + rimraf: "npm:^3.0.2" + slash: "npm:^3.0.0" + checksum: 10/563288b73b8b19a7261c47fd21a330eeab6e2acd7c6208c49790dfd369127120dd7836cdf0c1eca216b77c94782a81507eac6b4734252d3bef2795cb366996b6 + languageName: node + linkType: hard + "del@npm:^8.0.1": version: 8.0.1 resolution: "del@npm:8.0.1" @@ -11123,6 +11249,15 @@ __metadata: languageName: node linkType: hard +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: "npm:^4.0.0" + checksum: 10/fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 + languageName: node + linkType: hard + "discontinuous-range@npm:1.0.0": version: 1.0.0 resolution: "discontinuous-range@npm:1.0.0" @@ -12416,29 +12551,29 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.3.2": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" +"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.3": + version: 3.3.3 + resolution: "fast-glob@npm:3.3.3" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df + micromatch: "npm:^4.0.8" + checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad languageName: node linkType: hard -"fast-glob@npm:^3.3.3": - version: 3.3.3 - resolution: "fast-glob@npm:3.3.3" +"fast-glob@npm:^3.3.2": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.8" - checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad + micromatch: "npm:^4.0.4" + checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -13650,6 +13785,20 @@ __metadata: languageName: node linkType: hard +"globby@npm:^11.0.1": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: "npm:^2.1.0" + dir-glob: "npm:^3.0.1" + fast-glob: "npm:^3.2.9" + ignore: "npm:^5.2.0" + merge2: "npm:^1.4.1" + slash: "npm:^3.0.0" + checksum: 10/288e95e310227bbe037076ea81b7c2598ccbc3122d87abc6dab39e1eec309aa14f0e366a98cdc45237ffcfcbad3db597778c0068217dcb1950fef6249104e1b1 + languageName: node + linkType: hard + "globby@npm:^14.0.2": version: 14.1.0 resolution: "globby@npm:14.1.0" @@ -14948,7 +15097,7 @@ __metadata: languageName: node linkType: hard -"is-git-dirty@npm:^2.0.2": +"is-git-dirty@npm:^2.0.1, is-git-dirty@npm:^2.0.2": version: 2.0.2 resolution: "is-git-dirty@npm:2.0.2" dependencies: @@ -15056,6 +15205,13 @@ __metadata: languageName: node linkType: hard +"is-path-cwd@npm:^2.2.0": + version: 2.2.0 + resolution: "is-path-cwd@npm:2.2.0" + checksum: 10/46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048 + languageName: node + linkType: hard + "is-path-cwd@npm:^3.0.0": version: 3.0.0 resolution: "is-path-cwd@npm:3.0.0" @@ -16433,7 +16589,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.2.2, json5@npm:^2.2.3": +"json5@npm:^2.2.1, json5@npm:^2.2.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -16617,7 +16773,7 @@ __metadata: languageName: node linkType: hard -"kleur@npm:^4.1.5": +"kleur@npm:^4.1.4, kleur@npm:^4.1.5": version: 4.1.5 resolution: "kleur@npm:4.1.5" checksum: 10/44d84cc4eedd4311099402ef6d4acd9b2d16e08e499d6ef3bb92389bd4692d7ef09e35248c26e27f98acac532122acb12a1bfee645994ae3af4f0a37996da7df @@ -17726,7 +17882,7 @@ __metadata: languageName: node linkType: hard -"merge2@npm:^1.3.0": +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" checksum: 10/7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 @@ -20673,7 +20829,7 @@ __metadata: languageName: node linkType: hard -"p-map@npm:4.0.0": +"p-map@npm:4.0.0, p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" dependencies: @@ -21161,6 +21317,13 @@ __metadata: languageName: node linkType: hard +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 10/5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 + languageName: node + linkType: hard + "path-type@npm:^6.0.0": version: 6.0.0 resolution: "path-type@npm:6.0.0" @@ -21976,6 +22139,38 @@ __metadata: languageName: node linkType: hard +"react-native-builder-bob@npm:^0.40.13": + version: 0.40.18 + resolution: "react-native-builder-bob@npm:0.40.18" + dependencies: + "@babel/core": "npm:^7.25.2" + "@babel/plugin-transform-flow-strip-types": "npm:^7.26.5" + "@babel/plugin-transform-strict-mode": "npm:^7.24.7" + "@babel/preset-env": "npm:^7.25.2" + "@babel/preset-react": "npm:^7.24.7" + "@babel/preset-typescript": "npm:^7.24.7" + arktype: "npm:^2.1.15" + babel-plugin-syntax-hermes-parser: "npm:^0.28.0" + browserslist: "npm:^4.20.4" + cross-spawn: "npm:^7.0.3" + dedent: "npm:^0.7.0" + del: "npm:^6.1.1" + escape-string-regexp: "npm:^4.0.0" + fs-extra: "npm:^10.1.0" + glob: "npm:^10.5.0" + is-git-dirty: "npm:^2.0.1" + json5: "npm:^2.2.1" + kleur: "npm:^4.1.4" + prompts: "npm:^2.4.2" + react-native-monorepo-config: "npm:^0.3.3" + which: "npm:^2.0.2" + yargs: "npm:^17.5.1" + bin: + bob: bin/bob + checksum: 10/06eddba046a508dff0aa322c823fa57a280e2ed6a6f586de2114ebc11b6bb7863714eaaff8e93d681bb851fb4f9e792b102541211847f0e546f4e9546df6c3de + languageName: node + linkType: hard + "react-native-builder-bob@npm:^0.41.0": version: 0.41.0 resolution: "react-native-builder-bob@npm:0.41.0" @@ -26230,7 +26425,7 @@ __metadata: languageName: node linkType: hard -"which@npm:^2.0.1": +"which@npm:^2.0.1, which@npm:^2.0.2": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -26637,7 +26832,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.6.2, yargs@npm:^17.7.2": +"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.5.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: