@@ -12,7 +12,13 @@ vi.mock('path', async () => {
1212 const actual = await vi . importActual ( 'path' ) ;
1313 return {
1414 ...actual ,
15- resolve : vi . fn ( ) . mockReturnValue ( '/mocked/path/to/valueInjectionLoader.js' ) ,
15+ resolve : vi . fn ( ) . mockImplementation ( ( ...args : string [ ] ) => {
16+ const lastArg = args [ args . length - 1 ] ;
17+ if ( lastArg === 'moduleMetadataInjectionLoader.js' ) {
18+ return '/mocked/path/to/moduleMetadataInjectionLoader.js' ;
19+ }
20+ return '/mocked/path/to/valueInjectionLoader.js' ;
21+ } ) ,
1622 } ;
1723} ) ;
1824
@@ -936,6 +942,144 @@ describe('condition field version gating', () => {
936942 } ) ;
937943} ) ;
938944
945+ describe ( 'moduleMetadataInjection with applicationKey' , ( ) => {
946+ it ( 'should add metadata loader rule when applicationKey is set and Next.js >= 16' , ( ) => {
947+ const pathResolveSpy = vi . spyOn ( path , 'resolve' ) ;
948+ pathResolveSpy . mockImplementation ( ( ...args : string [ ] ) => {
949+ const lastArg = args [ args . length - 1 ] ;
950+ if ( lastArg === 'moduleMetadataInjectionLoader.js' ) {
951+ return '/mocked/path/to/moduleMetadataInjectionLoader.js' ;
952+ }
953+ return '/mocked/path/to/valueInjectionLoader.js' ;
954+ } ) ;
955+
956+ const userNextConfig : NextConfigObject = { } ;
957+
958+ const result = constructTurbopackConfig ( {
959+ userNextConfig,
960+ userSentryOptions : { _experimental : { turbopackApplicationKey : 'my-app' } } ,
961+ nextJsVersion : '16.0.0' ,
962+ } ) ;
963+
964+ expect ( result . rules ! [ '*.{ts,tsx,js,jsx,mjs,cjs}' ] ) . toEqual ( {
965+ condition : { not : 'foreign' } ,
966+ loaders : [
967+ {
968+ loader : '/mocked/path/to/moduleMetadataInjectionLoader.js' ,
969+ options : {
970+ applicationKey : 'my-app' ,
971+ } ,
972+ } ,
973+ ] ,
974+ } ) ;
975+ } ) ;
976+
977+ it ( 'should NOT add metadata loader rule when Next.js < 16' , ( ) => {
978+ const userNextConfig : NextConfigObject = { } ;
979+
980+ const result = constructTurbopackConfig ( {
981+ userNextConfig,
982+ userSentryOptions : { _experimental : { turbopackApplicationKey : 'my-app' } } ,
983+ nextJsVersion : '15.4.1' ,
984+ } ) ;
985+
986+ expect ( result . rules ! [ '*.{ts,tsx,js,jsx,mjs,cjs}' ] ) . toBeUndefined ( ) ;
987+ } ) ;
988+
989+ it ( 'should NOT add metadata loader rule when applicationKey is not set' , ( ) => {
990+ const userNextConfig : NextConfigObject = { } ;
991+
992+ const result = constructTurbopackConfig ( {
993+ userNextConfig,
994+ userSentryOptions : { } ,
995+ nextJsVersion : '16.0.0' ,
996+ } ) ;
997+
998+ expect ( result . rules ! [ '*.{ts,tsx,js,jsx,mjs,cjs}' ] ) . toBeUndefined ( ) ;
999+ } ) ;
1000+
1001+ it ( 'should NOT add metadata loader rule when nextJsVersion is undefined' , ( ) => {
1002+ const userNextConfig : NextConfigObject = { } ;
1003+
1004+ const result = constructTurbopackConfig ( {
1005+ userNextConfig,
1006+ userSentryOptions : { _experimental : { turbopackApplicationKey : 'my-app' } } ,
1007+ nextJsVersion : undefined ,
1008+ } ) ;
1009+
1010+ expect ( result . rules ! [ '*.{ts,tsx,js,jsx,mjs,cjs}' ] ) . toBeUndefined ( ) ;
1011+ } ) ;
1012+
1013+ it ( 'should pass applicationKey through to loader options correctly' , ( ) => {
1014+ const userNextConfig : NextConfigObject = { } ;
1015+
1016+ const result = constructTurbopackConfig ( {
1017+ userNextConfig,
1018+ userSentryOptions : { _experimental : { turbopackApplicationKey : 'custom-key-123' } } ,
1019+ nextJsVersion : '16.0.0' ,
1020+ } ) ;
1021+
1022+ const rule = result . rules ! [ '*.{ts,tsx,js,jsx,mjs,cjs}' ] as {
1023+ condition : unknown ;
1024+ loaders : Array < { loader : string ; options : { applicationKey : string } } > ;
1025+ } ;
1026+ expect ( rule . loaders [ 0 ] ! . options . applicationKey ) . toBe ( 'custom-key-123' ) ;
1027+ } ) ;
1028+
1029+ it ( 'should coexist with existing value injection rules' , ( ) => {
1030+ const userNextConfig : NextConfigObject = { } ;
1031+ const mockRouteManifest : RouteManifest = {
1032+ dynamicRoutes : [ ] ,
1033+ staticRoutes : [ { path : '/' , regex : '/' } ] ,
1034+ isrRoutes : [ ] ,
1035+ } ;
1036+
1037+ const result = constructTurbopackConfig ( {
1038+ userNextConfig,
1039+ userSentryOptions : { _experimental : { turbopackApplicationKey : 'my-app' } } ,
1040+ routeManifest : mockRouteManifest ,
1041+ nextJsVersion : '16.0.0' ,
1042+ } ) ;
1043+
1044+ // Value injection rules should still be present
1045+ expect ( result . rules ! [ '**/instrumentation-client.*' ] ) . toBeDefined ( ) ;
1046+ expect ( result . rules ! [ '**/instrumentation.*' ] ) . toBeDefined ( ) ;
1047+ // Metadata loader rule should also be present
1048+ expect ( result . rules ! [ '*.{ts,tsx,js,jsx,mjs,cjs}' ] ) . toBeDefined ( ) ;
1049+ } ) ;
1050+
1051+ it ( 'should add metadata loader rule for Next.js 17+' , ( ) => {
1052+ const pathResolveSpy = vi . spyOn ( path , 'resolve' ) ;
1053+ pathResolveSpy . mockImplementation ( ( ...args : string [ ] ) => {
1054+ const lastArg = args [ args . length - 1 ] ;
1055+ if ( lastArg === 'moduleMetadataInjectionLoader.js' ) {
1056+ return '/mocked/path/to/moduleMetadataInjectionLoader.js' ;
1057+ }
1058+ return '/mocked/path/to/valueInjectionLoader.js' ;
1059+ } ) ;
1060+
1061+ const userNextConfig : NextConfigObject = { } ;
1062+
1063+ const result = constructTurbopackConfig ( {
1064+ userNextConfig,
1065+ userSentryOptions : { _experimental : { turbopackApplicationKey : 'my-app' } } ,
1066+ nextJsVersion : '17.0.0' ,
1067+ } ) ;
1068+
1069+ expect ( result . rules ! [ '*.{ts,tsx,js,jsx,mjs,cjs}' ] ) . toEqual ( {
1070+ condition : { not : 'foreign' } ,
1071+ loaders : [
1072+ {
1073+ loader : '/mocked/path/to/moduleMetadataInjectionLoader.js' ,
1074+ options : {
1075+ applicationKey : 'my-app' ,
1076+ } ,
1077+ } ,
1078+ ] ,
1079+ } ) ;
1080+ } ) ;
1081+ } ) ;
1082+
9391083describe ( 'safelyAddTurbopackRule' , ( ) => {
9401084 const mockRule = {
9411085 loaders : [
0 commit comments