Skip to content

Commit 9cd3607

Browse files
committed
core: add getDefaultExport method
This was implemented for the portable Express integration, but others will need the same functionality, so we should have a reusable to save on bundle size.
1 parent 93a591e commit 9cd3607

File tree

4 files changed

+53
-16
lines changed

4 files changed

+53
-16
lines changed

packages/core/src/integrations/express/index.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,10 @@ import { DEBUG_BUILD } from '../../debug-build';
3333
import type {
3434
ExpressApplication,
3535
ExpressErrorMiddleware,
36-
ExpressExport,
3736
ExpressHandlerOptions,
3837
ExpressIntegrationOptions,
3938
ExpressLayer,
4039
ExpressMiddleware,
41-
ExpressModuleExport,
4240
ExpressRequest,
4341
ExpressResponse,
4442
ExpressRouter,
@@ -49,16 +47,13 @@ import type {
4947
import {
5048
defaultShouldHandleError,
5149
getLayerPath,
52-
hasDefaultProp,
5350
isExpressWithoutRouterPrototype,
5451
isExpressWithRouterPrototype,
5552
} from './utils';
5653
import { wrapMethod } from '../../utils/object';
5754
import { patchLayer } from './patch-layer';
5855
import { setSDKProcessingMetadata } from './set-sdk-processing-metadata';
59-
60-
const getExpressExport = (express: ExpressModuleExport): ExpressExport =>
61-
hasDefaultProp(express) ? express.default : (express as ExpressExport);
56+
import { getDefaultExport } from '../../utils/get-default-export';
6257

6358
/**
6459
* This is a portable instrumentatiton function that works in any environment
@@ -73,7 +68,7 @@ const getExpressExport = (express: ExpressModuleExport): ExpressExport =>
7368
*/
7469
export const patchExpressModule = (options: ExpressIntegrationOptions) => {
7570
// pass in the require() or import() result of express
76-
const express = getExpressExport(options.express);
71+
const express = getDefaultExport(options.express);
7772
const routerProto: ExpressRouterv4 | ExpressRouterv5 | undefined = isExpressWithRouterPrototype(express)
7873
? express.Router.prototype // Express v5
7974
: isExpressWithoutRouterPrototype(express)

packages/core/src/integrations/express/utils.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import type { SpanAttributes } from '../../types-hoist/span';
3131
import { getStoredLayers } from './request-layer-store';
3232
import type {
33-
ExpressExport,
3433
ExpressIntegrationOptions,
3534
ExpressLayer,
3635
ExpressLayerType,
@@ -254,14 +253,6 @@ const isExpressRouterPrototype = (routerProto?: unknown): routerProto is Express
254253
export const isExpressWithoutRouterPrototype = (express: unknown): express is ExpressExportv4 =>
255254
isExpressRouterPrototype((express as ExpressExportv4).Router) && !isExpressWithRouterPrototype(express);
256255

257-
// dynamic puts the default on .default, require or normal import are fine
258-
export const hasDefaultProp = (
259-
express: unknown,
260-
): express is {
261-
[k: string]: unknown;
262-
default: ExpressExport;
263-
} => !!express && typeof express === 'object' && 'default' in express && typeof express.default === 'function';
264-
265256
function getStatusCodeFromResponse(error: MiddlewareError): number {
266257
const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode;
267258
return statusCode ? parseInt(statusCode as string, 10) : 500;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Often we patch a module's default export, but we want to be able to do
3+
* something like this:
4+
*
5+
* ```ts
6+
* patchTheThing(await import('the-thing'));
7+
* ```
8+
*
9+
* Or like this:
10+
*
11+
* ```ts
12+
* import theThing from 'the-thing';
13+
* patchTheThing(theThing);
14+
* ```
15+
*/
16+
export function getDefaultExport<T>(moduleExport: T | { default: T }): T {
17+
return (
18+
(!!moduleExport &&
19+
typeof moduleExport === 'object' &&
20+
'default' in moduleExport &&
21+
(moduleExport as { default: T }).default) ||
22+
(moduleExport as T)
23+
);
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { getDefaultExport } from '../../../src/utils/get-default-export';
3+
4+
describe('getDefaultExport', () => {
5+
it('returns the default export if there is one', () => {
6+
const mod = {
7+
default: () => {}
8+
};
9+
expect(getDefaultExport(mod)).toBe(mod.default)
10+
});
11+
it('returns the module export if no default', () => {
12+
const mod = {};
13+
expect(getDefaultExport(mod)).toBe(mod)
14+
});
15+
it('returns the module if a function and not plain object', () => {
16+
const mod = Object.assign(function () {}, {
17+
default: () => {}
18+
});
19+
expect(getDefaultExport(mod)).toBe(mod)
20+
});
21+
it('returns the module if a default is falsey', () => {
22+
const mod = Object.assign(function () {}, {
23+
default: false,
24+
});
25+
expect(getDefaultExport(mod)).toBe(mod)
26+
});
27+
});

0 commit comments

Comments
 (0)