Skip to content

Commit 1f0caf1

Browse files
committed
feat(core): Update withScope to return callback return value
To align this with OpenTelemetry and make some things possible that are currently not easily doable without `pushScope` / `popScope`.
1 parent 30bb8b5 commit 1f0caf1

File tree

4 files changed

+58
-5
lines changed

4 files changed

+58
-5
lines changed

packages/core/src/exports.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ export function setUser(user: User | null): ReturnType<Hub['setUser']> {
163163
*
164164
* @param callback that will be enclosed into push/popScope.
165165
*/
166-
export function withScope(callback: (scope: Scope) => void): ReturnType<Hub['withScope']> {
167-
getCurrentHub().withScope(callback);
166+
export function withScope<T>(callback: (scope: Scope) => T): T {
167+
return getCurrentHub().withScope(callback);
168168
}
169169

170170
/**

packages/core/src/hub.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ export class Hub implements HubInterface {
161161
/**
162162
* @inheritDoc
163163
*/
164-
public withScope(callback: (scope: Scope) => void): void {
164+
public withScope<T>(callback: (scope: Scope) => T): T {
165165
const scope = this.pushScope();
166166
try {
167-
callback(scope);
167+
return callback(scope);
168168
} finally {
169169
this.popScope();
170170
}
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Hub, Scope, makeMain, withScope, getCurrentScope } from '../../src';
2+
import { TestClient, getDefaultTestClientOptions } from '../mocks/client';
3+
4+
function getTestClient(): TestClient {
5+
return new TestClient(
6+
getDefaultTestClientOptions({
7+
dsn: 'https://username@domain/123',
8+
}),
9+
);
10+
}
11+
12+
describe('withScope', () => {
13+
beforeEach(() => {
14+
const client = getTestClient();
15+
const hub = new Hub(client);
16+
makeMain(hub);
17+
});
18+
19+
it('works without a return value', () => {
20+
const scope1 = getCurrentScope();
21+
expect(scope1).toBeInstanceOf(Scope);
22+
23+
scope1.setTag('foo', 'bar');
24+
25+
const res = withScope(scope => {
26+
expect(scope).toBeInstanceOf(Scope);
27+
expect(scope).not.toBe(scope1);
28+
expect(scope['_tags']).toEqual({ foo: 'bar' });
29+
30+
expect(getCurrentScope()).toBe(scope);
31+
});
32+
33+
expect(getCurrentScope()).toBe(scope1);
34+
expect(res).toBe(undefined);
35+
});
36+
37+
it('works with a return value', () => {
38+
const res = withScope(scope => {
39+
return 'foo';
40+
});
41+
42+
expect(res).toBe('foo');
43+
});
44+
45+
it('works with an async function',async () => {
46+
const res = withScope(async scope => {
47+
return 'foo';
48+
});
49+
50+
expect(res).toBeInstanceOf(Promise);
51+
expect(await res).toBe('foo')
52+
});
53+
});

packages/types/src/hub.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export interface Hub {
6565
*
6666
* @param callback that will be enclosed into push/popScope.
6767
*/
68-
withScope(callback: (scope: Scope) => void): void;
68+
withScope<T>(callback: (scope: Scope) => T): T;
6969

7070
/** Returns the client of the top stack. */
7171
getClient(): Client | undefined;

0 commit comments

Comments
 (0)