@@ -44,35 +44,83 @@ function hasAbsolutePaths(content: string): {
4444}
4545
4646/**
47- * Check if content is missing external dependencies (they should be import/require statements) .
48- * External dependencies should NOT be bundled inline.
47+ * Check if bundle contains inlined dependencies.
48+ * Reads package.json dependencies and ensures they are NOT bundled inline.
4949 */
50- function checkExternalDependencies ( content : string ) : {
51- missingImports : string [ ]
52- hasAllImports : boolean
53- } {
54- // Dependencies that should be external (as import/require statements).
55- const externalDeps = [ '@socketsecurity/lib' ]
56-
57- const missingImports : string [ ] = [ ]
58-
59- for ( const dep of externalDeps ) {
60- // Check if the bundle has import or require() statements for this dependency.
61- // ESM: import { foo } from "@socketsecurity/lib"
62- // CJS: require("@socketsecurity/lib")
63- const importPattern = new RegExp (
64- `(?:import\\s+.*?from\\s+["']${ dep . replace ( '/' , '\\/' ) } |require\\(["']${ dep . replace ( '/' , '\\/' ) } ["']\\))` ,
65- )
66- const hasImport = importPattern . test ( content )
67-
68- if ( ! hasImport ) {
69- missingImports . push ( dep )
50+ async function checkBundledDependencies ( content : string ) : Promise < {
51+ bundledDeps : string [ ]
52+ hasNoBundledDeps : boolean
53+ } > {
54+ // Read package.json to get runtime dependencies.
55+ const pkgJsonPath = path . join ( packagePath , 'package.json' )
56+ const pkgJson = JSON . parse ( await fs . readFile ( pkgJsonPath , 'utf8' ) )
57+ const dependencies = pkgJson . dependencies || { }
58+
59+ const bundledDeps : string [ ] = [ ]
60+
61+ // If we have NO dependencies, check that no external packages are bundled.
62+ if ( Object . keys ( dependencies ) . length === 0 ) {
63+ // Look for signs of bundled npm packages in ESM format.
64+ // Bundled ESM packages have patterns like:
65+ // - import { x } from "inline-bundled-code"
66+ // - Functions from external packages inlined directly.
67+ const bundledPackagePatterns = [
68+ // Socket packages that should always be external.
69+ / @ s o c k e t s e c u r i t y \/ l i b / ,
70+ / @ s o c k e t s e c u r i t y \/ p a c k a g e u r l - j s / ,
71+ / @ s o c k e t s e c u r i t y \/ s d k / ,
72+ / @ s o c k e t s e c u r i t y \/ r e g i s t r y / ,
73+ ]
74+
75+ for ( const pattern of bundledPackagePatterns ) {
76+ // For ESM bundles, check if imports are to external packages (good)
77+ // vs having the code inlined (bad).
78+ // Look for: import ... from "@socketsecurity/lib" (external - good)
79+ // vs: no imports but code from the package is present (bundled - bad).
80+ const hasExternalImport = new RegExp (
81+ `import\\s+.*?from\\s+["']${ pattern . source } ` ,
82+ ) . test ( content )
83+
84+ // If no external import found, check if package code might be bundled.
85+ // This is a heuristic - look for multiple characteristic functions.
86+ if ( ! hasExternalImport ) {
87+ // Check for signs of bundled code from this package.
88+ // This would mean the package wasn't properly externalized.
89+ const bundlePattern = new RegExp (
90+ `(?:var|const|let)\\s+\\w+.*${ pattern . source } ` ,
91+ )
92+
93+ if ( bundlePattern . test ( content ) ) {
94+ bundledDeps . push ( pattern . source )
95+ }
96+ }
97+ }
98+ } else {
99+ // If we have dependencies, check that they remain external (not bundled).
100+ for ( const dep of Object . keys ( dependencies ) ) {
101+ const escapedDep = dep . replace ( / [ / \\ ^ $ * + ? . ( ) | [ \] { } ] / g, '\\$&' )
102+
103+ // Check if dependency is properly external.
104+ const hasExternalImport = new RegExp (
105+ `import\\s+.*?from\\s+["']${ escapedDep } ` ,
106+ ) . test ( content )
107+
108+ // If no external import, it might be bundled.
109+ if ( ! hasExternalImport ) {
110+ const bundlePattern = new RegExp (
111+ `(?:var|const|let)\\s+\\w+.*${ escapedDep } ` ,
112+ )
113+
114+ if ( bundlePattern . test ( content ) ) {
115+ bundledDeps . push ( dep )
116+ }
117+ }
70118 }
71119 }
72120
73121 return {
74- missingImports ,
75- hasAllImports : missingImports . length === 0 ,
122+ bundledDeps ,
123+ hasNoBundledDeps : bundledDeps . length === 0 ,
76124 }
77125}
78126
@@ -95,24 +143,22 @@ describe('Bundle validation', () => {
95143 )
96144 } )
97145
98- it ( 'should have external dependencies as import/require statements ' , async ( ) => {
146+ it ( 'should not bundle dependencies inline (validate against package.json dependencies) ' , async ( ) => {
99147 const indexPath = path . join ( distPath , 'index.mjs' )
100148 const content = await fs . readFile ( indexPath , 'utf8' )
101149
102- const result = checkExternalDependencies ( content )
150+ const result = await checkBundledDependencies ( content )
103151
104- if ( ! result . hasAllImports ) {
105- console . error (
106- 'Missing import/require statements for external dependencies:' ,
107- )
108- for ( const dep of result . missingImports ) {
152+ if ( ! result . hasNoBundledDeps ) {
153+ console . error ( 'Found bundled dependencies (should be external):' )
154+ for ( const dep of result . bundledDeps ) {
109155 console . error ( ` - ${ dep } ` )
110156 }
111157 }
112158
113159 expect (
114- result . hasAllImports ,
115- 'All external dependencies should be import/require statements , not bundled inline' ,
160+ result . hasNoBundledDeps ,
161+ 'Dependencies from package.json should be external , not bundled inline' ,
116162 ) . toBe ( true )
117163 } )
118164} )
0 commit comments