-
Notifications
You must be signed in to change notification settings - Fork 936
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Link dependencies before installation (#7145)
## Proposed Changes - core aspects, legacy, harmony, and local deps from the capsule are linked before installation. - the information about all the links is passed to the package manager, so that the package manager won't remove them.
- Loading branch information
Showing
4 changed files
with
145 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 34 additions & 23 deletions
57
scopes/component/isolator/symlink-dependencies-to-capsules.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,69 @@ | ||
import { ComponentID } from '@teambit/component'; | ||
import { LinkDetail } from '@teambit/dependency-resolver'; | ||
import { Logger } from '@teambit/logger'; | ||
import { BitId } from '@teambit/legacy-bit-id'; | ||
import ConsumerComponent from '@teambit/legacy/dist/consumer/component'; | ||
import Symlink from '@teambit/legacy/dist/links/symlink'; | ||
import componentIdToPackageName from '@teambit/legacy/dist/utils/bit/component-id-to-package-name'; | ||
import path from 'path'; | ||
|
||
import { Capsule } from './capsule'; | ||
import CapsuleList from './capsule-list'; | ||
|
||
export async function symlinkDependenciesToCapsules(capsules: Capsule[], capsuleList: CapsuleList, logger: Logger) { | ||
export async function symlinkDependenciesToCapsules( | ||
capsules: Capsule[], | ||
capsuleList: CapsuleList, | ||
logger: Logger | ||
): Promise<Record<string, Record<string, string>>> { | ||
logger.debug(`symlinkDependenciesToCapsules, ${capsules.length} capsules`); | ||
await Promise.all( | ||
capsules.map((capsule) => { | ||
return symlinkComponent(capsule.component.state._consumer, capsuleList, logger); | ||
}) | ||
return Object.fromEntries( | ||
await Promise.all( | ||
capsules.map((capsule) => { | ||
return symlinkComponent(capsule.component.state._consumer, capsuleList, logger); | ||
}) | ||
) | ||
); | ||
} | ||
|
||
export async function symlinkOnCapsuleRoot(capsuleList: CapsuleList, logger: Logger, capsuleRoot: string) { | ||
export async function symlinkOnCapsuleRoot( | ||
capsuleList: CapsuleList, | ||
logger: Logger, | ||
capsuleRoot: string | ||
): Promise<LinkDetail[]> { | ||
const modulesPath = path.join(capsuleRoot, 'node_modules'); | ||
const symlinks = capsuleList.map((capsule) => { | ||
return capsuleList.map((capsule) => { | ||
const packageName = componentIdToPackageName(capsule.component.state._consumer); | ||
const dest = path.join(modulesPath, packageName); | ||
const src = path.relative(path.resolve(dest, '..'), capsule.path); | ||
|
||
return new Symlink(src, dest, capsule.component.id._legacy); | ||
return { | ||
from: capsule.path, | ||
to: dest, | ||
packageName, | ||
}; | ||
}); | ||
|
||
await Promise.all(symlinks.map((symlink) => symlink.write())); | ||
} | ||
|
||
async function symlinkComponent(component: ConsumerComponent, capsuleList: CapsuleList, logger: Logger) { | ||
async function symlinkComponent( | ||
component: ConsumerComponent, | ||
capsuleList: CapsuleList, | ||
logger: Logger | ||
): Promise<[string, Record<string, string>]> { | ||
const componentCapsule = capsuleList.getCapsuleIgnoreScopeAndVersion(new ComponentID(component.id)); | ||
if (!componentCapsule) throw new Error(`unable to find the capsule for ${component.id.toString()}`); | ||
const allDeps = component.getAllDependenciesIds(); | ||
const symlinks = allDeps.map((depId: BitId) => { | ||
const linkResults = allDeps.reduce((acc, depId: BitId) => { | ||
// TODO: this is dangerous - we might have 2 capsules for the same component with different version, then we might link to the wrong place | ||
const devCapsule = capsuleList.getCapsuleIgnoreScopeAndVersion(new ComponentID(depId)); | ||
if (!devCapsule) { | ||
// happens when a dependency is not in the workspace. (it gets installed via the package manager) | ||
logger.debug( | ||
`symlinkComponentToCapsule: unable to find the capsule for ${depId.toStringWithoutVersion()}. skipping` | ||
); | ||
return null; | ||
return acc; | ||
} | ||
const packageName = componentIdToPackageName(devCapsule.component.state._consumer); | ||
const devCapsulePath = devCapsule.path; | ||
// @todo: this is a hack, the capsule should be the one responsible to symlink, this works only for FS capsules. | ||
const dest = path.join(componentCapsule.path, 'node_modules', packageName); | ||
// use relative symlink in capsules to make it really isolated from the machine fs | ||
const src = path.relative(path.resolve(dest, '..'), devCapsulePath); | ||
return new Symlink(src, dest, component.id); | ||
}); | ||
acc[packageName] = `link:${devCapsulePath}`; | ||
return acc; | ||
}, {}); | ||
|
||
await Promise.all(symlinks.map((symlink) => symlink && symlink.write())); | ||
return [componentCapsule.path, linkResults]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters