@@ -122,9 +122,21 @@ export class ImportResolver implements IImportResolver {
122122 for ( const [ pkg , versionRange ] of Object . entries ( allDeps ) ) {
123123 // Only store if not already set by resolutions/overrides
124124 if ( ! this . workspaceResolutions . has ( pkg ) && typeof versionRange === 'string' ) {
125+ // Handle npm aliases like "npm:@openzeppelin/contracts@4.8.3"
126+ if ( versionRange . startsWith ( 'npm:' ) ) {
127+ const npmAlias = versionRange . substring ( 4 ) // Remove "npm:" prefix
128+ const match = npmAlias . match ( / ^ ( @ ? [ ^ @ ] + ) @ ( .+ ) $ / )
129+ if ( match ) {
130+ const [ , realPackage , version ] = match
131+ this . workspaceResolutions . set ( pkg , `alias:${ realPackage } @${ version } ` )
132+ console . log ( `[ImportResolver] 🔗 NPM alias: ${ pkg } → ${ realPackage } @${ version } ` )
133+ } else {
134+ console . log ( `[ImportResolver] ⚠️ Invalid npm alias format: ${ pkg } → ${ versionRange } ` )
135+ }
136+ }
125137 // For exact versions (e.g., "4.8.3"), store directly
126138 // For ranges (e.g., "^4.8.0"), we'll need the lock file or npm to resolve
127- if ( versionRange . match ( / ^ \d + \. \d + \. \d + $ / ) ) {
139+ else if ( versionRange . match ( / ^ \d + \. \d + \. \d + $ / ) ) {
128140 // Exact version - store it
129141 this . workspaceResolutions . set ( pkg , versionRange )
130142 console . log ( `[ImportResolver] 📦 Workspace dependency (exact): ${ pkg } → ${ versionRange } ` )
@@ -597,11 +609,26 @@ export class ImportResolver implements IImportResolver {
597609 // Check if multiple parent packages have conflicting dependencies
598610 this . checkForConflictingParentDependencies ( packageName )
599611
600- // PRIORITY 1: Workspace resolutions/overrides
612+ // PRIORITY 1: Workspace resolutions/overrides - ALWAYS reload fresh
613+ await this . loadWorkspaceResolutions ( )
614+
601615 if ( this . workspaceResolutions . has ( packageName ) ) {
602- const version = this . workspaceResolutions . get ( packageName )
603- console . log ( `[ImportResolver] ✅ PRIORITY 1 - Workspace resolution: ${ packageName } → ${ version } ` )
604- return { version, source : 'workspace-resolution' }
616+ const resolution = this . workspaceResolutions . get ( packageName )
617+
618+ // Handle npm aliases like "alias:@openzeppelin/contracts@4.8.3"
619+ if ( resolution ?. startsWith ( 'alias:' ) ) {
620+ const aliasTarget = resolution . substring ( 6 ) // Remove "alias:" prefix
621+ console . log ( `[ImportResolver] 🔗 PRIORITY 1 - NPM alias: ${ packageName } → ${ aliasTarget } ` )
622+ const match = aliasTarget . match ( / ^ ( @ ? [ ^ @ ] + ) @ ( .+ ) $ / )
623+ if ( match ) {
624+ const [ , realPackage , version ] = match
625+ // Return the specific version from the alias, don't recurse
626+ return { version, source : `alias:${ packageName } →${ realPackage } ` }
627+ }
628+ } else {
629+ console . log ( `[ImportResolver] ✅ PRIORITY 1 - Workspace resolution: ${ packageName } → ${ resolution } ` )
630+ return { version : resolution , source : 'workspace-resolution' }
631+ }
605632 }
606633 console . log ( `[ImportResolver] ⏭️ Priority 1 (workspace): Not found` )
607634
@@ -654,8 +681,10 @@ export class ImportResolver implements IImportResolver {
654681 }
655682
656683 // Save package.json to file system for visibility and debugging
684+ // Use the actual package name from package.json, not the potentially aliased packageName parameter
685+ const realPackageName = packageJson . name || packageName
657686 try {
658- const targetPath = `.deps/npm/${ packageName } @${ packageJson . version } /package.json`
687+ const targetPath = `.deps/npm/${ realPackageName } @${ packageJson . version } /package.json`
659688 await this . pluginApi . call ( 'fileManager' , 'setFile' , targetPath , JSON . stringify ( packageJson , null , 2 ) )
660689 console . log ( `[ImportResolver] 💾 Saved package.json to: ${ targetPath } ` )
661690 } catch ( saveErr ) {
@@ -722,7 +751,17 @@ export class ImportResolver implements IImportResolver {
722751 return
723752 }
724753
725- const versionedPackageName = `${ packageName } @${ resolvedVersion } `
754+ // Handle npm aliases: if this is an alias, use the real package name
755+ let actualPackageName = packageName
756+ if ( source . startsWith ( 'alias:' ) ) {
757+ const aliasMatch = source . match ( / ^ a l i a s : [ ^ → ] + → ( .+ ) $ / )
758+ if ( aliasMatch ) {
759+ actualPackageName = aliasMatch [ 1 ]
760+ console . log ( `[ImportResolver] 🔄 Using real package name: ${ packageName } → ${ actualPackageName } ` )
761+ }
762+ }
763+
764+ const versionedPackageName = `${ actualPackageName } @${ resolvedVersion } `
726765 this . importMappings . set ( mappingKey , versionedPackageName )
727766
728767 // Record the source of this resolution
@@ -752,7 +791,9 @@ export class ImportResolver implements IImportResolver {
752791 // Save package.json if we haven't already (when using lock file or workspace resolutions)
753792 if ( source !== 'package-json' ) {
754793 try {
755- const targetPath = `.deps/npm/${ packageName } @${ resolvedVersion } /package.json`
794+ // Use the actual package name from package.json, not the potentially aliased packageName parameter
795+ const realPackageName = packageJson . name || packageName
796+ const targetPath = `.deps/npm/${ realPackageName } @${ resolvedVersion } /package.json`
756797 await this . pluginApi . call ( 'fileManager' , 'setFile' , targetPath , JSON . stringify ( packageJson , null , 2 ) )
757798 console . log ( `[ImportResolver] 💾 Saved package.json to: ${ targetPath } ` )
758799 } catch ( saveErr ) {
0 commit comments