@teambit/dependency-resolver 1.0.106 → 1.0.108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apply-updates.spec.ts +215 -0
- package/apply-updates.ts +81 -0
- package/dependency-detector.ts +5 -0
- package/dependency-env.ts +6 -0
- package/dependency-installer.ts +347 -0
- package/dependency-linker.ts +719 -0
- package/dependency-resolver.aspect.ts +7 -0
- package/dependency-resolver.graphql.ts +99 -0
- package/dependency-resolver.main.runtime.spec.ts +530 -0
- package/dependency-resolver.main.runtime.ts +1797 -0
- package/dependency-version-resolver.ts +42 -0
- package/dist/apply-updates.js +2 -4
- package/dist/apply-updates.js.map +1 -1
- package/dist/dependencies/base-dependency.d.ts +7 -7
- package/dist/dependencies/base-dependency.js +1 -2
- package/dist/dependencies/base-dependency.js.map +1 -1
- package/dist/dependencies/component-dependency/component-dependency.js +1 -2
- package/dist/dependencies/component-dependency/component-dependency.js.map +1 -1
- package/dist/dependencies/dependency-list-factory.js +2 -4
- package/dist/dependencies/dependency-list-factory.js.map +1 -1
- package/dist/dependencies/dependency-list.d.ts +2 -2
- package/dist/dependencies/dependency-list.js +1 -4
- package/dist/dependencies/dependency-list.js.map +1 -1
- package/dist/dependencies/dependency.d.ts +5 -5
- package/dist/dependencies.service.d.ts +4 -4
- package/dist/dependencies.service.js +3 -3
- package/dist/dependencies.service.js.map +1 -1
- package/dist/dependency-installer.d.ts +10 -9
- package/dist/dependency-installer.js +5 -8
- package/dist/dependency-installer.js.map +1 -1
- package/dist/dependency-linker.d.ts +10 -9
- package/dist/dependency-linker.js +7 -11
- package/dist/dependency-linker.js.map +1 -1
- package/dist/dependency-resolver.composition.d.ts +2 -2
- package/dist/dependency-resolver.main.runtime.d.ts +15 -15
- package/dist/dependency-resolver.main.runtime.js +33 -39
- package/dist/dependency-resolver.main.runtime.js.map +1 -1
- package/dist/dependency-version-resolver.d.ts +2 -1
- package/dist/get-all-policy-pkgs.d.ts +4 -4
- package/dist/manifest/deduping/dedupe-dependencies.d.ts +4 -4
- package/dist/manifest/deduping/dedupe-dependencies.js +1 -1
- package/dist/manifest/deduping/dedupe-dependencies.js.map +1 -1
- package/dist/manifest/deduping/hoist-dependencies.js +2 -3
- package/dist/manifest/deduping/hoist-dependencies.js.map +1 -1
- package/dist/manifest/deduping/hoist-dependencies.spec.js +6 -8
- package/dist/manifest/deduping/hoist-dependencies.spec.js.map +1 -1
- package/dist/manifest/deduping/index-by-dep-id.d.ts +4 -4
- package/dist/manifest/deduping/index-by-dep-id.js +1 -2
- package/dist/manifest/deduping/index-by-dep-id.js.map +1 -1
- package/dist/manifest/manifest.d.ts +4 -4
- package/dist/manifest/update-dependency-version.js +2 -2
- package/dist/manifest/update-dependency-version.js.map +1 -1
- package/dist/manifest/workspace-manifest-factory.d.ts +3 -3
- package/dist/manifest/workspace-manifest-factory.js +3 -5
- package/dist/manifest/workspace-manifest-factory.js.map +1 -1
- package/dist/manifest/workspace-manifest.js +1 -2
- package/dist/manifest/workspace-manifest.js.map +1 -1
- package/dist/package-manager-legacy.d.ts +1 -1
- package/dist/package-manager.d.ts +5 -5
- package/dist/policy/env-policy/env-policy.d.ts +7 -7
- package/dist/policy/policy.d.ts +9 -9
- package/dist/policy/variant-policy/variant-policy.d.ts +9 -9
- package/dist/policy/workspace-policy/workspace-policy.d.ts +11 -11
- package/dist/{preview-1703505948637.js → preview-1703647408454.js} +2 -2
- package/dist/registry/registry.d.ts +6 -6
- package/dist/show-fragments/serialize-by-lifecycle.js +1 -2
- package/dist/show-fragments/serialize-by-lifecycle.js.map +1 -1
- package/dist/types.d.ts +8 -8
- package/extend-with-components-from-dir.ts +29 -0
- package/get-all-policy-pkgs.spec.ts +82 -0
- package/get-all-policy-pkgs.ts +126 -0
- package/index.ts +70 -0
- package/package-manager-legacy.ts +137 -0
- package/package-manager.ts +174 -0
- package/package.json +27 -34
- package/tsconfig.json +16 -21
- package/types/asset.d.ts +15 -3
- package/types.ts +77 -0
package/dist/types.d.ts
CHANGED
|
@@ -2,15 +2,15 @@ import { ComponentConfig, ComponentFS } from '@teambit/component';
|
|
|
2
2
|
import { PathLinux } from '@teambit/legacy/dist/utils/path';
|
|
3
3
|
import { ComponentManifest } from './manifest/component-manifest';
|
|
4
4
|
import { PackageName } from './dependencies';
|
|
5
|
-
export
|
|
6
|
-
export
|
|
5
|
+
export type RegistryName = string;
|
|
6
|
+
export type Registry = {
|
|
7
7
|
uri: string;
|
|
8
8
|
alwaysAuth: boolean;
|
|
9
9
|
authHeaderValue?: string;
|
|
10
10
|
originalAuthType: string;
|
|
11
11
|
originalAuthValue: string;
|
|
12
12
|
};
|
|
13
|
-
export
|
|
13
|
+
export type RegistriesMap = Record<RegistryName, Registry>;
|
|
14
14
|
export interface RawComponentState {
|
|
15
15
|
filesystem: ComponentFS;
|
|
16
16
|
config: ComponentConfig;
|
|
@@ -20,7 +20,7 @@ export interface RawComponentState {
|
|
|
20
20
|
* For example, `import foo from './bar' `, "foo" is the import-specifier and is default.
|
|
21
21
|
* Conversely, `import { foo } from './bar' `, here, "foo" is non-default.
|
|
22
22
|
*/
|
|
23
|
-
export
|
|
23
|
+
export type Specifier = {
|
|
24
24
|
isDefault: boolean;
|
|
25
25
|
name: string;
|
|
26
26
|
};
|
|
@@ -29,7 +29,7 @@ export declare type Specifier = {
|
|
|
29
29
|
* For example, a component might have a dependency: "import { foo } from './bar' ", when a link is generated, we use
|
|
30
30
|
* the import-specifier name, which is "foo" to generate the link correctly.
|
|
31
31
|
*/
|
|
32
|
-
export
|
|
32
|
+
export type ImportSpecifier = {
|
|
33
33
|
mainFile: Specifier;
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
@@ -42,7 +42,7 @@ export declare type ImportSpecifier = {
|
|
|
42
42
|
* In this example, the component "foo" has one dependency "utils" with two RelativePaths.
|
|
43
43
|
* one for utils/is-string.js file and the second for utils/is-array.js file
|
|
44
44
|
*/
|
|
45
|
-
export
|
|
45
|
+
export type RelativePath = {
|
|
46
46
|
sourceRelativePath: PathLinux;
|
|
47
47
|
destinationRelativePath: PathLinux;
|
|
48
48
|
importSpecifiers?: ImportSpecifier[];
|
|
@@ -57,6 +57,6 @@ interface FileDependencyDefinition {
|
|
|
57
57
|
relativePaths?: RelativePath[];
|
|
58
58
|
isType?: boolean;
|
|
59
59
|
}
|
|
60
|
-
export
|
|
61
|
-
export
|
|
60
|
+
export type FileDependenciesDefinition = FileDependencyDefinition[];
|
|
61
|
+
export type ComponentsManifestsMap = Map<PackageName, ComponentManifest>;
|
|
62
62
|
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Currently, the same capsule directory is used multiple times during installation.
|
|
6
|
+
* The issue is that the state between installations is not preserved,
|
|
7
|
+
* so the node_modules directory gets broken on each sunseqent install.
|
|
8
|
+
* This function is for finding all components in the root of the capsule and reading their manifests.
|
|
9
|
+
* This way the package manager will have all the necessary information to keep the node_modules directory
|
|
10
|
+
* in the correct state.
|
|
11
|
+
*/
|
|
12
|
+
export async function extendWithComponentsFromDir(rootDir: string, manifestsByPaths) {
|
|
13
|
+
const files = await fs.readdir(rootDir, { withFileTypes: true });
|
|
14
|
+
const newManifestsByPaths = { ...manifestsByPaths };
|
|
15
|
+
await Promise.all(
|
|
16
|
+
files
|
|
17
|
+
.filter((file) => file.isDirectory() && file.name !== 'node_modules')
|
|
18
|
+
.map((dir) => path.join(rootDir, dir.name))
|
|
19
|
+
.filter((dirPath) => !manifestsByPaths[dirPath])
|
|
20
|
+
.map(async (dirPath) => {
|
|
21
|
+
try {
|
|
22
|
+
newManifestsByPaths[dirPath] = await fs.readJson(path.join(dirPath, 'package.json'));
|
|
23
|
+
} catch (err: any) {
|
|
24
|
+
if (err.code !== 'ENOENT') throw err;
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
return newManifestsByPaths;
|
|
29
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ComponentID } from '@teambit/component';
|
|
2
|
+
import { getAllPolicyPkgs } from './get-all-policy-pkgs';
|
|
3
|
+
import { WorkspacePolicy } from './policy';
|
|
4
|
+
|
|
5
|
+
describe('getAllPolicyPkgs()', () => {
|
|
6
|
+
it('should read the version from a version object', () => {
|
|
7
|
+
const outdatedPkgs = getAllPolicyPkgs({
|
|
8
|
+
rootPolicy: new WorkspacePolicy([]),
|
|
9
|
+
variantPoliciesByPatterns: {
|
|
10
|
+
comp: {
|
|
11
|
+
dependencies: {
|
|
12
|
+
foo: {
|
|
13
|
+
version: '1',
|
|
14
|
+
resolveFromEnv: true,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
devDependencies: {},
|
|
18
|
+
peerDependencies: {},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
componentPolicies: [],
|
|
22
|
+
componentModelVersions: [],
|
|
23
|
+
});
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
expect(outdatedPkgs).toStrictEqual([
|
|
26
|
+
{
|
|
27
|
+
currentRange: '1',
|
|
28
|
+
name: 'foo',
|
|
29
|
+
source: 'variants',
|
|
30
|
+
targetField: 'dependencies',
|
|
31
|
+
variantPattern: 'comp',
|
|
32
|
+
},
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
35
|
+
it('should deduplicate dependencies that are present in root policies', () => {
|
|
36
|
+
const outdatedPkgs = getAllPolicyPkgs({
|
|
37
|
+
rootPolicy: new WorkspacePolicy([
|
|
38
|
+
{
|
|
39
|
+
dependencyId: 'foo',
|
|
40
|
+
lifecycleType: 'runtime',
|
|
41
|
+
value: { version: '1' },
|
|
42
|
+
},
|
|
43
|
+
]),
|
|
44
|
+
variantPoliciesByPatterns: {},
|
|
45
|
+
componentPolicies: [],
|
|
46
|
+
componentModelVersions: [
|
|
47
|
+
{
|
|
48
|
+
name: 'foo',
|
|
49
|
+
version: '2',
|
|
50
|
+
lifecycleType: 'runtime',
|
|
51
|
+
componentId: ComponentID.fromString('scope/comp1'),
|
|
52
|
+
isAuto: true,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'bar',
|
|
56
|
+
version: '2',
|
|
57
|
+
lifecycleType: 'runtime',
|
|
58
|
+
componentId: ComponentID.fromString('scope/comp1'),
|
|
59
|
+
isAuto: true,
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
expect(outdatedPkgs).toStrictEqual([
|
|
65
|
+
{
|
|
66
|
+
currentRange: '1',
|
|
67
|
+
name: 'foo',
|
|
68
|
+
source: 'rootPolicy',
|
|
69
|
+
targetField: 'dependencies',
|
|
70
|
+
variantPattern: null,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
componentId: ComponentID.fromString('scope/comp1'),
|
|
74
|
+
currentRange: '2',
|
|
75
|
+
isAuto: true,
|
|
76
|
+
name: 'bar',
|
|
77
|
+
source: 'component-model',
|
|
78
|
+
targetField: 'dependencies',
|
|
79
|
+
},
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { ComponentID } from '@teambit/component-id';
|
|
2
|
+
import { ManifestDependenciesKeysNames } from './manifest';
|
|
3
|
+
import { VariantPolicyConfigObject, VariantPolicyEntryValue, WorkspacePolicy } from './policy';
|
|
4
|
+
import { DependencyLifecycleType } from './dependencies/dependency';
|
|
5
|
+
import { KEY_NAME_BY_LIFECYCLE_TYPE } from './dependencies';
|
|
6
|
+
|
|
7
|
+
export type CurrentPkgSource =
|
|
8
|
+
// the variants section of "workspace.jsonc"
|
|
9
|
+
| 'variants'
|
|
10
|
+
// these are dependencies set via "bit deps set" or "component.json"
|
|
11
|
+
| 'component'
|
|
12
|
+
// these are dependencies from the dependencies policy in "workspace.jsonc"
|
|
13
|
+
| 'rootPolicy'
|
|
14
|
+
// these are dependencies stored in the component object (snapped/tagged version)
|
|
15
|
+
| 'component-model';
|
|
16
|
+
|
|
17
|
+
type CurrentPkg = {
|
|
18
|
+
name: string;
|
|
19
|
+
currentRange: string;
|
|
20
|
+
source: CurrentPkgSource;
|
|
21
|
+
variantPattern?: string | null;
|
|
22
|
+
componentId?: ComponentID;
|
|
23
|
+
isAuto?: boolean;
|
|
24
|
+
|
|
25
|
+
targetField: ManifestDependenciesKeysNames;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type OutdatedPkg = CurrentPkg & {
|
|
29
|
+
latestRange: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type ComponentModelVersion = {
|
|
33
|
+
name: string;
|
|
34
|
+
version: string;
|
|
35
|
+
componentId: ComponentID;
|
|
36
|
+
lifecycleType: DependencyLifecycleType;
|
|
37
|
+
isAuto: boolean;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get packages from root policy, variants, and component config files (component.json files).
|
|
42
|
+
*/
|
|
43
|
+
export function getAllPolicyPkgs({
|
|
44
|
+
rootPolicy,
|
|
45
|
+
variantPoliciesByPatterns,
|
|
46
|
+
componentPolicies,
|
|
47
|
+
componentModelVersions,
|
|
48
|
+
}: {
|
|
49
|
+
rootPolicy: WorkspacePolicy;
|
|
50
|
+
variantPoliciesByPatterns: Record<string, VariantPolicyConfigObject>;
|
|
51
|
+
componentPolicies: Array<{ componentId: ComponentID; policy: any }>;
|
|
52
|
+
componentModelVersions: ComponentModelVersion[];
|
|
53
|
+
}): CurrentPkg[] {
|
|
54
|
+
const pkgsFromPolicies = getPkgsFromRootPolicy(rootPolicy);
|
|
55
|
+
const pkgsNamesFromPolicies = new Set(pkgsFromPolicies.map(({ name }) => name));
|
|
56
|
+
return [
|
|
57
|
+
...pkgsFromPolicies,
|
|
58
|
+
...getPkgsFromVariants(variantPoliciesByPatterns),
|
|
59
|
+
...getPkgsFromComponents(componentPolicies),
|
|
60
|
+
...componentModelVersions
|
|
61
|
+
.filter(({ name }) => !pkgsNamesFromPolicies.has(name))
|
|
62
|
+
.map((componentDep) => ({
|
|
63
|
+
name: componentDep.name,
|
|
64
|
+
currentRange: componentDep.version,
|
|
65
|
+
source: 'component-model' as const,
|
|
66
|
+
isAuto: componentDep.isAuto,
|
|
67
|
+
componentId: componentDep.componentId,
|
|
68
|
+
targetField: KEY_NAME_BY_LIFECYCLE_TYPE[componentDep.lifecycleType] as ManifestDependenciesKeysNames,
|
|
69
|
+
})),
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getPkgsFromRootPolicy(rootPolicy: WorkspacePolicy): CurrentPkg[] {
|
|
74
|
+
return rootPolicy.entries.map((entry) => ({
|
|
75
|
+
name: entry.dependencyId,
|
|
76
|
+
currentRange: entry.value.version,
|
|
77
|
+
source: 'rootPolicy',
|
|
78
|
+
variantPattern: null as string | null,
|
|
79
|
+
targetField: KEY_NAME_BY_LIFECYCLE_TYPE[entry.lifecycleType] as ManifestDependenciesKeysNames,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getPkgsFromVariants(variantPoliciesByPatterns: Record<string, VariantPolicyConfigObject>): CurrentPkg[] {
|
|
84
|
+
return Object.entries(variantPoliciesByPatterns)
|
|
85
|
+
.filter(([, variant]) => variant != null)
|
|
86
|
+
.map(([variantPattern, variant]) => {
|
|
87
|
+
return readAllDependenciesFromPolicyObject({ source: 'variants', variantPattern }, variant);
|
|
88
|
+
})
|
|
89
|
+
.flat();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function getPkgsFromComponents(
|
|
93
|
+
componentPolicies: Array<{ componentId: ComponentID; policy: VariantPolicyConfigObject }>
|
|
94
|
+
): CurrentPkg[] {
|
|
95
|
+
return componentPolicies
|
|
96
|
+
.map(({ componentId, policy }) => {
|
|
97
|
+
return readAllDependenciesFromPolicyObject({ source: 'component', componentId }, policy);
|
|
98
|
+
})
|
|
99
|
+
.flat();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function readAllDependenciesFromPolicyObject(
|
|
103
|
+
context: Pick<CurrentPkg, 'source' | 'componentId' | 'variantPattern'>,
|
|
104
|
+
policy: VariantPolicyConfigObject
|
|
105
|
+
): CurrentPkg[] {
|
|
106
|
+
if (!policy) return [];
|
|
107
|
+
const pkgs: CurrentPkg[] = [];
|
|
108
|
+
for (const targetField of [
|
|
109
|
+
'dependencies',
|
|
110
|
+
'devDependencies',
|
|
111
|
+
'peerDependencies',
|
|
112
|
+
] as ManifestDependenciesKeysNames[]) {
|
|
113
|
+
for (const [name, currentRange] of Object.entries(policy[targetField] ?? {})) {
|
|
114
|
+
if (currentRange !== '-') {
|
|
115
|
+
pkgs.push({
|
|
116
|
+
...context,
|
|
117
|
+
name,
|
|
118
|
+
currentRange:
|
|
119
|
+
typeof currentRange === 'string' ? currentRange : (currentRange as VariantPolicyEntryValue).version,
|
|
120
|
+
targetField,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return pkgs;
|
|
126
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { DependencyResolverAspect } from './dependency-resolver.aspect';
|
|
2
|
+
|
|
3
|
+
export type { UpdatedComponent } from './apply-updates';
|
|
4
|
+
export type { RawComponentState, ComponentsManifestsMap, RegistriesMap } from './types';
|
|
5
|
+
export { WorkspaceManifest, ComponentManifest } from './manifest';
|
|
6
|
+
export type { CreateFromComponentsOptions, ManifestDependenciesObject } from './manifest';
|
|
7
|
+
export { Registries, Registry } from './registry';
|
|
8
|
+
export type {
|
|
9
|
+
InstallationContext,
|
|
10
|
+
PackageImportMethod,
|
|
11
|
+
PackageManager,
|
|
12
|
+
PackageManagerInstallOptions,
|
|
13
|
+
PackageManagerResolveRemoteVersionOptions,
|
|
14
|
+
ResolvedPackageVersion,
|
|
15
|
+
} from './package-manager';
|
|
16
|
+
export type {
|
|
17
|
+
DependencyResolverMain,
|
|
18
|
+
DependencyResolverWorkspaceConfig,
|
|
19
|
+
DependencyResolverVariantConfig,
|
|
20
|
+
MergedOutdatedPkg,
|
|
21
|
+
NodeLinker,
|
|
22
|
+
} from './dependency-resolver.main.runtime';
|
|
23
|
+
export { NPM_REGISTRY, BIT_CLOUD_REGISTRY } from './dependency-resolver.main.runtime';
|
|
24
|
+
export type {
|
|
25
|
+
ProxyConfig as PackageManagerProxyConfig,
|
|
26
|
+
NetworkConfig as PackageManagerNetworkConfig,
|
|
27
|
+
} from './dependency-resolver.main.runtime';
|
|
28
|
+
export { DependencyList, BaseDependency, ComponentDependency, KEY_NAME_BY_LIFECYCLE_TYPE } from './dependencies';
|
|
29
|
+
export type {
|
|
30
|
+
DependencyLifecycleType,
|
|
31
|
+
WorkspaceDependencyLifecycleType,
|
|
32
|
+
DependencyFactory,
|
|
33
|
+
SerializedDependency,
|
|
34
|
+
Dependency,
|
|
35
|
+
SemverVersion,
|
|
36
|
+
DependenciesManifest,
|
|
37
|
+
} from './dependencies';
|
|
38
|
+
export { WorkspacePolicy, VariantPolicy, EnvPolicy } from './policy';
|
|
39
|
+
export type {
|
|
40
|
+
WorkspacePolicyEntry,
|
|
41
|
+
WorkspacePolicyConfigObject,
|
|
42
|
+
VariantPolicyConfigObject,
|
|
43
|
+
Policy,
|
|
44
|
+
PolicySemver,
|
|
45
|
+
PolicyConfigKeys,
|
|
46
|
+
PolicyConfigKeysNames,
|
|
47
|
+
PolicyEntry,
|
|
48
|
+
SerializedVariantPolicy,
|
|
49
|
+
WorkspacePolicyConfigKeysNames,
|
|
50
|
+
EnvPolicyConfigObject,
|
|
51
|
+
} from './policy';
|
|
52
|
+
export { DependencyLinker } from './dependency-linker';
|
|
53
|
+
export type {
|
|
54
|
+
CoreAspectLinkResult,
|
|
55
|
+
LinkDetail,
|
|
56
|
+
LinkResults,
|
|
57
|
+
LinkingOptions,
|
|
58
|
+
DepsLinkedToEnvResult,
|
|
59
|
+
NestedNMDepsLinksResult,
|
|
60
|
+
LinkToDirResult,
|
|
61
|
+
} from './dependency-linker';
|
|
62
|
+
export { DependencyInstaller } from './dependency-installer';
|
|
63
|
+
export type { GetComponentManifestsOptions, InstallOptions, InstallArgs } from './dependency-installer';
|
|
64
|
+
export type { DependencyDetector, FileContext } from './dependency-detector';
|
|
65
|
+
export type { DependencySource, VariantPolicyEntry } from './policy/variant-policy/variant-policy';
|
|
66
|
+
export type { OutdatedPkg } from './get-all-policy-pkgs';
|
|
67
|
+
export { extendWithComponentsFromDir } from './extend-with-components-from-dir';
|
|
68
|
+
export { isRange } from './manifest/deduping/hoist-dependencies';
|
|
69
|
+
export type { DependencyEnv } from './dependency-env';
|
|
70
|
+
export { DependencyResolverAspect as default, DependencyResolverAspect };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/* eslint-disable no-empty */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
4
|
+
import { Capsule } from '@teambit/isolator';
|
|
5
|
+
import { Logger } from '@teambit/logger';
|
|
6
|
+
import { pipeOutput } from '@teambit/legacy/dist/utils/child_process';
|
|
7
|
+
import createSymlinkOrCopy from '@teambit/legacy/dist/utils/fs/create-symlink-or-copy';
|
|
8
|
+
import { EventEmitter } from 'events';
|
|
9
|
+
import execa from 'execa';
|
|
10
|
+
import fs from 'fs-extra';
|
|
11
|
+
import mapSeries from 'p-map-series';
|
|
12
|
+
import path, { join } from 'path';
|
|
13
|
+
|
|
14
|
+
export default class PackageManager {
|
|
15
|
+
private emitter = new EventEmitter();
|
|
16
|
+
constructor(readonly packageManagerName: string, readonly logger: Logger) {}
|
|
17
|
+
|
|
18
|
+
get name() {
|
|
19
|
+
return this.packageManagerName;
|
|
20
|
+
}
|
|
21
|
+
async checkIfFileExistsInCapsule(capsule: Capsule, file: string) {
|
|
22
|
+
const pathToFile = join(capsule.wrkDir, file);
|
|
23
|
+
try {
|
|
24
|
+
await capsule.fs.promises.access(pathToFile);
|
|
25
|
+
return true;
|
|
26
|
+
} catch (e: any) {}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async removeLockFilesInCapsule(capsule: Capsule) {
|
|
31
|
+
async function safeUnlink(toRemove: string) {
|
|
32
|
+
try {
|
|
33
|
+
await capsule.fs.promises.unlink(join(capsule.wrkDir, toRemove));
|
|
34
|
+
} catch (e: any) {}
|
|
35
|
+
}
|
|
36
|
+
await safeUnlink('yarn.lock');
|
|
37
|
+
await safeUnlink('package-lock.json');
|
|
38
|
+
}
|
|
39
|
+
async capsulesInstall(capsules: Capsule[], opts: {} = {}) {
|
|
40
|
+
const packageManager = this.packageManagerName;
|
|
41
|
+
const longProcessLogger = this.logger.createLongProcessLogger('installing capsules', capsules.length);
|
|
42
|
+
if (packageManager === 'npm' || packageManager === 'yarn' || packageManager === 'pnpm') {
|
|
43
|
+
// Don't run them in parallel (Promise.all), the package-manager doesn't handle it well.
|
|
44
|
+
await mapSeries(capsules, async (capsule) => {
|
|
45
|
+
const componentId = capsule.component.id.toString();
|
|
46
|
+
longProcessLogger.logProgress(componentId);
|
|
47
|
+
// TODO: remove this hack once harmony supports ownExtensionName
|
|
48
|
+
const execOptions = { cwd: capsule.wrkDir };
|
|
49
|
+
const getExecCall = () => {
|
|
50
|
+
switch (packageManager) {
|
|
51
|
+
case 'npm':
|
|
52
|
+
return execa('npm', ['install', '--no-package-lock'], execOptions);
|
|
53
|
+
case 'yarn':
|
|
54
|
+
return execa('yarn', [], execOptions);
|
|
55
|
+
case 'pnpm':
|
|
56
|
+
return execa('pnpm', ['install'], execOptions);
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(`unsupported package manager ${packageManager}`);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const installProc = getExecCall();
|
|
62
|
+
this.logger.info(`${componentId}, ${packageManager === 'npm' ? '$ npm install --no-package-lock' : '$ yarn'}`); // TODO: better
|
|
63
|
+
installProc.stdout!.on('data', (d) => this.logger.info(`${componentId}, ${d.toString()}`));
|
|
64
|
+
installProc.stderr!.on('data', (d) => this.logger.warn(`${componentId}, ${d.toString()}`));
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
66
|
+
installProc.on('error', (e) => {
|
|
67
|
+
console.log('error:', e); // eslint-disable-line no-console
|
|
68
|
+
this.logger.error(`${componentId}, ${e}`);
|
|
69
|
+
});
|
|
70
|
+
await installProc;
|
|
71
|
+
linkBitLegacyInCapsule(capsule);
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
throw new Error(`unsupported package manager ${packageManager}`);
|
|
75
|
+
}
|
|
76
|
+
longProcessLogger.end();
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async runInstallInFolder(folder: string, opts: {} = {}): Promise<void> {
|
|
81
|
+
const packageManager = this.packageManagerName;
|
|
82
|
+
if (packageManager === 'yarn') {
|
|
83
|
+
const child = execa('yarn', [], { cwd: folder, stdio: 'pipe' });
|
|
84
|
+
pipeOutput(child);
|
|
85
|
+
await child;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (packageManager === 'npm') {
|
|
89
|
+
const child = execa('npm', ['install'], { cwd: folder, stdio: 'pipe' });
|
|
90
|
+
this.logger.info(`${folder} $ npm install`);
|
|
91
|
+
await new Promise((resolve, reject) => {
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
child.stdout.on('data', (d) => this.logger.info(`${folder} ${d.toString()}`));
|
|
94
|
+
// @ts-ignore
|
|
95
|
+
child.stderr.on('data', (d) => this.logger.warn(`${folder} ${d.toString()}`));
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
97
|
+
child.on('error', (e) => {
|
|
98
|
+
reject(e);
|
|
99
|
+
});
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
101
|
+
child.on('close', (exitStatus) => {
|
|
102
|
+
if (exitStatus) {
|
|
103
|
+
reject(new Error(`${folder}`));
|
|
104
|
+
} else {
|
|
105
|
+
resolve(null);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`unsupported package manager ${packageManager}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function linkBitLegacyInCapsule(capsule) {
|
|
116
|
+
const bitLegacyPath = path.join(capsule.wrkDir, './node_modules/@teambit/legacy');
|
|
117
|
+
const getLocalBitLegacyPath = () => {
|
|
118
|
+
const pathOutsideNodeModules = path.join(__dirname, '../..');
|
|
119
|
+
if (pathOutsideNodeModules.endsWith(`${path.sep}dist`)) {
|
|
120
|
+
return pathOutsideNodeModules;
|
|
121
|
+
}
|
|
122
|
+
throw new Error('unable to link @teambit/legacy to the capsule, the location of @teambit/legacy is unknown');
|
|
123
|
+
};
|
|
124
|
+
const localBitLegacyPath = getLocalBitLegacyPath();
|
|
125
|
+
// if there are no deps, sometimes the node_modules folder is not created
|
|
126
|
+
// and we need it in order to perform the linking
|
|
127
|
+
try {
|
|
128
|
+
capsule.fs.mkdirSync('node_modules');
|
|
129
|
+
} catch (e: any) {
|
|
130
|
+
// fail silently - we only need to create it if it doesn't already exist
|
|
131
|
+
}
|
|
132
|
+
// we use fs directly here rather than the capsule.fs because there are some edge cases
|
|
133
|
+
// that the capusle fs does not deal with well (eg. identifying and deleting
|
|
134
|
+
// a symlink rather than the what the symlink links to)
|
|
135
|
+
fs.removeSync(bitLegacyPath);
|
|
136
|
+
createSymlinkOrCopy(localBitLegacyPath, bitLegacyPath);
|
|
137
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { PeerDependencyIssuesByProjects } from '@pnpm/core';
|
|
2
|
+
import { PeerDependencyRules, ProjectManifest } from '@pnpm/types';
|
|
3
|
+
import { ComponentMap } from '@teambit/component';
|
|
4
|
+
import { Registries } from './registry';
|
|
5
|
+
import { DepsFilterFn } from './manifest';
|
|
6
|
+
import { NetworkConfig, ProxyConfig } from './dependency-resolver.main.runtime';
|
|
7
|
+
|
|
8
|
+
export { PeerDependencyIssuesByProjects };
|
|
9
|
+
|
|
10
|
+
export type PackageImportMethod = 'auto' | 'hardlink' | 'copy' | 'clone';
|
|
11
|
+
|
|
12
|
+
export type PackageManagerInstallOptions = {
|
|
13
|
+
cacheRootDir?: string;
|
|
14
|
+
/**
|
|
15
|
+
* decide whether to dedup dependencies.
|
|
16
|
+
*/
|
|
17
|
+
dedupe?: boolean;
|
|
18
|
+
|
|
19
|
+
copyPeerToRuntimeOnRoot?: boolean;
|
|
20
|
+
|
|
21
|
+
copyPeerToRuntimeOnComponents?: boolean;
|
|
22
|
+
|
|
23
|
+
excludeLinksFromLockfile?: boolean;
|
|
24
|
+
|
|
25
|
+
installPeersFromEnvs?: boolean;
|
|
26
|
+
|
|
27
|
+
dependencyFilterFn?: DepsFilterFn;
|
|
28
|
+
|
|
29
|
+
overrides?: Record<string, string>;
|
|
30
|
+
|
|
31
|
+
lockfileOnly?: boolean;
|
|
32
|
+
|
|
33
|
+
nodeLinker?: 'hoisted' | 'isolated';
|
|
34
|
+
|
|
35
|
+
packageManagerConfigRootDir?: string;
|
|
36
|
+
|
|
37
|
+
packageImportMethod?: PackageImportMethod;
|
|
38
|
+
|
|
39
|
+
rootComponents?: boolean;
|
|
40
|
+
|
|
41
|
+
rootComponentsForCapsules?: boolean;
|
|
42
|
+
|
|
43
|
+
useNesting?: boolean;
|
|
44
|
+
|
|
45
|
+
keepExistingModulesDir?: boolean;
|
|
46
|
+
|
|
47
|
+
sideEffectsCache?: boolean;
|
|
48
|
+
|
|
49
|
+
engineStrict?: boolean;
|
|
50
|
+
|
|
51
|
+
nodeVersion?: string;
|
|
52
|
+
|
|
53
|
+
peerDependencyRules?: PeerDependencyRules;
|
|
54
|
+
|
|
55
|
+
includeOptionalDeps?: boolean;
|
|
56
|
+
|
|
57
|
+
updateAll?: boolean;
|
|
58
|
+
|
|
59
|
+
hidePackageManagerOutput?: boolean;
|
|
60
|
+
|
|
61
|
+
pruneNodeModules?: boolean;
|
|
62
|
+
|
|
63
|
+
hasRootComponents?: boolean;
|
|
64
|
+
|
|
65
|
+
neverBuiltDependencies?: string[];
|
|
66
|
+
|
|
67
|
+
preferOffline?: boolean;
|
|
68
|
+
|
|
69
|
+
nmSelfReferences?: boolean;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* e.g. when running `bit install` through the web or the IDE, not from the CLI.
|
|
73
|
+
*/
|
|
74
|
+
optimizeReportForNonTerminal?: boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Sets the frequency of updating the progress output in milliseconds.
|
|
78
|
+
* E.g., if this is set to 1000, then the progress will be updated every second.
|
|
79
|
+
*/
|
|
80
|
+
throttleProgress?: number;
|
|
81
|
+
|
|
82
|
+
hideProgressPrefix?: boolean;
|
|
83
|
+
|
|
84
|
+
hideLifecycleOutput?: boolean;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Do installation using lockfile only. Ignore the component manifests.
|
|
88
|
+
*/
|
|
89
|
+
ignorePackageManifest?: boolean;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* When enabled, installation by the package manager will be skipped
|
|
93
|
+
* but all the options will be calculated and the rebuild function will be returned.
|
|
94
|
+
* We use this option for a performance optimization in Ripple CI.
|
|
95
|
+
*/
|
|
96
|
+
dryRun?: boolean;
|
|
97
|
+
|
|
98
|
+
dedupeInjectedDeps?: boolean;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export type PackageManagerGetPeerDependencyIssuesOptions = PackageManagerInstallOptions;
|
|
102
|
+
|
|
103
|
+
export type ResolvedPackageVersion = {
|
|
104
|
+
packageName: string;
|
|
105
|
+
version: string | null;
|
|
106
|
+
wantedRange?: string;
|
|
107
|
+
isSemver: boolean;
|
|
108
|
+
resolvedVia?: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export type PackageManagerResolveRemoteVersionOptions = {
|
|
112
|
+
rootDir: string;
|
|
113
|
+
cacheRootDir?: string;
|
|
114
|
+
packageManagerConfigRootDir?: string;
|
|
115
|
+
// fetchToCache?: boolean;
|
|
116
|
+
// update?: boolean;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export interface InstallationContext {
|
|
120
|
+
rootDir: string;
|
|
121
|
+
manifests: Record<string, ProjectManifest>;
|
|
122
|
+
componentDirectoryMap: ComponentMap<string>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface PackageManager {
|
|
126
|
+
/**
|
|
127
|
+
* Name of the package manager
|
|
128
|
+
*/
|
|
129
|
+
name: string;
|
|
130
|
+
/**
|
|
131
|
+
* install dependencies
|
|
132
|
+
* @param componentDirectoryMap
|
|
133
|
+
*/
|
|
134
|
+
install(
|
|
135
|
+
context: InstallationContext,
|
|
136
|
+
options: PackageManagerInstallOptions
|
|
137
|
+
): Promise<{ dependenciesChanged: boolean }>;
|
|
138
|
+
|
|
139
|
+
pruneModules?(rootDir: string): Promise<void>;
|
|
140
|
+
|
|
141
|
+
resolveRemoteVersion(
|
|
142
|
+
packageName: string,
|
|
143
|
+
options: PackageManagerResolveRemoteVersionOptions
|
|
144
|
+
): Promise<ResolvedPackageVersion>;
|
|
145
|
+
|
|
146
|
+
getPeerDependencyIssues?(
|
|
147
|
+
rootDir: string,
|
|
148
|
+
manifests: Record<string, ProjectManifest>,
|
|
149
|
+
options: PackageManagerGetPeerDependencyIssuesOptions
|
|
150
|
+
): Promise<PeerDependencyIssuesByProjects>;
|
|
151
|
+
|
|
152
|
+
getInjectedDirs?(rootDir: string, componentDir: string, packageName: string): Promise<string[]>;
|
|
153
|
+
|
|
154
|
+
getRegistries?(): Promise<Registries>;
|
|
155
|
+
|
|
156
|
+
getProxyConfig?(): Promise<ProxyConfig>;
|
|
157
|
+
|
|
158
|
+
getNetworkConfig?(): Promise<NetworkConfig>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Specify if the package manager can be run with deduping on existing worksapce (which already contains root dependencies)
|
|
162
|
+
* again, with a different context.
|
|
163
|
+
* If the package manager is not capable of doing so, we want to disable the deduping.
|
|
164
|
+
*/
|
|
165
|
+
supportsDedupingOnExistingRoot?: () => boolean;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Returns "dependencies" entries for ".bit_roots".
|
|
169
|
+
* These entries tell the package manager from where to the local components should be installed.
|
|
170
|
+
*/
|
|
171
|
+
getWorkspaceDepsOfBitRoots(manifests: ProjectManifest[]): Record<string, string>;
|
|
172
|
+
|
|
173
|
+
findUsages?(depName: string, opts: { lockfileDir: string; depth?: number }): Promise<string>;
|
|
174
|
+
}
|