@teambit/dependencies 1.0.82 → 1.0.83

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.
Files changed (43) hide show
  1. package/dependencies-loader/README.md +34 -0
  2. package/dependencies-loader/apply-overrides.ts +552 -0
  3. package/dependencies-loader/auto-detect-deps.ts +761 -0
  4. package/dependencies-loader/dependencies-data.ts +47 -0
  5. package/dependencies-loader/dependencies-loader.ts +174 -0
  6. package/dependencies-loader/dependencies-versions-resolver.ts +160 -0
  7. package/dependencies-loader/index.ts +2 -0
  8. package/dependencies-loader/overrides-dependencies.ts +115 -0
  9. package/dependencies-loader/package-to-definetly-typed.spec.ts +53 -0
  10. package/dependencies-loader/package-to-definetly-typed.ts +10 -0
  11. package/dist/dependencies-loader/README.md +34 -0
  12. package/dist/dependencies-loader/apply-overrides.d.ts +100 -0
  13. package/dist/dependencies-loader/apply-overrides.js +541 -0
  14. package/dist/dependencies-loader/apply-overrides.js.map +1 -0
  15. package/dist/dependencies-loader/auto-detect-deps.d.ts +165 -0
  16. package/dist/dependencies-loader/auto-detect-deps.js +768 -0
  17. package/dist/dependencies-loader/auto-detect-deps.js.map +1 -0
  18. package/dist/dependencies-loader/dependencies-data.d.ts +17 -0
  19. package/dist/dependencies-loader/dependencies-data.js +72 -0
  20. package/dist/dependencies-loader/dependencies-data.js.map +1 -0
  21. package/dist/dependencies-loader/dependencies-loader.d.ts +30 -0
  22. package/dist/dependencies-loader/dependencies-loader.js +229 -0
  23. package/dist/dependencies-loader/dependencies-loader.js.map +1 -0
  24. package/dist/dependencies-loader/dependencies-versions-resolver.d.ts +6 -0
  25. package/dist/dependencies-loader/dependencies-versions-resolver.js +153 -0
  26. package/dist/dependencies-loader/dependencies-versions-resolver.js.map +1 -0
  27. package/dist/dependencies-loader/index.d.ts +2 -0
  28. package/dist/dependencies-loader/index.js +33 -0
  29. package/dist/dependencies-loader/index.js.map +1 -0
  30. package/dist/dependencies-loader/overrides-dependencies.d.ts +17 -0
  31. package/dist/dependencies-loader/overrides-dependencies.js +118 -0
  32. package/dist/dependencies-loader/overrides-dependencies.js.map +1 -0
  33. package/dist/dependencies-loader/package-to-definetly-typed.d.ts +1 -0
  34. package/dist/dependencies-loader/package-to-definetly-typed.js +18 -0
  35. package/dist/dependencies-loader/package-to-definetly-typed.js.map +1 -0
  36. package/dist/dependencies-loader/package-to-definetly-typed.spec.d.ts +1 -0
  37. package/dist/dependencies-loader/package-to-definetly-typed.spec.js +27 -0
  38. package/dist/dependencies-loader/package-to-definetly-typed.spec.js.map +1 -0
  39. package/dist/dependencies.main.runtime.d.ts +21 -4
  40. package/dist/dependencies.main.runtime.js +49 -14
  41. package/dist/dependencies.main.runtime.js.map +1 -1
  42. package/package.json +17 -6
  43. /package/dist/{preview-1701813377689.js → preview-1701874572488.js} +0 -0
@@ -0,0 +1,34 @@
1
+ # Dependencies Cache Mechanism
2
+
3
+ To improve component-loading performance, the dependencies data is cached in the filesystem.
4
+
5
+ ### The component's cache gets invalidated in the following scenario:
6
+
7
+ 1. The component-dir or sub-dirs have been changed. (modified-date of the dirs paths)
8
+ 2. One of the component files have been changed.
9
+ 3. A component config file (component.json/package.json) has modified.
10
+
11
+ ### The entire cache of all component dependencies is invalidated if one of the following happened:
12
+
13
+ 1. workspace-config file (bit.json/workspace.jsonc) has changed.
14
+ 2. package.json file has changed.
15
+ 3. node_modules-dir (only root dir, not sub-dirs) has changed. - not sure if needed.
16
+ 4. On completion of "bit link".
17
+ 5. On completion of "bit install".
18
+ 6. During 'bit tag --persist', before loading the components.
19
+
20
+ ### A component is not entered to the cache in the first place in the following cases:
21
+
22
+ 1. No root-dir/track-dir (legacy).
23
+ 2. Component has one of the following issues: missingPackagesDependenciesOnFs, untrackedDependencies.
24
+
25
+ ### Limitations:
26
+
27
+ 1. If a user deleted the dists directories of a component in node-modules, we don't know about it and bit-status won't show any error.
28
+ 2. If a user deleted a package from node-modules dir manually, we don't know about it.
29
+
30
+ ### Disabling the cache
31
+
32
+ set the "no-fs-cache" feature.
33
+ For one command, prefix your command with `BIT_FEATURES=no-fs-cache`.
34
+ Or you can configure it on the machine level for all commands/workspaces: `bit config set features='no-fs-cache'`
@@ -0,0 +1,552 @@
1
+ import R from 'ramda';
2
+ import path from 'path';
3
+ import { ComponentID, ComponentIdList } from '@teambit/component-id';
4
+ import { cloneDeep, uniq } from 'lodash';
5
+ import { IssuesList, IssuesClasses, MissingPackagesData } from '@teambit/component-issues';
6
+ import { DEPENDENCIES_FIELDS, MANUALLY_REMOVE_DEPENDENCY } from '@teambit/legacy/dist/constants';
7
+ import Component from '@teambit/legacy/dist/consumer/component/consumer-component';
8
+ import PackageJsonFile from '@teambit/legacy/dist/consumer/component/package-json-file';
9
+ import { ResolvedPackageData, resolvePackageData, resolvePackagePath } from '@teambit/legacy/dist/utils/packages';
10
+ import { PathLinux } from '@teambit/legacy/dist/utils/path';
11
+ import { Workspace } from '@teambit/workspace';
12
+ import { Dependency } from '@teambit/legacy/dist/consumer/component/dependencies';
13
+ import { DependencyResolverMain } from '@teambit/dependency-resolver';
14
+ import Consumer from '@teambit/legacy/dist/consumer/consumer';
15
+ import ComponentMap from '@teambit/legacy/dist/consumer/bit-map/component-map';
16
+ import OverridesDependencies from './overrides-dependencies';
17
+ import { DependenciesData } from './dependencies-data';
18
+ import { DebugDependencies, FileType } from './auto-detect-deps';
19
+
20
+ export type AllDependencies = {
21
+ dependencies: Dependency[];
22
+ devDependencies: Dependency[];
23
+ };
24
+
25
+ export type AllPackagesDependencies = {
26
+ packageDependencies: Record<string, string>;
27
+ devPackageDependencies: Record<string, string>;
28
+ peerPackageDependencies: Record<string, string>;
29
+ };
30
+
31
+ const DepsKeysToAllPackagesDepsKeys = {
32
+ dependencies: 'packageDependencies',
33
+ devDependencies: 'devPackageDependencies',
34
+ peerDependencies: 'peerPackageDependencies',
35
+ };
36
+
37
+ export class ApplyOverrides {
38
+ componentId: ComponentID;
39
+ componentFromModel: Component;
40
+ allDependencies: AllDependencies;
41
+ allPackagesDependencies: AllPackagesDependencies;
42
+ /**
43
+ * This will store a copy of the package deps before removal
44
+ * in order to apply auto detected rules that are running after the removal
45
+ */
46
+ originAllPackagesDependencies: AllPackagesDependencies;
47
+ issues: IssuesList;
48
+ coreAspects: string[] = [];
49
+ processedFiles: string[];
50
+ overridesDependencies: OverridesDependencies;
51
+ debugDependenciesData: DebugDependencies;
52
+ autoDetectOverrides: Record<string, any> | undefined;
53
+ constructor(
54
+ private component: Component,
55
+ private depsResolver: DependencyResolverMain,
56
+ private workspace?: Workspace
57
+ ) {
58
+ this.componentId = component.componentId;
59
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
60
+ this.componentFromModel = this.component.componentFromModel;
61
+ this.allDependencies = {
62
+ dependencies: [],
63
+ devDependencies: [],
64
+ };
65
+ this.allPackagesDependencies = {
66
+ packageDependencies: {},
67
+ devPackageDependencies: {},
68
+ peerPackageDependencies: {},
69
+ };
70
+ this.processedFiles = [];
71
+ this.issues = component.issues;
72
+ this.setLegacyInsideHarmonyIssue();
73
+ this.overridesDependencies = new OverridesDependencies(component);
74
+ this.debugDependenciesData = { components: [] };
75
+ }
76
+
77
+ get consumer(): Consumer | undefined {
78
+ return this.workspace?.consumer;
79
+ }
80
+
81
+ async getDependenciesData(): Promise<{
82
+ dependenciesData: DependenciesData;
83
+ overridesDependencies: OverridesDependencies;
84
+ autoDetectOverrides?: Record<string, any>;
85
+ }> {
86
+ await this.populateDependencies();
87
+ const dependenciesData = new DependenciesData(
88
+ this.allDependencies,
89
+ this.allPackagesDependencies,
90
+ this.issues,
91
+ this.coreAspects
92
+ );
93
+ return {
94
+ dependenciesData,
95
+ overridesDependencies: this.overridesDependencies,
96
+ autoDetectOverrides: this.autoDetectOverrides,
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Given the tree of file dependencies from the driver, find the components of these files.
102
+ * Each dependency file has a path, use bit.map to search for the component name by that path.
103
+ * If the component is found, add it to "this.allDependencies.dependencies". Otherwise, add it to "this.issues.untrackedDependencies".
104
+ *
105
+ * For the found components, add their sourceRelativePath and destinationRelativePath, they are being used for
106
+ * generating links upon import:
107
+ * sourceRelativePath - location of the link file.
108
+ * destinationRelativePath - destination written inside the link file.
109
+ *
110
+ * When a dependency is found in a regular (implementation) file, it goes to `dependencies`. If
111
+ * it found on a test file, it goes to `devDependencies`.
112
+ * Similarly, when a package is found in a regular file, it goes to `packageDependencies`. When
113
+ * if found in a test file, it goes to `devPackageDependencies`.
114
+ * An exception for the above is when a package is required in a regular or test file but is also
115
+ * mentioned in the `package.json` file as a peerDependency, in that case, the package is added
116
+ * to `peerPackageDependencies` and removed from other places. Unless this package is overridden
117
+ * and marked as ignored in the consumer or component config file.
118
+ */
119
+ private async populateDependencies() {
120
+ await this.loadAutoDetectOverrides();
121
+ this.removeIgnoredComponentsByOverrides();
122
+ this.cloneAllPackagesDependencies();
123
+ this.removeIgnoredPackagesByOverrides();
124
+ this.removeDevAndEnvDepsIfTheyAlsoRegulars();
125
+ this.applyPeersFromComponentModel();
126
+ this.applyPackageJson();
127
+ this.applyWorkspacePolicy();
128
+ this.makeLegacyAsPeer();
129
+ await this.applyAutoDetectOverridesOnComponent();
130
+ this.manuallyAddDependencies();
131
+ // Doing this here (after manuallyAddDependencies) because usually the env of the env is adding dependencies as peer of the env
132
+ // which will make this not work if it come before
133
+ // example:
134
+ // custom react has peers with react 16.4.0.
135
+ // the custom react uses the "teambit.envs/env" env, which will add react ^17.0.0 to every component that uses it
136
+ // we want to make sure that the custom react is using 16.4.0 not 17.
137
+ await this.applyAutoDetectedPeersFromEnvOnEnvItSelf();
138
+ this.coreAspects = R.uniq(this.coreAspects);
139
+ }
140
+
141
+ private removeIgnoredComponentsByOverrides() {
142
+ const shouldBeIncluded = (dep: Dependency, fileType: FileType) =>
143
+ !this.overridesDependencies.shouldIgnorePackage(dep.packageName as string, fileType);
144
+ this.allDependencies.dependencies = this.allDependencies.dependencies.filter((dep) =>
145
+ shouldBeIncluded(dep, { isTestFile: false })
146
+ );
147
+ this.allDependencies.devDependencies = this.allDependencies.devDependencies.filter((dep) =>
148
+ shouldBeIncluded(dep, { isTestFile: true })
149
+ );
150
+
151
+ const missingIssue = this.issues.getIssueByName('MissingPackagesDependenciesOnFs');
152
+ if (!missingIssue) return;
153
+ const missingData = missingIssue.data as MissingPackagesData[];
154
+ missingData.forEach((m) => {
155
+ m.missingPackages = m.missingPackages.filter(
156
+ (pkg) => !this.overridesDependencies.shouldIgnorePackage(pkg, { isTestFile: m.isDevFile })
157
+ );
158
+ });
159
+ missingIssue.data = missingData.filter((m) => m.missingPackages.length);
160
+ if (!missingIssue.data.length) this.issues.delete(IssuesClasses.MissingPackagesDependenciesOnFs);
161
+ }
162
+
163
+ private async loadAutoDetectOverrides() {
164
+ this.autoDetectOverrides = await this.workspace?.getAutoDetectOverrides(
165
+ this.component.extensions,
166
+ this.component.id,
167
+ this.component.files
168
+ );
169
+ }
170
+
171
+ private cloneAllPackagesDependencies() {
172
+ this.originAllPackagesDependencies = cloneDeep(this.allPackagesDependencies);
173
+ }
174
+
175
+ private removeIgnoredPackagesByOverrides() {
176
+ const shouldBeIncluded = (pkgVersion, pkgName) =>
177
+ !this.overridesDependencies.shouldIgnorePackageByType(pkgName, 'dependencies');
178
+ const shouldBeIncludedDev = (pkgVersion, pkgName) =>
179
+ !this.overridesDependencies.shouldIgnorePackageByType(pkgName, 'devDependencies');
180
+
181
+ this.allPackagesDependencies.packageDependencies = R.pickBy(
182
+ shouldBeIncluded,
183
+ this.allPackagesDependencies.packageDependencies
184
+ );
185
+ this.allPackagesDependencies.devPackageDependencies = R.pickBy(
186
+ shouldBeIncludedDev,
187
+ this.allPackagesDependencies.devPackageDependencies
188
+ );
189
+ }
190
+
191
+ // TODO: maybe cache those results??
192
+ private _resolvePackageData(packageName: string): ResolvedPackageData | undefined {
193
+ const consumer = this.consumer;
194
+ if (!consumer) return undefined;
195
+ // if consumer is defined, then it has componentMap prop.
196
+ const componentMap = this.component.componentMap as ComponentMap;
197
+ const rootDir: PathLinux | null | undefined = componentMap.rootDir as string;
198
+ const consumerPath = consumer.getPath();
199
+ const basePath = rootDir ? path.join(consumerPath, rootDir) : consumerPath;
200
+ const modulePath = resolvePackagePath(packageName, basePath, consumerPath);
201
+ if (!modulePath) return undefined; // e.g. it's author and wasn't exported yet, so there's no node_modules of that component
202
+ const packageObject = resolvePackageData(basePath, modulePath);
203
+ return packageObject;
204
+ }
205
+
206
+ private _getComponentIdToAdd(
207
+ field: string,
208
+ dependency: string
209
+ ): { componentId?: ComponentID; packageName?: string } | undefined {
210
+ if (field === 'peerDependencies') return undefined;
211
+ const packageData = this._resolvePackageData(dependency);
212
+ return { componentId: packageData?.componentId, packageName: packageData?.name };
213
+ }
214
+
215
+ getDependenciesToAddManually(
216
+ packageJson: Record<string, any> | null | undefined,
217
+ existingDependencies: AllDependencies
218
+ ): { components: Record<string, any>; packages: Record<string, any> } | undefined {
219
+ const overrides = this.overridesDependencies.getDependenciesToAddManually();
220
+ if (!overrides) return undefined;
221
+ const components = {};
222
+ const packages = {};
223
+ DEPENDENCIES_FIELDS.forEach((depField) => {
224
+ if (!overrides[depField]) return;
225
+ Object.keys(overrides[depField]).forEach((dependency) => {
226
+ const dependencyValue = overrides[depField][dependency];
227
+ const componentData = this._getComponentIdToAdd(depField, dependency);
228
+ if (componentData?.componentId) {
229
+ const dependencyExist = existingDependencies[depField].find((d) =>
230
+ d.id.isEqualWithoutVersion(componentData.componentId)
231
+ );
232
+ if (!dependencyExist) {
233
+ this.overridesDependencies._addManuallyAddedDep(depField, componentData.componentId.toString());
234
+ components[depField] ? components[depField].push(componentData) : (components[depField] = [componentData]);
235
+ }
236
+ return;
237
+ }
238
+ const addedPkg = this.overridesDependencies._manuallyAddPackage(
239
+ depField,
240
+ dependency,
241
+ dependencyValue,
242
+ packageJson
243
+ );
244
+ if (addedPkg) {
245
+ packages[depField] = Object.assign(packages[depField] || {}, addedPkg);
246
+ if (componentData && !componentData.packageName) {
247
+ this.overridesDependencies.missingPackageDependencies.push(dependency);
248
+ }
249
+ }
250
+ });
251
+ });
252
+ return { components, packages };
253
+ }
254
+
255
+ private manuallyAddDependencies() {
256
+ const packageJson = this._getPackageJson();
257
+ const dependencies = this.getDependenciesToAddManually(packageJson, this.allDependencies);
258
+ if (!dependencies) return;
259
+ const { components, packages } = dependencies;
260
+ DEPENDENCIES_FIELDS.forEach((depField) => {
261
+ if (components[depField] && components[depField].length) {
262
+ components[depField].forEach((depData) =>
263
+ this.allDependencies[depField].push(new Dependency(depData.componentId, [], depData.packageName))
264
+ );
265
+ }
266
+ if (packages[depField] && !R.isEmpty(packages[depField])) {
267
+ Object.assign(this.allPackagesDependencies[this._pkgFieldMapping(depField)], packages[depField]);
268
+ }
269
+ });
270
+ // The automatic dependency detector considers all found dependencies to be runtime dependencies.
271
+ // But this breaks proper installation of injected subdependencies that are resolved from workspace components.
272
+ if (this.allPackagesDependencies.packageDependencies && packages.peerDependencies) {
273
+ for (const peerName of Object.keys(packages.peerDependencies)) {
274
+ delete this.allPackagesDependencies.packageDependencies[peerName];
275
+ }
276
+ }
277
+ if (this.allPackagesDependencies.packageDependencies && packages.peerPackageDependencies) {
278
+ for (const peerName of Object.keys(packages.peerPackageDependencies)) {
279
+ delete this.allPackagesDependencies.packageDependencies[peerName];
280
+ }
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Remove the dependencies which appear both in dev and regular deps from the dev
286
+ * Because if a dependency is both dev dependency and regular dependency it should be treated as regular one
287
+ * Apply for both packages and components dependencies
288
+ */
289
+ private removeDevAndEnvDepsIfTheyAlsoRegulars() {
290
+ // remove dev and env packages that are also regular packages
291
+ const getNotRegularPackages = (packages) =>
292
+ R.difference(R.keys(packages), R.keys(this.allPackagesDependencies.packageDependencies));
293
+ this.allPackagesDependencies.devPackageDependencies = R.pick(
294
+ getNotRegularPackages(this.allPackagesDependencies.devPackageDependencies),
295
+ this.allPackagesDependencies.devPackageDependencies
296
+ );
297
+ // remove dev dependencies that are also regular dependencies
298
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
299
+ const componentDepsIds = new ComponentIdList(...this.allDependencies.dependencies.map((c) => c.id));
300
+ this.allDependencies.devDependencies = this.allDependencies.devDependencies.filter(
301
+ (d) => !componentDepsIds.has(d.id)
302
+ );
303
+ }
304
+
305
+ private applyPeersFromComponentModel(): void {
306
+ const getPeerDependencies = (): Record<string, any> => {
307
+ const packageJson = this._getPackageJsonFromComponentModel();
308
+ if (packageJson && packageJson.peerDependencies) return packageJson.peerDependencies;
309
+ return {};
310
+ };
311
+ const projectPeerDependencies = getPeerDependencies();
312
+ const peerPackages = {};
313
+ if (R.isEmpty(projectPeerDependencies)) return;
314
+
315
+ // check whether the peer-dependencies was actually require in the code. if so, remove it from
316
+ // the packages/dev-packages and add it as a peer-package.
317
+ // if it was not required in the code, don't add it to the peerPackages
318
+ Object.keys(projectPeerDependencies).forEach((pkg) => {
319
+ if (this.overridesDependencies.shouldIgnorePeerPackage(pkg)) return;
320
+ ['packageDependencies', 'devPackageDependencies'].forEach((field) => {
321
+ if (Object.keys(this.allPackagesDependencies[field]).includes(pkg)) {
322
+ delete this.allPackagesDependencies[field][pkg];
323
+ peerPackages[pkg] = projectPeerDependencies[pkg];
324
+ }
325
+ });
326
+ });
327
+ this.allPackagesDependencies.peerPackageDependencies = peerPackages;
328
+ }
329
+
330
+ private applyPackageJson(): void {
331
+ const packageJson = this._getPackageJson();
332
+ if (!packageJson) return;
333
+ const pkgJsonPeer = packageJson.peerDependencies || {};
334
+ const pkgJsonRegularDeps = packageJson.dependencies || {};
335
+ const peerDeps = this.allPackagesDependencies.peerPackageDependencies || {};
336
+ ['packageDependencies', 'devPackageDependencies', 'peerPackageDependencies'].forEach((field) => {
337
+ R.forEachObjIndexed((_pkgVal, pkgName) => {
338
+ const peerVersionFromPkgJson = pkgJsonPeer[pkgName];
339
+ const regularVersionFromPkgJson = pkgJsonRegularDeps[pkgName];
340
+ if (peerVersionFromPkgJson) {
341
+ delete this.allPackagesDependencies[field][pkgName];
342
+ peerDeps[pkgName] = peerVersionFromPkgJson;
343
+ } else if (regularVersionFromPkgJson) {
344
+ delete this.allPackagesDependencies.peerPackageDependencies?.[pkgName];
345
+ this.allPackagesDependencies[field][pkgName] = regularVersionFromPkgJson;
346
+ }
347
+ }, this.allPackagesDependencies[field]);
348
+ });
349
+ this.allPackagesDependencies.peerPackageDependencies = peerDeps;
350
+ }
351
+
352
+ private applyWorkspacePolicy(): void {
353
+ const wsPolicy = this.depsResolver.getWorkspacePolicyManifest();
354
+ if (!wsPolicy) return;
355
+ const wsPeer = wsPolicy.peerDependencies || {};
356
+ const wsRegular = wsPolicy.dependencies || {};
357
+ const peerDeps = this.allPackagesDependencies.peerPackageDependencies || {};
358
+ // we are not iterate component deps since they are resolved from what actually installed
359
+ // the policy used for installation only in that case
360
+ ['packageDependencies', 'devPackageDependencies', 'peerPackageDependencies'].forEach((field) => {
361
+ R.forEachObjIndexed((_pkgVal, pkgName) => {
362
+ const peerVersionFromWsPolicy = wsPeer[pkgName];
363
+ const regularVersionFromWsPolicy = wsRegular[pkgName];
364
+ if (peerVersionFromWsPolicy) {
365
+ delete this.allPackagesDependencies[field][pkgName];
366
+ peerDeps[pkgName] = peerVersionFromWsPolicy;
367
+ } else if (regularVersionFromWsPolicy) {
368
+ delete this.allPackagesDependencies.peerPackageDependencies?.[pkgName];
369
+ this.allPackagesDependencies[field][pkgName] = regularVersionFromWsPolicy;
370
+ }
371
+ }, this.allPackagesDependencies[field]);
372
+ });
373
+ this.allPackagesDependencies.peerPackageDependencies = peerDeps;
374
+ }
375
+
376
+ /**
377
+ * It removes the @teambit/legacy dependency from the dependencies/devDeps and adds it as a peer dependency with ^.
378
+ */
379
+ private makeLegacyAsPeer(): void {
380
+ let version;
381
+ if (this.allPackagesDependencies.packageDependencies['@teambit/legacy']) {
382
+ version = this.allPackagesDependencies.packageDependencies['@teambit/legacy'];
383
+ delete this.allPackagesDependencies.packageDependencies['@teambit/legacy'];
384
+ }
385
+ if (this.allPackagesDependencies.devPackageDependencies['@teambit/legacy']) {
386
+ if (!version) version = this.allPackagesDependencies.devPackageDependencies['@teambit/legacy'];
387
+ delete this.allPackagesDependencies.devPackageDependencies['@teambit/legacy'];
388
+ }
389
+ if (version) {
390
+ if (!Number.isNaN(version[0])) version = `^${version}`;
391
+ this.allPackagesDependencies.peerPackageDependencies['@teambit/legacy'] = version;
392
+ }
393
+ }
394
+
395
+ private async applyAutoDetectOverridesOnComponent(): Promise<void> {
396
+ const autoDetectOverrides = this.autoDetectOverrides;
397
+
398
+ if (!autoDetectOverrides || !Object.keys(autoDetectOverrides).length) {
399
+ return;
400
+ }
401
+
402
+ const originallyExists: string[] = [];
403
+ let missingPackages: string[] = [];
404
+ // We want to also add missing packages to the peer list as we know to resolve the version from the env anyway
405
+ const missingData = this.issues.getIssueByName('MissingPackagesDependenciesOnFs')?.data as
406
+ | MissingPackagesData[]
407
+ | undefined;
408
+ if (missingData) {
409
+ missingPackages = uniq(missingData.map((d) => d.missingPackages).flat());
410
+ }
411
+ ['dependencies', 'devDependencies', 'peerDependencies'].forEach((field) => {
412
+ R.forEachObjIndexed((pkgVal, pkgName) => {
413
+ if (this.overridesDependencies.shouldIgnorePeerPackage(pkgName)) return;
414
+ // Validate it was auto detected, we only affect stuff that were detected
415
+ const existsInCompsDeps = this.allDependencies.dependencies.find((dep) => {
416
+ return dep.packageName === pkgName;
417
+ });
418
+
419
+ const existsInCompsDevDeps = this.allDependencies.devDependencies.find((dep) => {
420
+ return dep.packageName === pkgName;
421
+ });
422
+
423
+ if (
424
+ // We are checking originAllPackagesDependencies instead of allPackagesDependencies
425
+ // as it might be already removed from allPackagesDependencies at this point if it was set with
426
+ // "-" in runtime/dev
427
+ // in such case we still want to apply it here
428
+ !this.originAllPackagesDependencies.packageDependencies[pkgName] &&
429
+ !this.originAllPackagesDependencies.devPackageDependencies[pkgName] &&
430
+ !this.originAllPackagesDependencies.peerPackageDependencies[pkgName] &&
431
+ !existsInCompsDeps &&
432
+ !existsInCompsDevDeps &&
433
+ // Check if it was orignally exists in the component
434
+ // as we might have a policy which looks like this:
435
+ // "components": {
436
+ // "dependencies": {
437
+ // "my-dep": "-"
438
+ // },
439
+ // "devDependencies": {
440
+ // "my-dep": "1.0.0"
441
+ // },
442
+ // }
443
+ // in that case we might remove it before getting to the devDeps then we will think that it wasn't required in the component
444
+ // which is incorrect
445
+ !originallyExists.includes(pkgName) &&
446
+ !missingPackages.includes(pkgName)
447
+ ) {
448
+ return;
449
+ }
450
+ originallyExists.push(pkgName);
451
+ const key = DepsKeysToAllPackagesDepsKeys[field];
452
+
453
+ delete this.allPackagesDependencies[key][pkgName];
454
+ // When changing peer dependency we want it to be stronger than the other types
455
+ if (field === 'peerDependencies') {
456
+ delete this.allPackagesDependencies.devPackageDependencies[pkgName];
457
+ delete this.allPackagesDependencies.packageDependencies[pkgName];
458
+ if (existsInCompsDeps) {
459
+ this.allDependencies.dependencies = this.allDependencies.dependencies.filter(
460
+ (dep) => dep.packageName !== pkgName
461
+ );
462
+ }
463
+ if (existsInCompsDevDeps) {
464
+ this.allDependencies.devDependencies = this.allDependencies.devDependencies.filter(
465
+ (dep) => dep.packageName !== pkgName
466
+ );
467
+ }
468
+ }
469
+ // delete this.allPackagesDependencies.packageDependencies[pkgName];
470
+ // delete this.allPackagesDependencies.devPackageDependencies[pkgName];
471
+ // delete this.allPackagesDependencies.peerPackageDependencies[pkgName];
472
+
473
+ // If it exists in comps deps / comp dev deps, we don't want to add it to the allPackagesDependencies
474
+ // as it will make the same dep both a dev and runtime dep
475
+ // since we are here only for auto detected deps, it means we already resolved the version correctly
476
+ // so we don't need to really modify the version
477
+ // also the version here might have a range (^ or ~ for example) so we can't
478
+ // just put it as is, as it is not valid for component deps to have range
479
+ if (
480
+ pkgVal !== MANUALLY_REMOVE_DEPENDENCY &&
481
+ ((!existsInCompsDeps && !existsInCompsDevDeps) || field === 'peerDependencies')
482
+ ) {
483
+ this.allPackagesDependencies[key][pkgName] = pkgVal;
484
+ }
485
+ }, autoDetectOverrides[field]);
486
+ });
487
+ }
488
+
489
+ private async applyAutoDetectedPeersFromEnvOnEnvItSelf(): Promise<void> {
490
+ const envPolicy = await this.depsResolver.getEnvPolicyFromEnvLegacyId(this.component.id, this.component.files);
491
+ if (!envPolicy) return;
492
+ const envPolicyManifest = envPolicy.selfPolicy.toVersionManifest();
493
+
494
+ if (!envPolicyManifest || !Object.keys(envPolicyManifest).length) {
495
+ return;
496
+ }
497
+ const deps = this.allPackagesDependencies.packageDependencies || {};
498
+ // we are not iterate component deps since they are resolved from what actually installed
499
+ // the policy used for installation only in that case
500
+ ['packageDependencies', 'devPackageDependencies', 'peerPackageDependencies'].forEach((field) => {
501
+ R.forEachObjIndexed((_pkgVal, pkgName) => {
502
+ const peerVersionFromEnvPolicy = envPolicyManifest[pkgName];
503
+ if (peerVersionFromEnvPolicy) {
504
+ delete this.allPackagesDependencies[field][pkgName];
505
+ }
506
+ }, this.allPackagesDependencies[field]);
507
+ });
508
+ Object.assign(deps, envPolicyManifest);
509
+ // TODO: handle component deps once we support peers between components
510
+ this.allPackagesDependencies.packageDependencies = deps;
511
+ }
512
+
513
+ /**
514
+ * returns `package.json` of the component when it's imported, or `package.json` of the workspace
515
+ * when it's authored.
516
+ */
517
+ private _getPackageJson(): Record<string, any> | undefined {
518
+ return this.consumer?.packageJson.packageJsonObject;
519
+ }
520
+
521
+ private _getPackageJsonFromComponentModel(): Record<string, any> | undefined {
522
+ if (this.componentFromModel && this.component.componentMap) {
523
+ // a component is imported but the package.json file is missing or never written
524
+ // read the values from the model
525
+ const packageJson = PackageJsonFile.createFromComponent(
526
+ this.component.componentMap.rootDir,
527
+ this.componentFromModel
528
+ );
529
+ return packageJson.packageJsonObject;
530
+ }
531
+ return undefined;
532
+ }
533
+
534
+ private setLegacyInsideHarmonyIssue() {
535
+ if (this.componentFromModel && this.componentFromModel.isLegacy) {
536
+ this.issues.getOrCreate(IssuesClasses.LegacyInsideHarmony).data = true;
537
+ }
538
+ }
539
+
540
+ private _pkgFieldMapping(field: string) {
541
+ switch (field) {
542
+ case 'dependencies':
543
+ return 'packageDependencies';
544
+ case 'devDependencies':
545
+ return 'devPackageDependencies';
546
+ case 'peerDependencies':
547
+ return 'peerPackageDependencies';
548
+ default:
549
+ throw new Error(`${field} is not recognized`);
550
+ }
551
+ }
552
+ }