@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,47 @@
1
+ import { IssuesList } from '@teambit/component-issues';
2
+ import { Dependency } from '@teambit/legacy/dist/consumer/component/dependencies';
3
+ import { ManuallyChangedDependencies } from '@teambit/legacy/dist/consumer/component/consumer-component';
4
+ import { AllDependencies, AllPackagesDependencies } from './apply-overrides';
5
+
6
+ export type OverridesDependenciesData = {
7
+ manuallyRemovedDependencies: ManuallyChangedDependencies;
8
+ manuallyAddedDependencies: ManuallyChangedDependencies;
9
+ missingPackageDependencies: string[];
10
+ };
11
+
12
+ export class DependenciesData {
13
+ constructor(
14
+ public allDependencies: AllDependencies,
15
+ public allPackagesDependencies: AllPackagesDependencies,
16
+ public issues: IssuesList,
17
+ public coreAspects: string[]
18
+ ) {}
19
+
20
+ serialize(): string {
21
+ const { issues, allDependencies, ...rest } = this;
22
+ return JSON.stringify({
23
+ ...rest,
24
+ issues: issues.serialize(),
25
+ allDependencies: {
26
+ dependencies: allDependencies.dependencies.map((dep) => dep.serialize()),
27
+ devDependencies: allDependencies.devDependencies.map((dep) => dep.serialize()),
28
+ },
29
+ // for backward compatibility. version < 1.5.1 expected this to be saved in the fs cache.
30
+ overridesDependencies: {
31
+ manuallyRemovedDependencies: {},
32
+ manuallyAddedDependencies: {},
33
+ missingPackageDependencies: [],
34
+ },
35
+ });
36
+ }
37
+
38
+ static deserialize(data: string): DependenciesData {
39
+ const dataParsed = JSON.parse(data);
40
+ const dependencies = dataParsed.allDependencies.dependencies.map((dep) => Dependency.deserialize(dep));
41
+ const devDependencies = dataParsed.allDependencies.devDependencies.map((dep) => Dependency.deserialize(dep));
42
+ const issuesList = IssuesList.deserialize(dataParsed.issues);
43
+ const allDependencies = { dependencies, devDependencies };
44
+ const coreAspects = dataParsed.coreAspects;
45
+ return new DependenciesData(allDependencies, dataParsed.allPackagesDependencies, issuesList, coreAspects);
46
+ }
47
+ }
@@ -0,0 +1,174 @@
1
+ import R from 'ramda';
2
+ import path from 'path';
3
+ import { uniq } from 'lodash';
4
+ import { IssuesClasses } from '@teambit/component-issues';
5
+ import { Consumer } from '@teambit/legacy/dist/consumer';
6
+ import logger from '@teambit/legacy/dist/logger/logger';
7
+ import { getLastModifiedComponentTimestampMs } from '@teambit/legacy/dist/utils/fs/last-modified';
8
+ import { ExtensionDataEntry } from '@teambit/legacy/dist/consumer/config';
9
+ import Component from '@teambit/legacy/dist/consumer/component/consumer-component';
10
+ import { DependencyLoaderOpts } from '@teambit/legacy/dist/consumer/component/component-loader';
11
+ import { COMPONENT_CONFIG_FILE_NAME } from '@teambit/legacy/dist/constants';
12
+ import { Workspace } from '@teambit/workspace';
13
+ import DependencyResolverAspect, { DependencyResolverMain } from '@teambit/dependency-resolver';
14
+ import { DevFilesMain } from '@teambit/dev-files';
15
+ import { AspectLoaderMain } from '@teambit/aspect-loader';
16
+ import { DependenciesData } from './dependencies-data';
17
+ import { updateDependenciesVersions } from './dependencies-versions-resolver';
18
+ import { AutoDetectDeps, DebugDependencies } from './auto-detect-deps';
19
+ import OverridesDependencies from './overrides-dependencies';
20
+ import { ApplyOverrides } from './apply-overrides';
21
+
22
+ export class DependenciesLoader {
23
+ private idStr: string;
24
+ private consumer: Consumer;
25
+ constructor(
26
+ private component: Component,
27
+ private workspace: Workspace,
28
+ private depsResolver: DependencyResolverMain,
29
+ private devFiles: DevFilesMain,
30
+ private aspectLoader: AspectLoaderMain,
31
+ private opts: DependencyLoaderOpts
32
+ ) {
33
+ this.consumer = this.workspace.consumer;
34
+ this.idStr = this.component.id.toString();
35
+ }
36
+ async load() {
37
+ const { dependenciesData, debugDependenciesData } = await this.getDependenciesData();
38
+ const applyOverrides = new ApplyOverrides(this.component, this.depsResolver, this.workspace);
39
+ applyOverrides.allDependencies = dependenciesData.allDependencies;
40
+ applyOverrides.allPackagesDependencies = dependenciesData.allPackagesDependencies;
41
+ if (debugDependenciesData) {
42
+ // if it's coming from the cache, it's empty
43
+ applyOverrides.debugDependenciesData = debugDependenciesData;
44
+ }
45
+ applyOverrides.issues = dependenciesData.issues;
46
+ const results = await applyOverrides.getDependenciesData();
47
+ this.setDependenciesDataOnComponent(results.dependenciesData, results.overridesDependencies);
48
+ updateDependenciesVersions(
49
+ this.depsResolver,
50
+ this.workspace,
51
+ this.component,
52
+ results.overridesDependencies,
53
+ results.autoDetectOverrides,
54
+ applyOverrides.debugDependenciesData.components
55
+ );
56
+
57
+ return {
58
+ dependenciesData: results.dependenciesData,
59
+ overridesDependencies: results.overridesDependencies,
60
+ debugDependenciesData: applyOverrides.debugDependenciesData,
61
+ };
62
+ }
63
+
64
+ private async getDependenciesData(): Promise<{
65
+ dependenciesData: DependenciesData;
66
+ debugDependenciesData?: DebugDependencies;
67
+ }> {
68
+ const depsDataFromCache = await this.getDependenciesDataFromCacheIfPossible();
69
+ if (depsDataFromCache) {
70
+ return { dependenciesData: depsDataFromCache };
71
+ }
72
+
73
+ const autoDetectDeps = new AutoDetectDeps(
74
+ this.component,
75
+ this.workspace,
76
+ this.devFiles,
77
+ this.depsResolver,
78
+ this.aspectLoader
79
+ );
80
+ const results = await autoDetectDeps.getDependenciesData(
81
+ this.opts.cacheResolvedDependencies,
82
+ this.opts.cacheProjectAst
83
+ );
84
+ if (this.shouldSaveInCache(results.dependenciesData)) {
85
+ await this.consumer.componentFsCache.saveDependenciesDataInCache(
86
+ this.idStr,
87
+ results.dependenciesData.serialize()
88
+ );
89
+ }
90
+
91
+ return results;
92
+ }
93
+
94
+ private async getDependenciesDataFromCacheIfPossible(): Promise<DependenciesData | null> {
95
+ if (!this.opts.useDependenciesCache) {
96
+ return null;
97
+ }
98
+ const cacheData = await this.consumer.componentFsCache.getDependenciesDataFromCache(this.idStr);
99
+ if (!cacheData) {
100
+ return null; // probably the first time, so it wasn't entered to the cache yet.
101
+ }
102
+ const rootDir = this.component.componentMap?.getComponentDir();
103
+ if (!rootDir) {
104
+ // could happen on legacy only and when there is no trackDir, in which case, we can't
105
+ // determine whether or not a component file has been deleted, as a result, we are unable
106
+ // to invalidate the cache in such a case.
107
+ return null;
108
+ }
109
+ const filesPaths = this.component.files.map((f) => f.path);
110
+ const componentConfigPath = path.join(this.consumer.getPath(), rootDir, COMPONENT_CONFIG_FILE_NAME);
111
+ filesPaths.push(componentConfigPath);
112
+ const lastModifiedComponent = await getLastModifiedComponentTimestampMs(rootDir, filesPaths);
113
+ const wasModifiedAfterCache = lastModifiedComponent > cacheData.timestamp;
114
+ if (wasModifiedAfterCache) {
115
+ return null; // cache is invalid.
116
+ }
117
+ logger.debug(`dependencies-loader, getting the dependencies data for ${this.idStr} from the cache`);
118
+ return DependenciesData.deserialize(cacheData.data);
119
+ }
120
+
121
+ private shouldSaveInCache(dependenciesData: DependenciesData) {
122
+ if (!dependenciesData.issues) return true;
123
+ return !dependenciesData.issues.shouldBlockSavingInCache();
124
+ }
125
+
126
+ private setDependenciesDataOnComponent(
127
+ dependenciesData: DependenciesData,
128
+ overridesDependencies: OverridesDependencies
129
+ ) {
130
+ this.component.setDependencies(dependenciesData.allDependencies.dependencies);
131
+ this.component.setDevDependencies(dependenciesData.allDependencies.devDependencies);
132
+ this.component.packageDependencies = dependenciesData.allPackagesDependencies.packageDependencies ?? {};
133
+ this.component.devPackageDependencies = dependenciesData.allPackagesDependencies.devPackageDependencies ?? {};
134
+ this.component.peerPackageDependencies = dependenciesData.allPackagesDependencies.peerPackageDependencies ?? {};
135
+ const missingFromOverrides = overridesDependencies.missingPackageDependencies;
136
+ if (!R.isEmpty(missingFromOverrides)) {
137
+ dependenciesData.issues.getOrCreate(IssuesClasses.MissingManuallyConfiguredPackages).data =
138
+ uniq(missingFromOverrides);
139
+ }
140
+ if (!dependenciesData.issues.isEmpty()) this.component.issues = dependenciesData.issues;
141
+ this.component.manuallyRemovedDependencies = overridesDependencies.manuallyRemovedDependencies;
142
+ this.component.manuallyAddedDependencies = overridesDependencies.manuallyAddedDependencies;
143
+ if (dependenciesData.coreAspects.length) {
144
+ this.pushToDependencyResolverExtension('coreAspects', dependenciesData.coreAspects, 'set');
145
+ }
146
+ }
147
+
148
+ private pushToDependencyResolverExtension(dataField: string, data: any, operation: 'add' | 'set' = 'add') {
149
+ const depResolverAspectName = DependencyResolverAspect.id;
150
+ let extExistOnComponent = true;
151
+ let ext = this.component.extensions.findCoreExtension(depResolverAspectName);
152
+ if (!ext) {
153
+ extExistOnComponent = false;
154
+ // Create new deps resolver extension entry to add to the component with data only
155
+ ext = new ExtensionDataEntry(undefined, undefined, depResolverAspectName, undefined, {});
156
+ }
157
+
158
+ if (!ext.data[dataField]) ext.data[dataField] = [];
159
+ if (operation === 'add') {
160
+ const existing = ext.data[dataField].find((c) => c.packageName === data.packageName);
161
+ if (existing) {
162
+ existing.componentId = data.componentId;
163
+ } else {
164
+ ext.data[dataField].push(data);
165
+ }
166
+ }
167
+ if (operation === 'set') {
168
+ ext.data[dataField] = data;
169
+ }
170
+ if (!extExistOnComponent) {
171
+ this.component.extensions.push(ext);
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,160 @@
1
+ import R from 'ramda';
2
+ import { ComponentID } from '@teambit/component-id';
3
+ import Consumer from '@teambit/legacy/dist/consumer/consumer';
4
+ import { Workspace } from '@teambit/workspace';
5
+ import logger from '@teambit/legacy/dist/logger/logger';
6
+ import Component from '@teambit/legacy/dist/consumer/component/consumer-component';
7
+ import { ExtensionDataEntry, ExtensionDataList } from '@teambit/legacy/dist/consumer/config/extension-data';
8
+ import Dependencies from '@teambit/legacy/dist/consumer/component/dependencies/dependencies';
9
+ import { DependencyResolverMain } from '@teambit/dependency-resolver';
10
+ import { DEPENDENCIES_FIELDS } from '@teambit/legacy/dist/constants';
11
+ import Dependency from '@teambit/legacy/dist/consumer/component/dependencies/dependency';
12
+ import OverridesDependencies from './overrides-dependencies';
13
+ import { DebugComponentsDependency, getValidVersion } from './auto-detect-deps';
14
+
15
+ export function updateDependenciesVersions(
16
+ depsResolver: DependencyResolverMain,
17
+ workspace: Workspace,
18
+ component: Component,
19
+ overridesDependencies: OverridesDependencies,
20
+ autoDetectOverrides?: Record<string, any>,
21
+ debugDependencies?: DebugComponentsDependency[]
22
+ ) {
23
+ const consumer: Consumer = workspace.consumer;
24
+ const autoDetectConfigMerge = workspace.getAutoDetectConfigMerge(component.id) || {};
25
+
26
+ updateDependencies(component.dependencies);
27
+ updateDependencies(component.devDependencies);
28
+ updateExtensions(component.extensions);
29
+
30
+ /**
31
+ * the `pkg` can be missing only in two scenarios:
32
+ * 1: the dependency is using relative-paths, not the module path. (which bit-status shows an error and suggests
33
+ * running bit link --rewire).
34
+ * 2: this gets called for extension-id.
35
+ */
36
+ function resolveVersion(id: ComponentID, pkg?: string): string | undefined {
37
+ const idFromBitMap = getIdFromBitMap(id);
38
+ const idFromComponentConfig = getIdFromComponentConfig(id);
39
+ const getFromComponentConfig = () => idFromComponentConfig;
40
+ const getFromBitMap = () => idFromBitMap || null;
41
+ // later, change this to return the version from the overrides.
42
+ const getFromOverrides = () => (pkg && isPkgInOverrides(pkg) ? id : null);
43
+ const debugDep = debugDependencies?.find((dep) => dep.id.isEqualWithoutVersion(id));
44
+ // the id we get from the auto-detect is coming from the package.json of the dependency.
45
+ const getFromDepPackageJson = () => (id.hasVersion() ? id : null);
46
+ // In case it's resolved from the node_modules, and it's also in the ws policy or variants,
47
+ // use the resolved version from the node_modules / package folder
48
+ const getFromDepPackageJsonDueToWorkspacePolicy = () =>
49
+ pkg && id.hasVersion() && isPkgInWorkspacePolicies(pkg) ? id : null;
50
+ // merge config here is only auto-detected ones. their priority is less then the ws policy
51
+ // otherwise, imagine you merge a lane, you don't like the dependency you got from the other lane, you run
52
+ // bit-install to change it, but it won't do anything.
53
+ const getFromMergeConfig = () => (pkg ? resolveFromMergeConfig(id, pkg) : null);
54
+ const getFromDepPackageJsonDueToAutoDetectOverrides = () => (pkg && isPkgInAutoDetectOverrides(pkg) ? id : null);
55
+ // If there is a version in the node_modules/package folder, but it's not in the ws policy,
56
+ // prefer the version from the model over the version from the node_modules
57
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
58
+ const getFromModel = () => getIdFromModelDeps(component.componentFromModel!, id);
59
+
60
+ const strategies = [
61
+ getFromComponentConfig,
62
+ getFromOverrides,
63
+ getFromBitMap,
64
+ getFromDepPackageJsonDueToWorkspacePolicy,
65
+ getFromMergeConfig,
66
+ getFromDepPackageJsonDueToAutoDetectOverrides,
67
+ getFromModel,
68
+ getFromDepPackageJson,
69
+ ];
70
+
71
+ for (const strategy of strategies) {
72
+ const strategyId = strategy();
73
+ if (strategyId) {
74
+ logger.debug(
75
+ `found dependency version ${strategyId.version} for ${id.toString()} in strategy ${strategy.name}`
76
+ );
77
+ if (debugDep) {
78
+ debugDep.versionResolvedFrom = strategy.name.replace('getFrom', '');
79
+ debugDep.version = strategyId.version;
80
+ }
81
+
82
+ return strategyId.version;
83
+ }
84
+ }
85
+ return undefined;
86
+ }
87
+
88
+ function updateDependency(dependency: Dependency) {
89
+ const { id, packageName } = dependency;
90
+ const resolvedVersion = resolveVersion(id, packageName);
91
+ if (resolvedVersion) {
92
+ dependency.id = dependency.id.changeVersion(resolvedVersion);
93
+ }
94
+ }
95
+ function updateDependencies(dependencies: Dependencies) {
96
+ dependencies.get().forEach(updateDependency);
97
+ }
98
+
99
+ function updateExtension(extension: ExtensionDataEntry) {
100
+ if (extension.extensionId) {
101
+ const resolvedVersion = resolveVersion(extension.extensionId);
102
+ if (resolvedVersion) {
103
+ extension.extensionId = extension.extensionId.changeVersion(resolvedVersion);
104
+ }
105
+ }
106
+ }
107
+ function updateExtensions(extensions: ExtensionDataList) {
108
+ extensions.forEach(updateExtension);
109
+ }
110
+
111
+ function getIdFromModelDeps(componentFromModel: Component, componentId: ComponentID): ComponentID | null {
112
+ if (!componentFromModel) return null;
113
+ const dependency = componentFromModel.getAllDependenciesIds().searchWithoutVersion(componentId);
114
+ if (!dependency) return null;
115
+ return dependency;
116
+ }
117
+
118
+ function getIdFromBitMap(componentId: ComponentID): ComponentID | null | undefined {
119
+ const existingIds = consumer.bitmapIdsFromCurrentLane.filterWithoutVersion(componentId);
120
+ return existingIds.length === 1 ? existingIds[0] : undefined;
121
+ }
122
+
123
+ function getIdFromComponentConfig(componentId: ComponentID): ComponentID | undefined {
124
+ const dependencies = component.overrides.getComponentDependenciesWithVersion();
125
+ if (R.isEmpty(dependencies)) return undefined;
126
+ const dependency = Object.keys(dependencies).find((idStr) => componentId.toStringWithoutVersion() === idStr);
127
+ if (!dependency) return undefined;
128
+ return componentId.changeVersion(dependencies[dependency]);
129
+ }
130
+
131
+ function isPkgInOverrides(pkgName: string): boolean {
132
+ const dependencies = overridesDependencies.getDependenciesToAddManually();
133
+ if (!dependencies) return false;
134
+ const allDeps = Object.values(dependencies)
135
+ .map((obj) => Object.keys(obj))
136
+ .flat();
137
+ return allDeps.includes(pkgName);
138
+ }
139
+
140
+ function isPkgInAutoDetectOverrides(pkgName: string): boolean {
141
+ return DEPENDENCIES_FIELDS.some(
142
+ (depField) => autoDetectOverrides?.[depField] && autoDetectOverrides[depField][pkgName]
143
+ );
144
+ }
145
+
146
+ function isPkgInWorkspacePolicies(pkgName: string) {
147
+ return depsResolver.getWorkspacePolicyManifest().dependencies?.[pkgName];
148
+ }
149
+
150
+ function resolveFromMergeConfig(id: ComponentID, pkgName: string) {
151
+ let foundVersion: string | undefined | null;
152
+ DEPENDENCIES_FIELDS.forEach((field) => {
153
+ if (autoDetectConfigMerge[field]?.[pkgName]) {
154
+ foundVersion = autoDetectConfigMerge[field]?.[pkgName];
155
+ foundVersion = foundVersion ? getValidVersion(foundVersion) : null;
156
+ }
157
+ });
158
+ return foundVersion ? id.changeVersion(foundVersion) : undefined;
159
+ }
160
+ }
@@ -0,0 +1,2 @@
1
+ export { DependenciesLoader } from './dependencies-loader';
2
+ export { ApplyOverrides } from './apply-overrides';
@@ -0,0 +1,115 @@
1
+ import {
2
+ DEPENDENCIES_FIELDS,
3
+ MANUALLY_ADD_DEPENDENCY,
4
+ MANUALLY_REMOVE_DEPENDENCY,
5
+ } from '@teambit/legacy/dist/constants';
6
+ import logger from '@teambit/legacy/dist/logger/logger';
7
+ import Component, { ManuallyChangedDependencies } from '@teambit/legacy/dist/consumer/component/consumer-component';
8
+ import { FileType } from './auto-detect-deps';
9
+
10
+ export default class OverridesDependencies {
11
+ component: Component;
12
+ componentFromModel: Component | null | undefined;
13
+ manuallyRemovedDependencies: ManuallyChangedDependencies;
14
+ manuallyAddedDependencies: ManuallyChangedDependencies;
15
+ missingPackageDependencies: string[];
16
+ constructor(component: Component) {
17
+ this.component = component;
18
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
19
+ this.componentFromModel = this.component.componentFromModel;
20
+ this.manuallyRemovedDependencies = {};
21
+ this.manuallyAddedDependencies = {};
22
+ this.missingPackageDependencies = [];
23
+ }
24
+
25
+ shouldIgnorePackage(packageName: string, fileType: FileType): boolean {
26
+ const field = fileType.isTestFile ? 'devDependencies' : 'dependencies';
27
+ return this.shouldIgnorePackageByType(packageName, field);
28
+ }
29
+
30
+ shouldIgnorePackageByType(packageName: string, field: string): boolean {
31
+ const shouldIgnorePackage = (packages: string[]) => {
32
+ return packages.some((pkg) => pkg === packageName);
33
+ };
34
+ const ignoreField = this.component.overrides.getIgnoredPackages(field);
35
+ const ignore = shouldIgnorePackage(ignoreField);
36
+ if (ignore) {
37
+ this._addManuallyRemovedDep(field, packageName);
38
+ }
39
+ return ignore;
40
+ }
41
+
42
+ shouldIgnorePeerPackage(packageName: string): boolean {
43
+ const shouldIgnorePackage = (packages: string[]) => {
44
+ return packages.some((pkg) => pkg === packageName);
45
+ };
46
+ const field = 'peerDependencies';
47
+ const ignorePeer = this.component.overrides.getIgnoredPackages(field);
48
+ const ignore = shouldIgnorePackage(ignorePeer);
49
+ if (ignore) {
50
+ this._addManuallyRemovedDep(field, packageName);
51
+ }
52
+ return ignore;
53
+ }
54
+
55
+ getDependenciesToAddManually(): Record<string, any> | undefined {
56
+ const overrides = this.component.overrides.componentOverridesData;
57
+ if (!overrides) return undefined;
58
+ const packages = {};
59
+ DEPENDENCIES_FIELDS.forEach((depField) => {
60
+ if (!overrides[depField]) return;
61
+ Object.keys(overrides[depField]).forEach((dependency) => {
62
+ const dependencyValue = overrides[depField][dependency];
63
+ if (dependencyValue === MANUALLY_REMOVE_DEPENDENCY) return;
64
+ (packages[depField] ||= {})[dependency] = dependencyValue;
65
+ });
66
+ });
67
+ return packages;
68
+ }
69
+
70
+ _manuallyAddPackage(
71
+ field: string,
72
+ dependency: string,
73
+ dependencyValue: string,
74
+ packageJson: Record<string, any> | null | undefined
75
+ ): Record<string, any> | null | undefined {
76
+ const packageVersionToAdd = (): string | null | undefined => {
77
+ if (dependencyValue !== MANUALLY_ADD_DEPENDENCY) {
78
+ return dependencyValue;
79
+ }
80
+ if (!packageJson) return null;
81
+ for (const depField of DEPENDENCIES_FIELDS) {
82
+ if (packageJson[depField]) {
83
+ const found = Object.keys(packageJson[depField]).find((pkg) => pkg === dependency);
84
+ if (found) return packageJson[depField][dependency];
85
+ }
86
+ }
87
+ return null;
88
+ };
89
+ const versionToAdd = packageVersionToAdd();
90
+ if (!versionToAdd) {
91
+ logger.debug(`unable to manually add the dependency "${dependency}" into "${this.component.id.toString()}".
92
+ it's not an existing component, nor existing package (in a package.json)`);
93
+ this.missingPackageDependencies.push(dependency);
94
+ return undefined;
95
+ }
96
+ const packageStr = `${dependency}@${versionToAdd}`;
97
+ this._addManuallyAddedDep(field, packageStr);
98
+
99
+ return { [dependency]: versionToAdd };
100
+ }
101
+
102
+ _addManuallyRemovedDep(field: string, value: string) {
103
+ this.manuallyRemovedDependencies[field]
104
+ ? this.manuallyRemovedDependencies[field].push(value)
105
+ : (this.manuallyRemovedDependencies[field] = [value]);
106
+ }
107
+
108
+ _addManuallyAddedDep(field: string, value: string) {
109
+ if (this.manuallyAddedDependencies?.[field]?.includes(value)) return;
110
+
111
+ this.manuallyAddedDependencies[field]
112
+ ? this.manuallyAddedDependencies[field].push(value)
113
+ : (this.manuallyAddedDependencies[field] = [value]);
114
+ }
115
+ }
@@ -0,0 +1,53 @@
1
+ import { expect } from 'chai';
2
+ import { packageToDefinetlyTyped } from './package-to-definetly-typed';
3
+
4
+ const scenarios = new Map([
5
+ ['@testing-library/jest-dom', '@types/testing-library__jest-dom'],
6
+ ['chai', '@types/chai'],
7
+ ['mocha', '@types/mocha'],
8
+
9
+ ['classnames', '@types/classnames'],
10
+ ['cors', '@types/cors'],
11
+ ['cross-spawn', '@types/cross-spawn'],
12
+ ['dagre', '@types/dagre'],
13
+ ['didyoumean', '@types/didyoumean'],
14
+ ['eslint', '@types/eslint'],
15
+ ['express', '@types/express'],
16
+ ['find-cache-dir', '@types/find-cache-dir'],
17
+ ['find-root', '@types/find-root'],
18
+ ['history', '@types/history'],
19
+ ['http-proxy-agent', '@types/http-proxy-agent'],
20
+ ['lodash', '@types/lodash'],
21
+ ['lodash.compact', '@types/lodash.compact'],
22
+ ['lodash.flatten', '@types/lodash.flatten'],
23
+ ['lodash.head', '@types/lodash.head'],
24
+ ['lodash.pick', '@types/lodash.pick'],
25
+ ['@mdx-js/react', '@types/mdx-js__react'],
26
+ ['memoizee', '@types/memoizee'],
27
+ ['mime', '@types/mime'],
28
+ ['mousetrap', '@types/mousetrap'],
29
+ ['node', '@types/node'],
30
+ ['puppeteer', '@types/puppeteer'],
31
+ ['react', '@types/react'],
32
+ ['react-dom', '@types/react-dom'],
33
+ ['react-router-dom', '@types/react-router-dom'],
34
+ ['react-tabs', '@types/react-tabs'],
35
+ ['react-tooltip', '@types/react-tooltip'],
36
+ ['socket.io-client', '@types/socket.io-client'],
37
+ ['ua-parser-js', '@types/ua-parser-js'],
38
+ ['url-join', '@types/url-join'],
39
+ ['url-parse', '@types/url-parse'],
40
+ ['webpack', '@types/webpack'],
41
+ ['webpack-dev-server', '@types/webpack-dev-server'],
42
+ ['webpack-merge', '@types/webpack-merge'],
43
+ ]);
44
+
45
+ describe('packageToDefinetlyTyped()', () => {
46
+ scenarios.forEach((expected, input) => {
47
+ it(`should map to ${expected}`, () => {
48
+ const result = packageToDefinetlyTyped(input);
49
+
50
+ expect(result).to.equal(expected);
51
+ });
52
+ });
53
+ });
@@ -0,0 +1,10 @@
1
+ const scopedRegistryRegex = /^(@([-\w]+)\/)/;
2
+ const scopedRegistryReplace = '$2__';
3
+
4
+ // it seems definetly typed are using this:
5
+ // `const dtsName = packageName.replace("@", "").replace("/", "__")`
6
+
7
+ export function packageToDefinetlyTyped(pkgName: string) {
8
+ const escaped = pkgName.replace(scopedRegistryRegex, scopedRegistryReplace);
9
+ return `@types/${escaped}`;
10
+ }
@@ -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'`