@teambit/dependencies 1.0.1233 → 1.0.1235
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/dependencies-loader/apply-overrides.spec.ts +85 -0
- package/dependencies-loader/apply-overrides.ts +51 -15
- package/dependencies-loader/dependencies-loader.ts +7 -1
- package/dependencies-loader/dependencies-versions-resolver.ts +2 -1
- package/dependencies-loader/overrides-dependencies.ts +5 -3
- package/dist/dependencies-loader/apply-overrides.d.ts +5 -1
- package/dist/dependencies-loader/apply-overrides.js +66 -11
- package/dist/dependencies-loader/apply-overrides.js.map +1 -1
- package/dist/dependencies-loader/apply-overrides.spec.d.ts +1 -0
- package/dist/dependencies-loader/apply-overrides.spec.js +143 -0
- package/dist/dependencies-loader/apply-overrides.spec.js.map +1 -0
- package/dist/dependencies-loader/dependencies-loader.d.ts +6 -1
- package/dist/dependencies-loader/dependencies-loader.js +7 -1
- package/dist/dependencies-loader/dependencies-loader.js.map +1 -1
- package/dist/dependencies-loader/dependencies-versions-resolver.js +8 -1
- package/dist/dependencies-loader/dependencies-versions-resolver.js.map +1 -1
- package/dist/dependencies-loader/overrides-dependencies.js +10 -2
- package/dist/dependencies-loader/overrides-dependencies.js.map +1 -1
- package/dist/dependencies.main.runtime.d.ts +2 -1
- package/dist/dependencies.main.runtime.js +2 -2
- package/dist/dependencies.main.runtime.js.map +1 -1
- package/package.json +25 -25
- /package/dist/{preview-1792442853086.js → preview-1792532220087.js} +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { ComponentID } from '@teambit/component-id';
|
|
3
|
+
import { Dependency } from '@teambit/legacy.consumer-component';
|
|
4
|
+
import { ComponentOverrides } from '@teambit/legacy.consumer-config';
|
|
5
|
+
import type { DependencyResolverMain } from '@teambit/dependency-resolver';
|
|
6
|
+
import type { Logger } from '@teambit/logger';
|
|
7
|
+
import { ApplyOverrides } from './apply-overrides';
|
|
8
|
+
|
|
9
|
+
const noopLogger = { debug() {}, warn() {}, trace() {} } as unknown as Logger;
|
|
10
|
+
|
|
11
|
+
function createApplyOverrides(forcedDeps: Record<string, Record<string, string>>) {
|
|
12
|
+
const id = ComponentID.fromString('my-scope/my-env@0.0.1');
|
|
13
|
+
const component = { id, componentId: id, issues: undefined, overrides: new ComponentOverrides(forcedDeps) };
|
|
14
|
+
// no workspace, as in a bare scope
|
|
15
|
+
return new ApplyOverrides(component as any, {} as DependencyResolverMain, noopLogger);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('ApplyOverrides', () => {
|
|
19
|
+
describe('outside a workspace, a forced dependency that is a component dependency in another field', () => {
|
|
20
|
+
// e.g. a peer that an env sets for itself (in env.jsonc) is a runtime dependency of the env. the env of the env
|
|
21
|
+
// may set it as a peer, which moves the component dependency to the peers before the forced deps are added.
|
|
22
|
+
const peerDep = new Dependency(
|
|
23
|
+
ComponentID.fromString('my-scope/ui/button@1.0.0'),
|
|
24
|
+
[],
|
|
25
|
+
'@my-scope/ui.button',
|
|
26
|
+
'^1.0.0'
|
|
27
|
+
);
|
|
28
|
+
let result: ReturnType<ApplyOverrides['getDependenciesToAddManually']>;
|
|
29
|
+
before(() => {
|
|
30
|
+
const applyOverrides = createApplyOverrides({ dependencies: { '@my-scope/ui.button': '1.0.0' } });
|
|
31
|
+
applyOverrides.allDependencies = { dependencies: [], devDependencies: [], peerDependencies: [peerDep] };
|
|
32
|
+
result = applyOverrides.getDependenciesToAddManually(undefined, applyOverrides.allDependencies);
|
|
33
|
+
});
|
|
34
|
+
it('should resolve the package to the component, as the node_modules of a workspace would', () => {
|
|
35
|
+
expect(result?.components.dependencies).to.have.lengthOf(1);
|
|
36
|
+
expect(result?.components.dependencies[0].componentId.toString()).to.equal('my-scope/ui/button@1.0.0');
|
|
37
|
+
expect(result?.packages).to.deep.equal({});
|
|
38
|
+
});
|
|
39
|
+
it('should not set a version range on a runtime component dependency', () => {
|
|
40
|
+
expect(result?.components.dependencies[0].versionRange).to.be.undefined;
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
function createApplyOverridesWithPolicy({
|
|
46
|
+
installed,
|
|
47
|
+
inWorkspacePolicy,
|
|
48
|
+
}: {
|
|
49
|
+
installed?: string;
|
|
50
|
+
inWorkspacePolicy?: string;
|
|
51
|
+
}) {
|
|
52
|
+
const applyOverrides = Object.create(ApplyOverrides.prototype);
|
|
53
|
+
applyOverrides.depsResolver = {
|
|
54
|
+
getWorkspacePolicyManifest: () => ({ dependencies: inWorkspacePolicy ? { 'my-pkg': inWorkspacePolicy } : {} }),
|
|
55
|
+
};
|
|
56
|
+
applyOverrides._resolvePackageData = () => (installed ? { concreteVersion: installed } : undefined);
|
|
57
|
+
return applyOverrides;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe('ApplyOverrides.resolveEnvPeerDepVersion()', () => {
|
|
61
|
+
it('should prefer the installed version by default', () => {
|
|
62
|
+
const applyOverrides = createApplyOverridesWithPolicy({ installed: '2.0.0', inWorkspacePolicy: '3.0.1' });
|
|
63
|
+
expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg')).to.equal('2.0.0');
|
|
64
|
+
});
|
|
65
|
+
it('should prefer the workspace policy when asked to, as the installed version could be outdated', () => {
|
|
66
|
+
const applyOverrides = createApplyOverridesWithPolicy({ installed: '2.0.0', inWorkspacePolicy: '3.0.1' });
|
|
67
|
+
expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg', true)).to.equal('3.0.1');
|
|
68
|
+
});
|
|
69
|
+
it('should prefer the installed version when it satisfies the workspace policy range', () => {
|
|
70
|
+
const applyOverrides = createApplyOverridesWithPolicy({ installed: '18.2.0', inWorkspacePolicy: '^18.0.0' });
|
|
71
|
+
expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg', true)).to.equal('18.2.0');
|
|
72
|
+
});
|
|
73
|
+
it('should take the minimum version of the workspace policy range when the installed one is outdated', () => {
|
|
74
|
+
const applyOverrides = createApplyOverridesWithPolicy({ installed: '17.0.0', inWorkspacePolicy: '^18.1.0' });
|
|
75
|
+
expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg', true)).to.equal('18.1.0');
|
|
76
|
+
});
|
|
77
|
+
it('should keep an unconstrained workspace policy range as is', () => {
|
|
78
|
+
const applyOverrides = createApplyOverridesWithPolicy({ inWorkspacePolicy: '*' });
|
|
79
|
+
expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg', true)).to.equal('*');
|
|
80
|
+
});
|
|
81
|
+
it('should fall back to the installed version when the workspace policy does not have the package', () => {
|
|
82
|
+
const applyOverrides = createApplyOverridesWithPolicy({ installed: '2.0.0' });
|
|
83
|
+
expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg', true)).to.equal('2.0.0');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import semver from 'semver';
|
|
2
3
|
import type { ComponentID } from '@teambit/component-id';
|
|
3
4
|
import { ComponentIdList } from '@teambit/component-id';
|
|
4
5
|
import { cloneDeep, difference, forEach, isEmpty, pick, pickBy, uniq } from 'lodash';
|
|
@@ -14,6 +15,7 @@ import type { ResolvedPackageData } from '../resolve-pkg-data';
|
|
|
14
15
|
import { resolvePackageData } from '../resolve-pkg-data';
|
|
15
16
|
import type { Workspace } from '@teambit/workspace';
|
|
16
17
|
import type { DependencyResolverMain } from '@teambit/dependency-resolver';
|
|
18
|
+
import { isPlusVersion, resolvePlusVersion } from '@teambit/dependency-resolver';
|
|
17
19
|
import type { Consumer } from '@teambit/legacy.consumer';
|
|
18
20
|
import type { ComponentMap } from '@teambit/legacy.bit-map';
|
|
19
21
|
import type { Logger } from '@teambit/logger';
|
|
@@ -245,7 +247,9 @@ export class ApplyOverrides {
|
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
private async loadAutoDetectOverrides() {
|
|
248
|
-
|
|
250
|
+
// outside a workspace, they're calculated by the caller (if at all) and set before this runs
|
|
251
|
+
if (!this.workspace) return;
|
|
252
|
+
this.autoDetectOverrides = await this.workspace.getAutoDetectOverrides(
|
|
249
253
|
this.component.extensions,
|
|
250
254
|
this.component.id,
|
|
251
255
|
this.component.files,
|
|
@@ -290,12 +294,30 @@ export class ApplyOverrides {
|
|
|
290
294
|
|
|
291
295
|
private _getComponentIdToAdd(
|
|
292
296
|
dependency: string,
|
|
293
|
-
versionRange: string
|
|
294
|
-
|
|
297
|
+
versionRange: string,
|
|
298
|
+
depField: string
|
|
299
|
+
): { componentId?: ComponentID; packageName?: string; versionRange?: string } {
|
|
300
|
+
if (!this.consumer) {
|
|
301
|
+
// a scope has no node_modules to resolve the package from. if it's a component dependency, use it. otherwise, a
|
|
302
|
+
// forced component dependency (e.g. an env's own peer, which is a runtime dep of the env) is added as a package
|
|
303
|
+
// and then dropped in favor of the component dependency, which may be in a different field.
|
|
304
|
+
const compDep = this.findComponentDepByPackageName(dependency);
|
|
305
|
+
if (compDep) {
|
|
306
|
+
// same as the workspace (see updateDependenciesVersions), only a peer component dependency keeps its range
|
|
307
|
+
const range = depField === 'peerDependencies' ? versionRange : undefined;
|
|
308
|
+
return { componentId: compDep.id, packageName: dependency, versionRange: range };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
295
311
|
const packageData = this._resolvePackageData(dependency);
|
|
296
312
|
return { componentId: packageData?.componentId, packageName: packageData?.name, versionRange };
|
|
297
313
|
}
|
|
298
314
|
|
|
315
|
+
private findComponentDepByPackageName(packageName: string): Dependency | undefined {
|
|
316
|
+
const { dependencies, devDependencies, peerDependencies } = this.allDependencies;
|
|
317
|
+
const isMatch = (dep: Dependency) => dep.packageName === packageName;
|
|
318
|
+
return dependencies.find(isMatch) || devDependencies.find(isMatch) || peerDependencies.find(isMatch);
|
|
319
|
+
}
|
|
320
|
+
|
|
299
321
|
getDependenciesToAddManually(
|
|
300
322
|
packageJson: Record<string, any> | null | undefined,
|
|
301
323
|
existingDependencies: AllDependencies
|
|
@@ -309,7 +331,7 @@ export class ApplyOverrides {
|
|
|
309
331
|
if (!overrides[depField]) return;
|
|
310
332
|
Object.keys(overrides[depField]).forEach((dependency) => {
|
|
311
333
|
const dependencyValue = overrides[depField][dependency];
|
|
312
|
-
const componentData = this._getComponentIdToAdd(dependency, dependencyValue);
|
|
334
|
+
const componentData = this._getComponentIdToAdd(dependency, dependencyValue, depField);
|
|
313
335
|
if (componentData?.componentId) {
|
|
314
336
|
if (componentData.componentId.isEqualWithoutVersion(this.componentId)) {
|
|
315
337
|
this.logger.warn(
|
|
@@ -589,10 +611,7 @@ export class ApplyOverrides {
|
|
|
589
611
|
|
|
590
612
|
private isPackageAutoDetected(pkgName: string, originallyExists: string[], missingPackages: string[]): boolean {
|
|
591
613
|
// Check component dependencies
|
|
592
|
-
const existsInAnyCompDeps =
|
|
593
|
-
this.allDependencies.dependencies.some((dep) => dep.packageName === pkgName) ||
|
|
594
|
-
this.allDependencies.devDependencies.some((dep) => dep.packageName === pkgName) ||
|
|
595
|
-
this.allDependencies.peerDependencies.some((dep) => dep.packageName === pkgName);
|
|
614
|
+
const existsInAnyCompDeps = Boolean(this.findComponentDepByPackageName(pkgName));
|
|
596
615
|
|
|
597
616
|
// Check originAllPackagesDependencies instead of allPackagesDependencies
|
|
598
617
|
// as it might be already removed at this point if it was set with "-" in runtime/dev
|
|
@@ -716,7 +735,11 @@ export class ApplyOverrides {
|
|
|
716
735
|
comp.versionRange = pkgVal;
|
|
717
736
|
this.allDependencies.peerDependencies.push(comp);
|
|
718
737
|
} else {
|
|
719
|
-
|
|
738
|
+
// a package has no separate version and range, so a "+" placeholder is resolved here.
|
|
739
|
+
// a component dep keeps it in the versionRange, and it's resolved when generating the package.json
|
|
740
|
+
this.allPackagesDependencies[key][pkgName] = isPlusVersion(pkgVal)
|
|
741
|
+
? resolvePlusVersion(pkgVal, this.resolveEnvPeerDepVersion(pkgName, true))
|
|
742
|
+
: pkgVal;
|
|
720
743
|
}
|
|
721
744
|
|
|
722
745
|
if (existsInCompsPeerDeps) {
|
|
@@ -750,11 +773,11 @@ export class ApplyOverrides {
|
|
|
750
773
|
});
|
|
751
774
|
const resolvedEnvPolicyManifest = Object.keys(envPolicyManifest).reduce((acc, pkgName) => {
|
|
752
775
|
const version = envPolicyManifest[pkgName];
|
|
753
|
-
if (version
|
|
776
|
+
if (!isPlusVersion(version)) {
|
|
754
777
|
acc[pkgName] = version;
|
|
755
778
|
return acc;
|
|
756
779
|
}
|
|
757
|
-
acc[pkgName] = this.resolveEnvPeerDepVersion(pkgName);
|
|
780
|
+
acc[pkgName] = resolvePlusVersion(version, this.resolveEnvPeerDepVersion(pkgName));
|
|
758
781
|
return acc;
|
|
759
782
|
}, {});
|
|
760
783
|
// TODO: handle component deps once we support peers between components
|
|
@@ -765,21 +788,34 @@ export class ApplyOverrides {
|
|
|
765
788
|
}
|
|
766
789
|
|
|
767
790
|
/**
|
|
768
|
-
* in the env.jsonc file, a policy-peer package can have `+` sign in the version. it means that it should be resolved
|
|
791
|
+
* in the env.jsonc file, a policy-peer package can have `+` sign (or `+^`/`+~`) in the version. it means that it should be resolved
|
|
769
792
|
* from the workspace. whatever version is installed/imported in the workspace, it should be used here.
|
|
770
793
|
* in some cases, the package is not installed in the workspace, for example, the env is now imported without the
|
|
771
794
|
* dep. so the dep is not in the node_modules.
|
|
772
795
|
* strategy should be: .bitmap, workspace.jsonc, then model.
|
|
773
796
|
* it's not in .bitmap, otherwise, it was linked and `_resolvePackageData` would have found it.
|
|
774
797
|
* so either, it's in the workspace.jsonc or in the model.
|
|
798
|
+
* @param preferWorkspacePolicy check the workspace.jsonc before what's installed. needed for a package that the
|
|
799
|
+
* component gets with a plus version. what's installed for the component was installed according to the version it
|
|
800
|
+
* had before, so it doesn't follow an upgrade in the workspace.jsonc (e.g. by "bit update").
|
|
775
801
|
*/
|
|
776
|
-
private resolveEnvPeerDepVersion(pkgName: string): string {
|
|
802
|
+
private resolveEnvPeerDepVersion(pkgName: string, preferWorkspacePolicy = false): string {
|
|
803
|
+
const wsPolicy = this.depsResolver.getWorkspacePolicyManifest();
|
|
804
|
+
const wsVersion = wsPolicy?.dependencies?.[pkgName] || wsPolicy?.peerDependencies?.[pkgName];
|
|
777
805
|
const resolved = this._resolvePackageData(pkgName);
|
|
806
|
+
if (preferWorkspacePolicy && wsVersion) {
|
|
807
|
+
// the workspace.jsonc has usually a range. the plus version needs a concrete version to add its own prefix to
|
|
808
|
+
if (resolved?.concreteVersion && semver.satisfies(resolved.concreteVersion, wsVersion)) {
|
|
809
|
+
return resolved.concreteVersion;
|
|
810
|
+
}
|
|
811
|
+
const validRange = semver.validRange(wsVersion);
|
|
812
|
+
// an unconstrained range (e.g. "*") has no meaningful minimum, keep it as is
|
|
813
|
+
if (!validRange || validRange === '*') return wsVersion;
|
|
814
|
+
return semver.minVersion(wsVersion)?.version || wsVersion;
|
|
815
|
+
}
|
|
778
816
|
if (resolved && resolved.concreteVersion) {
|
|
779
817
|
return resolved.concreteVersion;
|
|
780
818
|
}
|
|
781
|
-
const wsPolicy = this.depsResolver.getWorkspacePolicyManifest();
|
|
782
|
-
const wsVersion = wsPolicy?.dependencies?.[pkgName] || wsPolicy?.peerDependencies?.[pkgName];
|
|
783
819
|
if (wsVersion) {
|
|
784
820
|
return wsVersion;
|
|
785
821
|
}
|
|
@@ -15,6 +15,7 @@ import { DependencyResolverAspect } from '@teambit/dependency-resolver';
|
|
|
15
15
|
import type { DevFilesMain } from '@teambit/dev-files';
|
|
16
16
|
import type { Logger } from '@teambit/logger';
|
|
17
17
|
import type { AspectLoaderMain } from '@teambit/aspect-loader';
|
|
18
|
+
import type { DependenciesOverridesData } from '@teambit/legacy.consumer-config';
|
|
18
19
|
import { DependenciesData } from './dependencies-data';
|
|
19
20
|
import { updateDependenciesVersions } from './dependencies-versions-resolver';
|
|
20
21
|
import type { DebugDependencies } from './auto-detect-deps';
|
|
@@ -62,12 +63,17 @@ export class DependenciesLoader {
|
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
/**
|
|
67
|
+
* `autoDetectOverrides` are the non-force policy entries (versions for dependencies that were detected). a workspace
|
|
68
|
+
* calculates them on its own, a scope gets them from the caller.
|
|
69
|
+
*/
|
|
70
|
+
async loadFromScope(dependenciesData: Partial<DependenciesData>, autoDetectOverrides?: DependenciesOverridesData) {
|
|
66
71
|
const applyOverrides = new ApplyOverrides(this.component, this.depsResolver, this.logger);
|
|
67
72
|
const { allDependencies, allPackagesDependencies, issues } = dependenciesData;
|
|
68
73
|
if (allDependencies) applyOverrides.allDependencies = allDependencies;
|
|
69
74
|
if (allPackagesDependencies) applyOverrides.allPackagesDependencies = allPackagesDependencies;
|
|
70
75
|
if (issues) applyOverrides.issues = issues;
|
|
76
|
+
if (autoDetectOverrides) applyOverrides.autoDetectOverrides = autoDetectOverrides;
|
|
71
77
|
const results = await applyOverrides.getDependenciesData();
|
|
72
78
|
this.setDependenciesDataOnComponent(results.dependenciesData, results.overridesDependencies);
|
|
73
79
|
}
|
|
@@ -8,6 +8,7 @@ import { isEmpty } from 'lodash';
|
|
|
8
8
|
import type { Dependency, Dependencies, ConsumerComponent as Component } from '@teambit/legacy.consumer-component';
|
|
9
9
|
import type { ExtensionDataEntry, ExtensionDataList } from '@teambit/legacy.extension-data';
|
|
10
10
|
import type { DependencyResolverMain } from '@teambit/dependency-resolver';
|
|
11
|
+
import { isPlusVersion } from '@teambit/dependency-resolver';
|
|
11
12
|
import { DEPENDENCIES_FIELDS } from '@teambit/legacy.constants';
|
|
12
13
|
import type OverridesDependencies from './overrides-dependencies';
|
|
13
14
|
import type { DebugComponentsDependency } from './auto-detect-deps';
|
|
@@ -126,7 +127,7 @@ export async function updateDependenciesVersions(
|
|
|
126
127
|
) {
|
|
127
128
|
dependency.versionRange = `${componentRangePrefix}${resolvedVersion}`;
|
|
128
129
|
}
|
|
129
|
-
} else if (dependency.versionRange && depType !== 'peerDependencies' && dependency.versionRange
|
|
130
|
+
} else if (dependency.versionRange && depType !== 'peerDependencies' && !isPlusVersion(dependency.versionRange)) {
|
|
130
131
|
dependency.versionRange = undefined;
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { DEPENDENCIES_FIELDS,
|
|
1
|
+
import { DEPENDENCIES_FIELDS, MANUALLY_REMOVE_DEPENDENCY } from '@teambit/legacy.constants';
|
|
2
2
|
import { logger } from '@teambit/legacy.logger';
|
|
3
|
+
import { isPlusVersion, resolvePlusVersion } from '@teambit/dependency-resolver';
|
|
3
4
|
import type { ConsumerComponent as Component, ManuallyChangedDependencies } from '@teambit/legacy.consumer-component';
|
|
4
5
|
import type { FileType } from './auto-detect-deps';
|
|
5
6
|
|
|
@@ -75,14 +76,15 @@ export default class OverridesDependencies {
|
|
|
75
76
|
packageJson: Record<string, any> | null | undefined
|
|
76
77
|
): Record<string, any> | null | undefined {
|
|
77
78
|
const packageVersionToAdd = (): string | null | undefined => {
|
|
78
|
-
|
|
79
|
+
// "+", "+^" and "+~" take the version from the package.json
|
|
80
|
+
if (!isPlusVersion(dependencyValue)) {
|
|
79
81
|
return dependencyValue;
|
|
80
82
|
}
|
|
81
83
|
if (!packageJson) return null;
|
|
82
84
|
for (const depField of DEPENDENCIES_FIELDS) {
|
|
83
85
|
if (packageJson[depField]) {
|
|
84
86
|
const found = Object.keys(packageJson[depField]).find((pkg) => pkg === dependency);
|
|
85
|
-
if (found) return packageJson[depField][dependency];
|
|
87
|
+
if (found) return resolvePlusVersion(dependencyValue, packageJson[depField][dependency]);
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
return null;
|
|
@@ -93,6 +93,7 @@ export declare class ApplyOverrides {
|
|
|
93
93
|
private removeIgnoredPackagesByOverrides;
|
|
94
94
|
private _resolvePackageData;
|
|
95
95
|
private _getComponentIdToAdd;
|
|
96
|
+
private findComponentDepByPackageName;
|
|
96
97
|
getDependenciesToAddManually(packageJson: Record<string, any> | null | undefined, existingDependencies: AllDependencies): {
|
|
97
98
|
components: Record<string, any>;
|
|
98
99
|
packages: Record<string, any>;
|
|
@@ -129,13 +130,16 @@ export declare class ApplyOverrides {
|
|
|
129
130
|
private applyPackageVersion;
|
|
130
131
|
private applyAutoDetectedPeersFromEnvOnEnvItSelf;
|
|
131
132
|
/**
|
|
132
|
-
* in the env.jsonc file, a policy-peer package can have `+` sign in the version. it means that it should be resolved
|
|
133
|
+
* in the env.jsonc file, a policy-peer package can have `+` sign (or `+^`/`+~`) in the version. it means that it should be resolved
|
|
133
134
|
* from the workspace. whatever version is installed/imported in the workspace, it should be used here.
|
|
134
135
|
* in some cases, the package is not installed in the workspace, for example, the env is now imported without the
|
|
135
136
|
* dep. so the dep is not in the node_modules.
|
|
136
137
|
* strategy should be: .bitmap, workspace.jsonc, then model.
|
|
137
138
|
* it's not in .bitmap, otherwise, it was linked and `_resolvePackageData` would have found it.
|
|
138
139
|
* so either, it's in the workspace.jsonc or in the model.
|
|
140
|
+
* @param preferWorkspacePolicy check the workspace.jsonc before what's installed. needed for a package that the
|
|
141
|
+
* component gets with a plus version. what's installed for the component was installed according to the version it
|
|
142
|
+
* had before, so it doesn't follow an upgrade in the workspace.jsonc (e.g. by "bit update").
|
|
139
143
|
*/
|
|
140
144
|
private resolveEnvPeerDepVersion;
|
|
141
145
|
/**
|
|
@@ -11,6 +11,13 @@ function _path() {
|
|
|
11
11
|
};
|
|
12
12
|
return data;
|
|
13
13
|
}
|
|
14
|
+
function _semver() {
|
|
15
|
+
const data = _interopRequireDefault(require("semver"));
|
|
16
|
+
_semver = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
14
21
|
function _componentId() {
|
|
15
22
|
const data = require("@teambit/component-id");
|
|
16
23
|
_componentId = function () {
|
|
@@ -67,6 +74,13 @@ function _resolvePkgData() {
|
|
|
67
74
|
};
|
|
68
75
|
return data;
|
|
69
76
|
}
|
|
77
|
+
function _dependencyResolver() {
|
|
78
|
+
const data = require("@teambit/dependency-resolver");
|
|
79
|
+
_dependencyResolver = function () {
|
|
80
|
+
return data;
|
|
81
|
+
};
|
|
82
|
+
return data;
|
|
83
|
+
}
|
|
70
84
|
function _legacy4() {
|
|
71
85
|
const data = require("@teambit/legacy.consumer-config");
|
|
72
86
|
_legacy4 = function () {
|
|
@@ -285,7 +299,9 @@ class ApplyOverrides {
|
|
|
285
299
|
if (!missingIssue.data.length) this.issues.delete(_componentIssues().IssuesClasses.MissingPackagesDependenciesOnFs);
|
|
286
300
|
}
|
|
287
301
|
async loadAutoDetectOverrides() {
|
|
288
|
-
|
|
302
|
+
// outside a workspace, they're calculated by the caller (if at all) and set before this runs
|
|
303
|
+
if (!this.workspace) return;
|
|
304
|
+
this.autoDetectOverrides = await this.workspace.getAutoDetectOverrides(this.component.extensions, this.component.id, this.component.files, this.getEnvExtendsDeps());
|
|
289
305
|
}
|
|
290
306
|
cloneAllPackagesDependencies() {
|
|
291
307
|
this.originAllPackagesDependencies = (0, _lodash().cloneDeep)(this.allPackagesDependencies);
|
|
@@ -311,7 +327,22 @@ class ApplyOverrides {
|
|
|
311
327
|
const packageObject = (0, _resolvePkgData().resolvePackageData)(basePath, modulePath);
|
|
312
328
|
return packageObject;
|
|
313
329
|
}
|
|
314
|
-
_getComponentIdToAdd(dependency, versionRange) {
|
|
330
|
+
_getComponentIdToAdd(dependency, versionRange, depField) {
|
|
331
|
+
if (!this.consumer) {
|
|
332
|
+
// a scope has no node_modules to resolve the package from. if it's a component dependency, use it. otherwise, a
|
|
333
|
+
// forced component dependency (e.g. an env's own peer, which is a runtime dep of the env) is added as a package
|
|
334
|
+
// and then dropped in favor of the component dependency, which may be in a different field.
|
|
335
|
+
const compDep = this.findComponentDepByPackageName(dependency);
|
|
336
|
+
if (compDep) {
|
|
337
|
+
// same as the workspace (see updateDependenciesVersions), only a peer component dependency keeps its range
|
|
338
|
+
const range = depField === 'peerDependencies' ? versionRange : undefined;
|
|
339
|
+
return {
|
|
340
|
+
componentId: compDep.id,
|
|
341
|
+
packageName: dependency,
|
|
342
|
+
versionRange: range
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
315
346
|
const packageData = this._resolvePackageData(dependency);
|
|
316
347
|
return {
|
|
317
348
|
componentId: packageData?.componentId,
|
|
@@ -319,6 +350,15 @@ class ApplyOverrides {
|
|
|
319
350
|
versionRange
|
|
320
351
|
};
|
|
321
352
|
}
|
|
353
|
+
findComponentDepByPackageName(packageName) {
|
|
354
|
+
const {
|
|
355
|
+
dependencies,
|
|
356
|
+
devDependencies,
|
|
357
|
+
peerDependencies
|
|
358
|
+
} = this.allDependencies;
|
|
359
|
+
const isMatch = dep => dep.packageName === packageName;
|
|
360
|
+
return dependencies.find(isMatch) || devDependencies.find(isMatch) || peerDependencies.find(isMatch);
|
|
361
|
+
}
|
|
322
362
|
getDependenciesToAddManually(packageJson, existingDependencies) {
|
|
323
363
|
const overrides = this.overridesDependencies.getDependenciesToAddManually();
|
|
324
364
|
if (!overrides) return undefined;
|
|
@@ -329,7 +369,7 @@ class ApplyOverrides {
|
|
|
329
369
|
if (!overrides[depField]) return;
|
|
330
370
|
Object.keys(overrides[depField]).forEach(dependency => {
|
|
331
371
|
const dependencyValue = overrides[depField][dependency];
|
|
332
|
-
const componentData = this._getComponentIdToAdd(dependency, dependencyValue);
|
|
372
|
+
const componentData = this._getComponentIdToAdd(dependency, dependencyValue, depField);
|
|
333
373
|
if (componentData?.componentId) {
|
|
334
374
|
if (componentData.componentId.isEqualWithoutVersion(this.componentId)) {
|
|
335
375
|
this.logger.warn(`component ${this.componentId.toString()} depends on itself ${componentData.componentId.toString()}. ignoring it.`);
|
|
@@ -577,7 +617,7 @@ class ApplyOverrides {
|
|
|
577
617
|
}
|
|
578
618
|
isPackageAutoDetected(pkgName, originallyExists, missingPackages) {
|
|
579
619
|
// Check component dependencies
|
|
580
|
-
const existsInAnyCompDeps =
|
|
620
|
+
const existsInAnyCompDeps = Boolean(this.findComponentDepByPackageName(pkgName));
|
|
581
621
|
|
|
582
622
|
// Check originAllPackagesDependencies instead of allPackagesDependencies
|
|
583
623
|
// as it might be already removed at this point if it was set with "-" in runtime/dev
|
|
@@ -658,7 +698,9 @@ class ApplyOverrides {
|
|
|
658
698
|
comp.versionRange = pkgVal;
|
|
659
699
|
this.allDependencies.peerDependencies.push(comp);
|
|
660
700
|
} else {
|
|
661
|
-
|
|
701
|
+
// a package has no separate version and range, so a "+" placeholder is resolved here.
|
|
702
|
+
// a component dep keeps it in the versionRange, and it's resolved when generating the package.json
|
|
703
|
+
this.allPackagesDependencies[key][pkgName] = (0, _dependencyResolver().isPlusVersion)(pkgVal) ? (0, _dependencyResolver().resolvePlusVersion)(pkgVal, this.resolveEnvPeerDepVersion(pkgName, true)) : pkgVal;
|
|
662
704
|
}
|
|
663
705
|
if (existsInCompsPeerDeps) {
|
|
664
706
|
existsInCompsPeerDeps.versionRange = pkgVal;
|
|
@@ -685,11 +727,11 @@ class ApplyOverrides {
|
|
|
685
727
|
});
|
|
686
728
|
const resolvedEnvPolicyManifest = Object.keys(envPolicyManifest).reduce((acc, pkgName) => {
|
|
687
729
|
const version = envPolicyManifest[pkgName];
|
|
688
|
-
if (
|
|
730
|
+
if (!(0, _dependencyResolver().isPlusVersion)(version)) {
|
|
689
731
|
acc[pkgName] = version;
|
|
690
732
|
return acc;
|
|
691
733
|
}
|
|
692
|
-
acc[pkgName] = this.resolveEnvPeerDepVersion(pkgName);
|
|
734
|
+
acc[pkgName] = (0, _dependencyResolver().resolvePlusVersion)(version, this.resolveEnvPeerDepVersion(pkgName));
|
|
693
735
|
return acc;
|
|
694
736
|
}, {});
|
|
695
737
|
// TODO: handle component deps once we support peers between components
|
|
@@ -697,21 +739,34 @@ class ApplyOverrides {
|
|
|
697
739
|
}
|
|
698
740
|
|
|
699
741
|
/**
|
|
700
|
-
* in the env.jsonc file, a policy-peer package can have `+` sign in the version. it means that it should be resolved
|
|
742
|
+
* in the env.jsonc file, a policy-peer package can have `+` sign (or `+^`/`+~`) in the version. it means that it should be resolved
|
|
701
743
|
* from the workspace. whatever version is installed/imported in the workspace, it should be used here.
|
|
702
744
|
* in some cases, the package is not installed in the workspace, for example, the env is now imported without the
|
|
703
745
|
* dep. so the dep is not in the node_modules.
|
|
704
746
|
* strategy should be: .bitmap, workspace.jsonc, then model.
|
|
705
747
|
* it's not in .bitmap, otherwise, it was linked and `_resolvePackageData` would have found it.
|
|
706
748
|
* so either, it's in the workspace.jsonc or in the model.
|
|
749
|
+
* @param preferWorkspacePolicy check the workspace.jsonc before what's installed. needed for a package that the
|
|
750
|
+
* component gets with a plus version. what's installed for the component was installed according to the version it
|
|
751
|
+
* had before, so it doesn't follow an upgrade in the workspace.jsonc (e.g. by "bit update").
|
|
707
752
|
*/
|
|
708
|
-
resolveEnvPeerDepVersion(pkgName) {
|
|
753
|
+
resolveEnvPeerDepVersion(pkgName, preferWorkspacePolicy = false) {
|
|
754
|
+
const wsPolicy = this.depsResolver.getWorkspacePolicyManifest();
|
|
755
|
+
const wsVersion = wsPolicy?.dependencies?.[pkgName] || wsPolicy?.peerDependencies?.[pkgName];
|
|
709
756
|
const resolved = this._resolvePackageData(pkgName);
|
|
757
|
+
if (preferWorkspacePolicy && wsVersion) {
|
|
758
|
+
// the workspace.jsonc has usually a range. the plus version needs a concrete version to add its own prefix to
|
|
759
|
+
if (resolved?.concreteVersion && _semver().default.satisfies(resolved.concreteVersion, wsVersion)) {
|
|
760
|
+
return resolved.concreteVersion;
|
|
761
|
+
}
|
|
762
|
+
const validRange = _semver().default.validRange(wsVersion);
|
|
763
|
+
// an unconstrained range (e.g. "*") has no meaningful minimum, keep it as is
|
|
764
|
+
if (!validRange || validRange === '*') return wsVersion;
|
|
765
|
+
return _semver().default.minVersion(wsVersion)?.version || wsVersion;
|
|
766
|
+
}
|
|
710
767
|
if (resolved && resolved.concreteVersion) {
|
|
711
768
|
return resolved.concreteVersion;
|
|
712
769
|
}
|
|
713
|
-
const wsPolicy = this.depsResolver.getWorkspacePolicyManifest();
|
|
714
|
-
const wsVersion = wsPolicy?.dependencies?.[pkgName] || wsPolicy?.peerDependencies?.[pkgName];
|
|
715
770
|
if (wsVersion) {
|
|
716
771
|
return wsVersion;
|
|
717
772
|
}
|