Skip to content

Commit f834a96

Browse files
committed
Refactor to use React component function
1 parent 6dace8a commit f834a96

File tree

10 files changed

+132
-103
lines changed

10 files changed

+132
-103
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## API Report File for "@firebase/telemetry-react"
2+
3+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4+
5+
```ts
6+
7+
import { FirebaseOptions } from '@firebase/app';
8+
9+
// @public
10+
export function FirebaseTelemetry({ firebaseOptions }: {
11+
firebaseOptions?: FirebaseOptions;
12+
}): null;
13+
14+
15+
// (No @packageDocumentation comment for this package)
16+
17+
```

common/api-review/telemetry.api.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { AnyValueMap } from '@opentelemetry/api-logs';
88
import { FirebaseApp } from '@firebase/app';
9+
import { Instrumentation } from 'next';
910
import { LoggerProvider } from '@opentelemetry/sdk-logs';
1011

1112
// @public
@@ -17,13 +18,7 @@ export function flush(telemetry: Telemetry): Promise<void>;
1718
// @public
1819
export function getTelemetry(app?: FirebaseApp): Telemetry;
1920

20-
// @public (undocumented)
21-
export namespace Instrumentation {
22-
// Warning: (ae-forgotten-export) The symbol "InstrumentationOnRequestError" needs to be exported by the entry point index.d.ts
23-
//
24-
// (undocumented)
25-
export type onRequestError = InstrumentationOnRequestError;
26-
}
21+
export { Instrumentation }
2722

2823
// @public
2924
export const nextOnRequestError: Instrumentation.onRequestError;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Project: /docs/reference/js/_project.yaml
2+
Book: /docs/reference/_book.yaml
3+
page_type: reference
4+
5+
{% comment %}
6+
DO NOT EDIT THIS FILE!
7+
This is generated by the JS SDK team, and any local changes will be
8+
overwritten. Changes should be made in the source code at
9+
https://github.com/firebase/firebase-js-sdk
10+
{% endcomment %}
11+
12+
# Instrumentation namespace
13+
<b>Signature:</b>
14+
15+
```typescript
16+
export declare namespace Instrumentation
17+
```
18+
19+
## Type Aliases
20+
21+
| Type Alias | Description |
22+
| --- | --- |
23+
| [onRequestError](./telemetry.instrumentation.md#instrumentationonrequesterror) | |
24+
25+
## Instrumentation.onRequestError
26+
27+
<b>Signature:</b>
28+
29+
```typescript
30+
type onRequestError = InstrumentationOnRequestError;
31+
```

docs-devsite/telemetry.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ https://github.com/firebase/firebase-js-sdk
2727
| --- | --- |
2828
| [Telemetry](./telemetry.telemetry.md#telemetry_interface) | An instance of the Firebase Telemetry SDK.<!-- -->Do not create this instance directly. Instead, use [getTelemetry()](./telemetry.md#gettelemetry_cf608e1)<!-- -->. |
2929

30+
## Namespaces
31+
32+
| Namespace | Description |
33+
| --- | --- |
34+
| [Instrumentation](./telemetry.instrumentation.md#instrumentation_namespace) | |
35+
3036
## Variables
3137

3238
| Variable | Description |

packages/telemetry/api-extractor.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,11 @@
77
"untrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>.d.ts",
88
"betaTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-public.d.ts"
99
},
10+
// "additionalEntryPoints": [
11+
// {
12+
// "modulePath": "react",
13+
// "filePath": "<projectFolder>/dist/react/index.d.ts"
14+
// }
15+
// ],
1016
"bundledPackages": ["next"]
1117
}

packages/telemetry/api-extractor.react.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
"dtsRollup": {
55
"enabled": true,
66
"untrimmedFilePath": "<projectFolder>/dist/react/index.d.ts"
7-
},
8-
"apiReport": {
9-
"enabled": false
10-
},
11-
"docModel": {
12-
"enabled": false
13-
},
14-
"tsdocMetadata": {
15-
"enabled": false
16-
}
7+
}//,
8+
// "apiReport": {
9+
// "enabled": false
10+
// },
11+
// "docModel": {
12+
// "enabled": false
13+
// },
14+
// "tsdocMetadata": {
15+
// "enabled": false
16+
// }
1717
}

packages/telemetry/package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
"./react": {
2323
"types": "./dist/react/index.d.ts",
2424
"node": {
25-
"import": "./dist/react/index.node.esm.js",
26-
"default": "./dist/react/index.node.cjs.js"
25+
"import": "./dist/react/index.esm.js",
26+
"default": "./dist/react/index.cjs.js"
2727
},
2828
"browser": {
2929
"require": "./dist/react/index.cjs.js",
@@ -48,9 +48,11 @@
4848
"test:browser": "karma start",
4949
"test:node": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha **/*.test.ts src/**/*.test.ts --config ../../config/mocharc.node.js",
5050
"trusted-type-check": "tsec -p tsconfig.json --noEmit",
51-
"api-report": "yarn api-report:main && yarn api-report:react",
52-
"api-report:main": "api-extractor run --local --verbose",
53-
"api-report:react": "api-extractor run --config api-extractor.react.json --local --verbose",
51+
"api-report": "yarn api-report:react && yarn api-report:main",
52+
"api-report:main": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package telemetry --packageRoot . --typescriptDts ./dist/index.d.ts --rollupDts ./dist/index.d.ts --untrimmedRollupDts ./dist/index.d.ts --publicDts ./dist/index.d.ts",
53+
"api-report:main1": "api-extractor run --local --verbose",
54+
"api-report:react": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package telemetry-react --packageRoot . --typescriptDts ./dist/src/react/index.d.ts --rollupDts ./dist/src/react/index.d.ts --untrimmedRollupDts ./dist/src/react/index.d.ts --publicDts ./dist/src/react/index.d.ts",
55+
"api-report:react1": "api-extractor run --config api-extractor.react.json --local --verbose",
5456
"typings:public": "node ../../scripts/build/use_typings.js ./dist/telemetry-public.d.ts"
5557
},
5658
"peerDependencies": {

packages/telemetry/rollup.config.js

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -110,47 +110,8 @@ const reactBuilds = [
110110
}
111111
];
112112

113-
const reactNodeBuilds = [
114-
{
115-
input: 'src/react/index.ts',
116-
output: {
117-
file: pkg.exports['./react'].node.default,
118-
format: 'cjs',
119-
sourcemap: true,
120-
banner: `'use client';`
121-
},
122-
plugins: [
123-
typescriptPlugin({
124-
typescript,
125-
tsconfig: 'tsconfig.react.json'
126-
}),
127-
json()
128-
],
129-
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
130-
},
131-
{
132-
input: 'src/react/index.ts',
133-
output: {
134-
file: pkg.exports['./react'].node.import,
135-
format: 'es',
136-
sourcemap: true,
137-
banner: `'use client';`
138-
},
139-
plugins: [
140-
typescriptPlugin({
141-
typescript,
142-
tsconfig: 'tsconfig.react.json'
143-
}),
144-
json(),
145-
emitModulePackageFile()
146-
],
147-
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
148-
}
149-
];
150-
151113
export default [
152114
...browserBuilds,
153115
...nodeBuilds,
154-
...reactBuilds,
155-
...reactNodeBuilds
116+
...reactBuilds
156117
];

packages/telemetry/src/react/index.test.tsx

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ import { render } from '@testing-library/react';
3030
use(sinonChai);
3131
use(chaiAsPromised);
3232

33-
describe('FirebaseTelemetry', () => {
33+
describe.only('FirebaseTelemetry', () => {
3434
let getTelemetryStub: sinon.SinonStub;
3535
let captureErrorStub: sinon.SinonStub;
3636
let initializeAppStub: sinon.SinonStub;
37+
let getAppStub: sinon.SinonStub;
3738
let fakeApp: FirebaseApp;
3839
let fakeTelemetry: Telemetry;
3940

@@ -44,6 +45,7 @@ describe('FirebaseTelemetry', () => {
4445
initializeAppStub = stub(app, 'initializeApp').returns(fakeApp);
4546
getTelemetryStub = stub(telemetry, 'getTelemetry').returns(fakeTelemetry);
4647
captureErrorStub = stub(telemetry, 'captureError');
48+
getAppStub = stub(app, 'getApp').returns(fakeApp);
4749
});
4850

4951
afterEach(() => {
@@ -52,15 +54,13 @@ describe('FirebaseTelemetry', () => {
5254

5355
it('gets telemetry with the default app if no firebaseOptions are provided', () => {
5456
render(<FirebaseTelemetry />);
55-
expect(getTelemetryStub).to.have.been.called;
5657
expect(initializeAppStub).not.to.have.been.called;
5758
});
5859

5960
it('initializes a new app and gets telemetry if firebaseOptions are provided', () => {
6061
const firebaseOptions = { apiKey: 'test' };
6162
render(<FirebaseTelemetry firebaseOptions={firebaseOptions} />);
6263
expect(initializeAppStub).to.have.been.calledWith(firebaseOptions);
63-
expect(getTelemetryStub).to.have.been.calledWith(fakeApp);
6464
});
6565

6666
it('captures window errors', done => {
@@ -71,6 +71,7 @@ describe('FirebaseTelemetry', () => {
7171
};
7272
window.addEventListener('error', (event: ErrorEvent) => {
7373
// Registers another listener (sequential) to confirm behaviour.
74+
expect(getTelemetryStub).to.have.been.called;
7475
expect(captureErrorStub).to.have.been.calledWith(fakeTelemetry, error);
7576
done();
7677
});
@@ -85,24 +86,16 @@ describe('FirebaseTelemetry', () => {
8586
window.dispatchEvent(
8687
new PromiseRejectionEvent('unhandledrejection', { reason, promise })
8788
);
89+
expect(getTelemetryStub).to.have.been.called;
8890
expect(captureErrorStub).to.have.been.calledWith(fakeTelemetry, reason);
8991
});
9092

91-
it('renders children', () => {
92-
const { getByText } = render(
93-
<FirebaseTelemetry>
94-
<span>here are my children</span>
95-
</FirebaseTelemetry>
96-
);
97-
expect(getByText('here are my children')).to.exist;
98-
});
99-
10093
it('fails silently when getTelemetry fails', () => {
10194
const error = new Error('getTelemetry failed');
102-
getTelemetryStub.throws(error);
95+
initializeAppStub.throws(error);
10396
const consoleWarnStub = stub(console, 'warn');
10497

105-
expect(() => render(<FirebaseTelemetry />)).not.to.throw();
98+
expect(() => render(<FirebaseTelemetry firebaseOptions={{}}/>)).not.to.throw();
10699
expect(consoleWarnStub).to.have.been.calledWith(
107100
'Firebase Telemetry was not initialized:\n',
108101
error

packages/telemetry/src/react/index.ts

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,43 @@
1818
import { FirebaseOptions, initializeApp } from '@firebase/app';
1919
import { registerTelemetry } from '../register';
2020
import { captureError, getTelemetry } from '../api';
21-
import { Component, ReactNode } from 'react';
21+
import { useEffect } from 'react';
2222

2323
registerTelemetry();
2424

25-
export interface FirebaseTelemetryProps {
26-
firebaseOptions?: FirebaseOptions;
27-
children?: ReactNode;
25+
function errorListener(event: ErrorEvent): void {
26+
captureError(getTelemetry(), event.error, {});
2827
}
2928

30-
export class FirebaseTelemetry extends Component<FirebaseTelemetryProps> {
31-
constructor(public props: FirebaseTelemetryProps) {
32-
super(props);
33-
}
29+
function unhandledRejectionListener(event: PromiseRejectionEvent): void {
30+
captureError(getTelemetry(), event.reason, {});
31+
}
3432

35-
componentDidMount(): void {
33+
/**
34+
* Registers event listeners for uncaught errors.
35+
*
36+
* This should be installed near the root of your application. Caught errors, including those
37+
* implicitly caught by Error Boundaries, will not be captured by this component.
38+
*
39+
* @example
40+
* ```html
41+
* <body>
42+
* <FirebaseTelemetry firebaseOptions={options} />
43+
* ... my app ...
44+
* </body>
45+
* ```
46+
*
47+
* @param firebaseOptions - Options to run {@link @firebase/app#initializeApp}. If this is not provided, initializeApp needs to be called explicitly elsewhere in your application.
48+
* @returns The default {@link Telemetry} instance for the given {@link @firebase/app#FirebaseApp}.
49+
*
50+
* @public
51+
*/
52+
export function FirebaseTelemetry({
53+
firebaseOptions
54+
}: {
55+
firebaseOptions?: FirebaseOptions;
56+
}): null {
57+
useEffect(() => {
3658
if (typeof window === 'undefined') {
3759
return;
3860
}
@@ -41,27 +63,23 @@ export class FirebaseTelemetry extends Component<FirebaseTelemetryProps> {
4163
process.env.OTEL_ENDPOINT = window.location.origin;
4264

4365
try {
44-
const telemetry = this.props.firebaseOptions
45-
? getTelemetry(initializeApp(this.props.firebaseOptions))
46-
: getTelemetry();
47-
48-
window.addEventListener('error', (event: ErrorEvent) => {
49-
captureError(telemetry, event.error, {});
50-
});
51-
52-
window.addEventListener(
53-
'unhandledrejection',
54-
(event: PromiseRejectionEvent) => {
55-
captureError(telemetry, event.reason, {});
56-
}
57-
);
66+
if (firebaseOptions) {
67+
initializeApp(firebaseOptions);
68+
}
69+
window.addEventListener('error', errorListener);
70+
window.addEventListener('unhandledrejection', unhandledRejectionListener);
5871
} catch (error) {
5972
// Log the error here, but don't die.
6073
console.warn(`Firebase Telemetry was not initialized:\n`, error);
6174
}
62-
}
75+
return () => {
76+
window.removeEventListener('error', errorListener);
77+
window.removeEventListener(
78+
'unhandledrejection',
79+
unhandledRejectionListener
80+
);
81+
};
82+
}, []);
6383

64-
render(): ReactNode {
65-
return this.props.children;
66-
}
84+
return null;
6785
}

0 commit comments

Comments
 (0)