@teambit/workspace.modules.node-modules-linker 0.0.1

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.
@@ -0,0 +1 @@
1
+ export { NodeModulesLinksResult, linkToNodeModules, linkToNodeModulesWithCodemod } from './node-modules-linker';
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.linkToNodeModulesWithCodemod = exports.linkToNodeModules = void 0;
4
+ var node_modules_linker_1 = require("./node-modules-linker");
5
+ Object.defineProperty(exports, "linkToNodeModules", { enumerable: true, get: function () { return node_modules_linker_1.linkToNodeModules; } });
6
+ Object.defineProperty(exports, "linkToNodeModulesWithCodemod", { enumerable: true, get: function () { return node_modules_linker_1.linkToNodeModulesWithCodemod; } });
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;AAAA,6DAAgH;AAA/E,wHAAA,iBAAiB,OAAA;AAAE,mIAAA,4BAA4B,OAAA"}
@@ -0,0 +1,75 @@
1
+ import { BitId } from '@teambit/legacy-bit-id';
2
+ import BitMap from '@teambit/legacy/dist/consumer/bit-map/bit-map';
3
+ import Component from '@teambit/legacy/dist/consumer/component/consumer-component';
4
+ import PackageJsonFile from '@teambit/legacy/dist/consumer/component/package-json-file';
5
+ import DataToPersist from '@teambit/legacy/dist/consumer/component/sources/data-to-persist';
6
+ import Consumer from '@teambit/legacy/dist/consumer/consumer';
7
+ import { PathOsBasedRelative } from '@teambit/legacy/dist/utils/path';
8
+ import Symlink from '@teambit/legacy/dist/links/symlink';
9
+ import { Workspace } from '@teambit/workspace';
10
+ declare type LinkDetail = {
11
+ from: string;
12
+ to: string;
13
+ };
14
+ export declare type NodeModulesLinksResult = {
15
+ id: BitId;
16
+ bound: LinkDetail[];
17
+ };
18
+ /**
19
+ * link given components to node_modules, so it's possible to use absolute link instead of relative
20
+ * for example, require('@bit/remote-scope.bar.foo)
21
+ */
22
+ export default class NodeModuleLinker {
23
+ components: Component[];
24
+ consumer: Consumer;
25
+ bitMap: BitMap;
26
+ dataToPersist: DataToPersist;
27
+ constructor(components: Component[], consumer: Consumer);
28
+ link(): Promise<NodeModulesLinksResult[]>;
29
+ getLinks(): Promise<DataToPersist>;
30
+ getLinksResults(): NodeModulesLinksResult[];
31
+ _getDefaultScope(component?: Component): string | undefined | null;
32
+ /**
33
+ * even when an authored component has rootDir, we can't just symlink that rootDir to
34
+ * node_modules/rootDir. it could work only when the main-file is index.js, not for other cases.
35
+ * node expects the module inside node_modules to have either package.json with valid "main"
36
+ * property or an index.js file. this main property can't be relative.
37
+ */
38
+ _populateComponentsLinks(component: Component): Promise<void>;
39
+ /**
40
+ * symlink the entire source directory into "src" in node-modules.
41
+ */
42
+ private symlinkComponentDir;
43
+ /**
44
+ * Removing existing links root (the package path) - to handle cases it was linked by package manager for example
45
+ * this makes sure we are not affecting other places (like package manager cache) we shouldn't touch
46
+ * If you have a case when this deletes something created by the package manager and it's not the desired behavior,
47
+ * do not delete this code, but make sure the package manger nest the installed version into it's dependent
48
+ * @param component
49
+ */
50
+ _deleteExistingLinksRootIfSymlink(linkPath: string): any;
51
+ /**
52
+ * When the dists is outside the components directory, it doesn't have access to the node_modules of the component's
53
+ * root-dir. The solution is to go through the node_modules packages one by one and symlink them.
54
+ */
55
+ _getSymlinkPackages(from: string, to: string, component: Component): Symlink[];
56
+ _getDependencyLink(parentRootDir: PathOsBasedRelative, bitId: BitId, rootDir: PathOsBasedRelative, bindingPrefix: string, component: Component): Symlink;
57
+ /**
58
+ * create package.json on node_modules/@bit/component-name/package.json with a property 'main'
59
+ * pointing to the component's main file.
60
+ * It is needed for Authored components only.
61
+ * Since an authored component doesn't have rootDir, it's impossible to symlink to the component directory.
62
+ * It makes it easier for Author to use absolute syntax between their own components.
63
+ */
64
+ private createPackageJson;
65
+ /**
66
+ * these are changes made by aspects
67
+ */
68
+ _applyTransformers(component: Component, packageJson: PackageJsonFile): Promise<void>;
69
+ }
70
+ export declare function linkToNodeModulesWithCodemod(workspace: Workspace, bitIds: BitId[], changeRelativeToModulePaths: boolean): Promise<{
71
+ linksResults: NodeModulesLinksResult[];
72
+ codemodResults: any;
73
+ }>;
74
+ export declare function linkToNodeModules(workspace: Workspace, bitIds: BitId[], loadFromScope?: boolean): Promise<NodeModulesLinksResult[]>;
75
+ export {};
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.linkToNodeModules = exports.linkToNodeModulesWithCodemod = void 0;
39
+ const fs_extra_1 = __importDefault(require("fs-extra"));
40
+ const glob_1 = __importDefault(require("glob"));
41
+ const p_map_series_1 = __importDefault(require("p-map-series"));
42
+ const path = __importStar(require("path"));
43
+ const ramda_1 = __importDefault(require("ramda"));
44
+ const constants_1 = require("@teambit/legacy/dist/constants");
45
+ const components_list_1 = __importDefault(require("@teambit/legacy/dist/consumer/component/components-list"));
46
+ const package_json_file_1 = __importDefault(require("@teambit/legacy/dist/consumer/component/package-json-file"));
47
+ const package_json_transformer_1 = require("@teambit/legacy/dist/consumer/component/package-json-transformer");
48
+ const data_to_persist_1 = __importDefault(require("@teambit/legacy/dist/consumer/component/sources/data-to-persist"));
49
+ const remove_path_1 = __importDefault(require("@teambit/legacy/dist/consumer/component/sources/remove-path"));
50
+ const logger_1 = __importDefault(require("@teambit/legacy/dist/logger/logger"));
51
+ const utils_1 = require("@teambit/legacy/dist/utils");
52
+ const component_node_modules_path_1 = __importDefault(require("@teambit/legacy/dist/utils/bit/component-node-modules-path"));
53
+ const bit_id_1 = require("@teambit/legacy/dist/bit-id");
54
+ const codemod_components_1 = require("@teambit/legacy/dist/consumer/component-ops/codemod-components");
55
+ const symlink_1 = __importDefault(require("@teambit/legacy/dist/links/symlink"));
56
+ /**
57
+ * link given components to node_modules, so it's possible to use absolute link instead of relative
58
+ * for example, require('@bit/remote-scope.bar.foo)
59
+ */
60
+ class NodeModuleLinker {
61
+ constructor(components, consumer) {
62
+ this.components = components_list_1.default.getUniqueComponents(components);
63
+ this.consumer = consumer;
64
+ this.bitMap = consumer.bitMap;
65
+ this.dataToPersist = new data_to_persist_1.default();
66
+ }
67
+ link() {
68
+ var _a;
69
+ return __awaiter(this, void 0, void 0, function* () {
70
+ const links = yield this.getLinks();
71
+ const linksResults = this.getLinksResults();
72
+ if (this.consumer)
73
+ links.addBasePath(this.consumer.getPath());
74
+ yield links.persistAllToFS();
75
+ yield ((_a = this.consumer) === null || _a === void 0 ? void 0 : _a.componentFsCache.deleteAllDependenciesDataCache());
76
+ return linksResults;
77
+ });
78
+ }
79
+ getLinks() {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ this.dataToPersist = new data_to_persist_1.default();
82
+ // don't use Promise.all because down the road it calls transformPackageJson of pkg aspect, which loads components
83
+ yield (0, p_map_series_1.default)(this.components, (component) => {
84
+ const componentId = component.id.toString();
85
+ logger_1.default.debug(`linking component to node_modules: ${componentId}`);
86
+ const componentMap = this.bitMap.getComponent(component.id);
87
+ component.componentMap = componentMap;
88
+ return this._populateComponentsLinks(component);
89
+ });
90
+ return this.dataToPersist;
91
+ });
92
+ }
93
+ getLinksResults() {
94
+ const linksResults = [];
95
+ const getExistingLinkResult = (id) => linksResults.find((linkResult) => linkResult.id.isEqual(id));
96
+ const addLinkResult = (id, from, to) => {
97
+ if (!id)
98
+ return;
99
+ const existingLinkResult = getExistingLinkResult(id);
100
+ if (existingLinkResult) {
101
+ existingLinkResult.bound.push({ from, to });
102
+ }
103
+ else {
104
+ linksResults.push({ id, bound: [{ from, to }] });
105
+ }
106
+ };
107
+ this.dataToPersist.symlinks.forEach((symlink) => {
108
+ addLinkResult(symlink.componentId, symlink.src, symlink.dest);
109
+ });
110
+ this.components.forEach((component) => {
111
+ const existingLinkResult = getExistingLinkResult(component.id);
112
+ if (!existingLinkResult) {
113
+ linksResults.push({ id: component.id, bound: [] });
114
+ }
115
+ });
116
+ return linksResults;
117
+ }
118
+ _getDefaultScope(component) {
119
+ if (component) {
120
+ return component.defaultScope;
121
+ }
122
+ return this.consumer ? this.consumer.config.defaultScope : null;
123
+ }
124
+ /**
125
+ * even when an authored component has rootDir, we can't just symlink that rootDir to
126
+ * node_modules/rootDir. it could work only when the main-file is index.js, not for other cases.
127
+ * node expects the module inside node_modules to have either package.json with valid "main"
128
+ * property or an index.js file. this main property can't be relative.
129
+ */
130
+ _populateComponentsLinks(component) {
131
+ return __awaiter(this, void 0, void 0, function* () {
132
+ const componentId = component.id;
133
+ const linkPath = (0, component_node_modules_path_1.default)({
134
+ bindingPrefix: component.bindingPrefix,
135
+ id: componentId,
136
+ allowNonScope: true,
137
+ defaultScope: this._getDefaultScope(component),
138
+ extensions: component.extensions,
139
+ });
140
+ this.symlinkComponentDir(component, linkPath);
141
+ this._deleteExistingLinksRootIfSymlink(linkPath);
142
+ yield this.createPackageJson(component);
143
+ });
144
+ }
145
+ /**
146
+ * symlink the entire source directory into "src" in node-modules.
147
+ */
148
+ symlinkComponentDir(component, linkPath) {
149
+ const componentMap = component.componentMap;
150
+ const filesToBind = componentMap.getAllFilesPaths();
151
+ filesToBind.forEach((file) => {
152
+ const fileWithRootDir = path.join(componentMap.rootDir, file);
153
+ const dest = path.join(linkPath, file);
154
+ this.dataToPersist.addSymlink(symlink_1.default.makeInstance(fileWithRootDir, dest, component.id, true));
155
+ });
156
+ if (constants_1.IS_WINDOWS) {
157
+ this.dataToPersist.addSymlink(symlink_1.default.makeInstance(componentMap.rootDir, path.join(linkPath, constants_1.SOURCE_DIR_SYMLINK_TO_NM), component.id));
158
+ }
159
+ }
160
+ /**
161
+ * Removing existing links root (the package path) - to handle cases it was linked by package manager for example
162
+ * this makes sure we are not affecting other places (like package manager cache) we shouldn't touch
163
+ * If you have a case when this deletes something created by the package manager and it's not the desired behavior,
164
+ * do not delete this code, but make sure the package manger nest the installed version into it's dependent
165
+ * @param component
166
+ */
167
+ _deleteExistingLinksRootIfSymlink(linkPath) {
168
+ try {
169
+ const stat = fs_extra_1.default.lstatSync(linkPath);
170
+ if (stat.isSymbolicLink()) {
171
+ this.dataToPersist.removePath(new remove_path_1.default(linkPath));
172
+ }
173
+ return undefined;
174
+ }
175
+ catch (err) {
176
+ return undefined; // probably file does not exist
177
+ }
178
+ }
179
+ /**
180
+ * When the dists is outside the components directory, it doesn't have access to the node_modules of the component's
181
+ * root-dir. The solution is to go through the node_modules packages one by one and symlink them.
182
+ */
183
+ _getSymlinkPackages(from, to, component) {
184
+ if (!this.consumer)
185
+ throw new Error('getSymlinkPackages expects the Consumer to be defined');
186
+ const dependenciesSavedAsComponents = component.dependenciesSavedAsComponents;
187
+ const fromNodeModules = path.join(from, 'node_modules');
188
+ const toNodeModules = path.join(to, 'node_modules');
189
+ logger_1.default.debug(`symlinkPackages for dists outside the component directory from ${fromNodeModules} to ${toNodeModules}`);
190
+ const unfilteredDirs = glob_1.default.sync('*', { cwd: fromNodeModules });
191
+ // when dependenciesSavedAsComponents the node_modules/@bit has real link files, we don't want to touch them
192
+ // otherwise, node_modules/@bit has packages as any other directory in node_modules
193
+ const dirsToFilter = dependenciesSavedAsComponents ? [this.consumer.config._bindingPrefix] : [];
194
+ const customResolvedData = component.dependencies.getCustomResolvedData();
195
+ if (!ramda_1.default.isEmpty(customResolvedData)) {
196
+ // filter out packages that are actually symlinks to dependencies
197
+ Object.keys(customResolvedData).forEach((importSource) => dirsToFilter.push((0, utils_1.first)(importSource.split('/'))));
198
+ }
199
+ const dirs = dirsToFilter.length ? unfilteredDirs.filter((dir) => !dirsToFilter.includes(dir)) : unfilteredDirs;
200
+ if (!dirs.length)
201
+ return [];
202
+ return dirs.map((dir) => {
203
+ const fromDir = path.join(fromNodeModules, dir);
204
+ const toDir = path.join(toNodeModules, dir);
205
+ return symlink_1.default.makeInstance(fromDir, toDir);
206
+ });
207
+ }
208
+ _getDependencyLink(parentRootDir, bitId, rootDir, bindingPrefix, component) {
209
+ const relativeDestPath = (0, component_node_modules_path_1.default)(Object.assign(Object.assign({}, component), { id: bitId, allowNonScope: true, bindingPrefix, isDependency: true }));
210
+ const destPathInsideParent = path.join(parentRootDir, relativeDestPath);
211
+ return symlink_1.default.makeInstance(rootDir, destPathInsideParent, bitId);
212
+ }
213
+ /**
214
+ * create package.json on node_modules/@bit/component-name/package.json with a property 'main'
215
+ * pointing to the component's main file.
216
+ * It is needed for Authored components only.
217
+ * Since an authored component doesn't have rootDir, it's impossible to symlink to the component directory.
218
+ * It makes it easier for Author to use absolute syntax between their own components.
219
+ */
220
+ createPackageJson(component) {
221
+ return __awaiter(this, void 0, void 0, function* () {
222
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
223
+ const hasPackageJsonAsComponentFile = component.files.some((file) => file.relative === constants_1.PACKAGE_JSON);
224
+ if (hasPackageJsonAsComponentFile)
225
+ return; // don't generate package.json on top of the user package.json
226
+ const dest = path.join((0, component_node_modules_path_1.default)(Object.assign(Object.assign({}, component), { id: component.id, allowNonScope: true })));
227
+ const packageJson = package_json_file_1.default.createFromComponent(dest, component, true, true);
228
+ yield this._applyTransformers(component, packageJson);
229
+ if (constants_1.IS_WINDOWS) {
230
+ // in the workspace, override the "types" and add the "src" prefix.
231
+ // otherwise, the navigation and auto-complete won't work on the IDE.
232
+ // this is for Windows only. For Linux, we use symlinks for the files.
233
+ packageJson.addOrUpdateProperty('types', `${constants_1.SOURCE_DIR_SYMLINK_TO_NM}/${component.mainFile}`);
234
+ }
235
+ if (packageJson.packageJsonObject.version === 'latest') {
236
+ packageJson.packageJsonObject.version = '0.0.1-new';
237
+ }
238
+ // packageJson.mergePropsFromExtensions(component);
239
+ // TODO: we need to have an hook here to get the transformer from the pkg extension
240
+ // delete the version, otherwise, we have to maintains it. such as, when tagging, it should be
241
+ // changed to the new tagged version.
242
+ delete packageJson.packageJsonObject.version;
243
+ this.dataToPersist.addFile(packageJson.toVinylFile());
244
+ });
245
+ }
246
+ /**
247
+ * these are changes made by aspects
248
+ */
249
+ _applyTransformers(component, packageJson) {
250
+ return __awaiter(this, void 0, void 0, function* () {
251
+ return package_json_transformer_1.PackageJsonTransformer.applyTransformers(component, packageJson);
252
+ });
253
+ }
254
+ }
255
+ exports.default = NodeModuleLinker;
256
+ function linkToNodeModulesWithCodemod(workspace, bitIds, changeRelativeToModulePaths) {
257
+ return __awaiter(this, void 0, void 0, function* () {
258
+ let codemodResults;
259
+ if (changeRelativeToModulePaths) {
260
+ codemodResults = yield (0, codemod_components_1.changeCodeFromRelativeToModulePaths)(workspace.consumer, bitIds);
261
+ }
262
+ const linksResults = yield linkToNodeModules(workspace, bitIds);
263
+ return { linksResults, codemodResults };
264
+ });
265
+ }
266
+ exports.linkToNodeModulesWithCodemod = linkToNodeModulesWithCodemod;
267
+ function linkToNodeModules(workspace, bitIds, loadFromScope = false) {
268
+ return __awaiter(this, void 0, void 0, function* () {
269
+ const componentsIds = bit_id_1.BitIds.fromArray(bitIds);
270
+ if (!componentsIds.length)
271
+ return [];
272
+ const getComponents = () => __awaiter(this, void 0, void 0, function* () {
273
+ if (loadFromScope) {
274
+ return Promise.all(componentsIds.map((id) => workspace.consumer.loadComponentFromModel(id)));
275
+ }
276
+ const { components } = yield workspace.consumer.loadComponents(componentsIds);
277
+ return components;
278
+ });
279
+ const components = yield getComponents();
280
+ const nodeModuleLinker = new NodeModuleLinker(components, workspace.consumer);
281
+ return nodeModuleLinker.link();
282
+ });
283
+ }
284
+ exports.linkToNodeModules = linkToNodeModules;
285
+ //# sourceMappingURL=node-modules-linker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-modules-linker.js","sourceRoot":"","sources":["../node-modules-linker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ ;
2
+ ;
3
+
4
+ export const compositions = [];
5
+ export const overview = [];
6
+
7
+ export const compositions_metadata = {"compositions":[]};
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": [
4
+ "es2019",
5
+ "DOM",
6
+ "ES6",
7
+ "DOM.Iterable"
8
+ ],
9
+ "target": "es2015",
10
+ "module": "CommonJS",
11
+ "jsx": "react",
12
+ "allowJs": true,
13
+ "composite": true,
14
+ "declaration": true,
15
+ "sourceMap": true,
16
+ "skipLibCheck": true,
17
+ "experimentalDecorators": true,
18
+ "outDir": "dist",
19
+ "moduleResolution": "node",
20
+ "esModuleInterop": true,
21
+ "rootDir": ".",
22
+ "resolveJsonModule": true
23
+ },
24
+ "exclude": [
25
+ "dist",
26
+ "package.json"
27
+ ],
28
+ "include": [
29
+ "**/*",
30
+ "**/*.json"
31
+ ]
32
+ }
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { NodeModulesLinksResult, linkToNodeModules, linkToNodeModulesWithCodemod } from './node-modules-linker';
@@ -0,0 +1,288 @@
1
+ import fs from 'fs-extra';
2
+ import glob from 'glob';
3
+ import pMapSeries from 'p-map-series';
4
+ import * as path from 'path';
5
+ import R from 'ramda';
6
+ import { BitId } from '@teambit/legacy-bit-id';
7
+ import { IS_WINDOWS, PACKAGE_JSON, SOURCE_DIR_SYMLINK_TO_NM } from '@teambit/legacy/dist/constants';
8
+ import BitMap from '@teambit/legacy/dist/consumer/bit-map/bit-map';
9
+ import ComponentMap from '@teambit/legacy/dist/consumer/bit-map/component-map';
10
+ import ComponentsList from '@teambit/legacy/dist/consumer/component/components-list';
11
+ import Component from '@teambit/legacy/dist/consumer/component/consumer-component';
12
+ import PackageJsonFile from '@teambit/legacy/dist/consumer/component/package-json-file';
13
+ import { PackageJsonTransformer } from '@teambit/legacy/dist/consumer/component/package-json-transformer';
14
+ import DataToPersist from '@teambit/legacy/dist/consumer/component/sources/data-to-persist';
15
+ import RemovePath from '@teambit/legacy/dist/consumer/component/sources/remove-path';
16
+ import Consumer from '@teambit/legacy/dist/consumer/consumer';
17
+ import logger from '@teambit/legacy/dist/logger/logger';
18
+ import { first } from '@teambit/legacy/dist/utils';
19
+ import getNodeModulesPathOfComponent from '@teambit/legacy/dist/utils/bit/component-node-modules-path';
20
+ import { PathOsBasedRelative } from '@teambit/legacy/dist/utils/path';
21
+ import { BitIds } from '@teambit/legacy/dist/bit-id';
22
+ import { changeCodeFromRelativeToModulePaths } from '@teambit/legacy/dist/consumer/component-ops/codemod-components';
23
+ import Symlink from '@teambit/legacy/dist/links/symlink';
24
+ import { Workspace } from '@teambit/workspace';
25
+
26
+ type LinkDetail = { from: string; to: string };
27
+ export type NodeModulesLinksResult = {
28
+ id: BitId;
29
+ bound: LinkDetail[];
30
+ };
31
+
32
+ /**
33
+ * link given components to node_modules, so it's possible to use absolute link instead of relative
34
+ * for example, require('@bit/remote-scope.bar.foo)
35
+ */
36
+ export default class NodeModuleLinker {
37
+ components: Component[];
38
+ consumer: Consumer;
39
+ bitMap: BitMap; // preparation for the capsule, which is going to have only BitMap with no Consumer
40
+ dataToPersist: DataToPersist;
41
+ constructor(components: Component[], consumer: Consumer) {
42
+ this.components = ComponentsList.getUniqueComponents(components);
43
+ this.consumer = consumer;
44
+ this.bitMap = consumer.bitMap;
45
+ this.dataToPersist = new DataToPersist();
46
+ }
47
+ async link(): Promise<NodeModulesLinksResult[]> {
48
+ const links = await this.getLinks();
49
+ const linksResults = this.getLinksResults();
50
+ if (this.consumer) links.addBasePath(this.consumer.getPath());
51
+ await links.persistAllToFS();
52
+ await this.consumer?.componentFsCache.deleteAllDependenciesDataCache();
53
+ return linksResults;
54
+ }
55
+ async getLinks(): Promise<DataToPersist> {
56
+ this.dataToPersist = new DataToPersist();
57
+ // don't use Promise.all because down the road it calls transformPackageJson of pkg aspect, which loads components
58
+ await pMapSeries(this.components, (component) => {
59
+ const componentId = component.id.toString();
60
+ logger.debug(`linking component to node_modules: ${componentId}`);
61
+ const componentMap: ComponentMap = this.bitMap.getComponent(component.id);
62
+ component.componentMap = componentMap;
63
+ return this._populateComponentsLinks(component);
64
+ });
65
+
66
+ return this.dataToPersist;
67
+ }
68
+ getLinksResults(): NodeModulesLinksResult[] {
69
+ const linksResults: NodeModulesLinksResult[] = [];
70
+ const getExistingLinkResult = (id) => linksResults.find((linkResult) => linkResult.id.isEqual(id));
71
+ const addLinkResult = (id: BitId | null | undefined, from: string, to: string) => {
72
+ if (!id) return;
73
+ const existingLinkResult = getExistingLinkResult(id);
74
+ if (existingLinkResult) {
75
+ existingLinkResult.bound.push({ from, to });
76
+ } else {
77
+ linksResults.push({ id, bound: [{ from, to }] });
78
+ }
79
+ };
80
+ this.dataToPersist.symlinks.forEach((symlink: Symlink) => {
81
+ addLinkResult(symlink.componentId, symlink.src, symlink.dest);
82
+ });
83
+ this.components.forEach((component) => {
84
+ const existingLinkResult = getExistingLinkResult(component.id);
85
+ if (!existingLinkResult) {
86
+ linksResults.push({ id: component.id, bound: [] });
87
+ }
88
+ });
89
+ return linksResults;
90
+ }
91
+
92
+ _getDefaultScope(component?: Component): string | undefined | null {
93
+ if (component) {
94
+ return component.defaultScope;
95
+ }
96
+ return this.consumer ? this.consumer.config.defaultScope : null;
97
+ }
98
+
99
+ /**
100
+ * even when an authored component has rootDir, we can't just symlink that rootDir to
101
+ * node_modules/rootDir. it could work only when the main-file is index.js, not for other cases.
102
+ * node expects the module inside node_modules to have either package.json with valid "main"
103
+ * property or an index.js file. this main property can't be relative.
104
+ */
105
+ async _populateComponentsLinks(component: Component): Promise<void> {
106
+ const componentId = component.id;
107
+ const linkPath: PathOsBasedRelative = getNodeModulesPathOfComponent({
108
+ bindingPrefix: component.bindingPrefix,
109
+ id: componentId,
110
+ allowNonScope: true,
111
+ defaultScope: this._getDefaultScope(component),
112
+ extensions: component.extensions,
113
+ });
114
+
115
+ this.symlinkComponentDir(component, linkPath);
116
+ this._deleteExistingLinksRootIfSymlink(linkPath);
117
+ await this.createPackageJson(component);
118
+ }
119
+
120
+ /**
121
+ * symlink the entire source directory into "src" in node-modules.
122
+ */
123
+ private symlinkComponentDir(component: Component, linkPath: PathOsBasedRelative) {
124
+ const componentMap = component.componentMap as ComponentMap;
125
+
126
+ const filesToBind = componentMap.getAllFilesPaths();
127
+ filesToBind.forEach((file) => {
128
+ const fileWithRootDir = path.join(componentMap.rootDir as string, file);
129
+ const dest = path.join(linkPath, file);
130
+ this.dataToPersist.addSymlink(Symlink.makeInstance(fileWithRootDir, dest, component.id, true));
131
+ });
132
+
133
+ if (IS_WINDOWS) {
134
+ this.dataToPersist.addSymlink(
135
+ Symlink.makeInstance(
136
+ componentMap.rootDir as string,
137
+ path.join(linkPath, SOURCE_DIR_SYMLINK_TO_NM),
138
+ component.id
139
+ )
140
+ );
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Removing existing links root (the package path) - to handle cases it was linked by package manager for example
146
+ * this makes sure we are not affecting other places (like package manager cache) we shouldn't touch
147
+ * If you have a case when this deletes something created by the package manager and it's not the desired behavior,
148
+ * do not delete this code, but make sure the package manger nest the installed version into it's dependent
149
+ * @param component
150
+ */
151
+ _deleteExistingLinksRootIfSymlink(linkPath: string) {
152
+ try {
153
+ const stat = fs.lstatSync(linkPath);
154
+ if (stat.isSymbolicLink()) {
155
+ this.dataToPersist.removePath(new RemovePath(linkPath));
156
+ }
157
+ return undefined;
158
+ } catch (err: any) {
159
+ return undefined; // probably file does not exist
160
+ }
161
+ }
162
+
163
+ /**
164
+ * When the dists is outside the components directory, it doesn't have access to the node_modules of the component's
165
+ * root-dir. The solution is to go through the node_modules packages one by one and symlink them.
166
+ */
167
+ _getSymlinkPackages(from: string, to: string, component: Component): Symlink[] {
168
+ if (!this.consumer) throw new Error('getSymlinkPackages expects the Consumer to be defined');
169
+ const dependenciesSavedAsComponents = component.dependenciesSavedAsComponents;
170
+ const fromNodeModules = path.join(from, 'node_modules');
171
+ const toNodeModules = path.join(to, 'node_modules');
172
+ logger.debug(
173
+ `symlinkPackages for dists outside the component directory from ${fromNodeModules} to ${toNodeModules}`
174
+ );
175
+ const unfilteredDirs = glob.sync('*', { cwd: fromNodeModules });
176
+ // when dependenciesSavedAsComponents the node_modules/@bit has real link files, we don't want to touch them
177
+ // otherwise, node_modules/@bit has packages as any other directory in node_modules
178
+ const dirsToFilter = dependenciesSavedAsComponents ? [this.consumer.config._bindingPrefix] : [];
179
+ const customResolvedData = component.dependencies.getCustomResolvedData();
180
+ if (!R.isEmpty(customResolvedData)) {
181
+ // filter out packages that are actually symlinks to dependencies
182
+ Object.keys(customResolvedData).forEach((importSource) => dirsToFilter.push(first(importSource.split('/'))));
183
+ }
184
+ const dirs = dirsToFilter.length ? unfilteredDirs.filter((dir) => !dirsToFilter.includes(dir)) : unfilteredDirs;
185
+ if (!dirs.length) return [];
186
+ return dirs.map((dir) => {
187
+ const fromDir = path.join(fromNodeModules, dir);
188
+ const toDir = path.join(toNodeModules, dir);
189
+ return Symlink.makeInstance(fromDir, toDir);
190
+ });
191
+ }
192
+
193
+ _getDependencyLink(
194
+ parentRootDir: PathOsBasedRelative,
195
+ bitId: BitId,
196
+ rootDir: PathOsBasedRelative,
197
+ bindingPrefix: string,
198
+ component: Component
199
+ ): Symlink {
200
+ const relativeDestPath = getNodeModulesPathOfComponent({
201
+ ...component,
202
+ id: bitId,
203
+ allowNonScope: true,
204
+ bindingPrefix,
205
+ isDependency: true,
206
+ });
207
+ const destPathInsideParent = path.join(parentRootDir, relativeDestPath);
208
+ return Symlink.makeInstance(rootDir, destPathInsideParent, bitId);
209
+ }
210
+
211
+ /**
212
+ * create package.json on node_modules/@bit/component-name/package.json with a property 'main'
213
+ * pointing to the component's main file.
214
+ * It is needed for Authored components only.
215
+ * Since an authored component doesn't have rootDir, it's impossible to symlink to the component directory.
216
+ * It makes it easier for Author to use absolute syntax between their own components.
217
+ */
218
+ private async createPackageJson(component: Component) {
219
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
220
+ const hasPackageJsonAsComponentFile = component.files.some((file) => file.relative === PACKAGE_JSON);
221
+ if (hasPackageJsonAsComponentFile) return; // don't generate package.json on top of the user package.json
222
+ const dest = path.join(
223
+ getNodeModulesPathOfComponent({
224
+ ...component,
225
+ id: component.id,
226
+ allowNonScope: true,
227
+ })
228
+ );
229
+ const packageJson = PackageJsonFile.createFromComponent(dest, component, true, true);
230
+ await this._applyTransformers(component, packageJson);
231
+ if (IS_WINDOWS) {
232
+ // in the workspace, override the "types" and add the "src" prefix.
233
+ // otherwise, the navigation and auto-complete won't work on the IDE.
234
+ // this is for Windows only. For Linux, we use symlinks for the files.
235
+ packageJson.addOrUpdateProperty('types', `${SOURCE_DIR_SYMLINK_TO_NM}/${component.mainFile}`);
236
+ }
237
+ if (packageJson.packageJsonObject.version === 'latest') {
238
+ packageJson.packageJsonObject.version = '0.0.1-new';
239
+ }
240
+
241
+ // packageJson.mergePropsFromExtensions(component);
242
+ // TODO: we need to have an hook here to get the transformer from the pkg extension
243
+
244
+ // delete the version, otherwise, we have to maintains it. such as, when tagging, it should be
245
+ // changed to the new tagged version.
246
+ delete packageJson.packageJsonObject.version;
247
+ this.dataToPersist.addFile(packageJson.toVinylFile());
248
+ }
249
+
250
+ /**
251
+ * these are changes made by aspects
252
+ */
253
+ async _applyTransformers(component: Component, packageJson: PackageJsonFile) {
254
+ return PackageJsonTransformer.applyTransformers(component, packageJson);
255
+ }
256
+ }
257
+
258
+ export async function linkToNodeModulesWithCodemod(
259
+ workspace: Workspace,
260
+ bitIds: BitId[],
261
+ changeRelativeToModulePaths: boolean
262
+ ) {
263
+ let codemodResults;
264
+ if (changeRelativeToModulePaths) {
265
+ codemodResults = await changeCodeFromRelativeToModulePaths(workspace.consumer, bitIds);
266
+ }
267
+ const linksResults = await linkToNodeModules(workspace, bitIds);
268
+ return { linksResults, codemodResults };
269
+ }
270
+
271
+ export async function linkToNodeModules(
272
+ workspace: Workspace,
273
+ bitIds: BitId[],
274
+ loadFromScope = false
275
+ ): Promise<NodeModulesLinksResult[]> {
276
+ const componentsIds = BitIds.fromArray(bitIds);
277
+ if (!componentsIds.length) return [];
278
+ const getComponents = async () => {
279
+ if (loadFromScope) {
280
+ return Promise.all(componentsIds.map((id) => workspace.consumer.loadComponentFromModel(id)));
281
+ }
282
+ const { components } = await workspace.consumer.loadComponents(componentsIds);
283
+ return components;
284
+ };
285
+ const components = await getComponents();
286
+ const nodeModuleLinker = new NodeModuleLinker(components, workspace.consumer);
287
+ return nodeModuleLinker.link();
288
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@teambit/workspace.modules.node-modules-linker",
3
+ "version": "0.0.1",
4
+ "main": "dist/index.js",
5
+ "componentId": {
6
+ "scope": "teambit.workspace",
7
+ "name": "modules/node-modules-linker",
8
+ "version": "0.0.1"
9
+ },
10
+ "dependencies": {
11
+ "fs-extra": "10.0.0",
12
+ "glob": "7.1.6",
13
+ "p-map-series": "2.1.0",
14
+ "ramda": "0.27.1",
15
+ "@teambit/legacy-bit-id": "0.0.421"
16
+ },
17
+ "devDependencies": {
18
+ "@types/fs-extra": "9.0.7",
19
+ "@types/mocha": "9.1.0",
20
+ "@types/jest": "26.0.20",
21
+ "@types/node": "12.20.4",
22
+ "@babel/runtime": "7.20.0"
23
+ },
24
+ "peerDependencies": {},
25
+ "license": "Apache-2.0",
26
+ "private": false,
27
+ "engines": {
28
+ "node": ">=12.22.0"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/teambit/bit"
33
+ },
34
+ "keywords": [
35
+ "bit",
36
+ "components",
37
+ "collaboration",
38
+ "web",
39
+ "react",
40
+ "react-components",
41
+ "angular",
42
+ "angular-components"
43
+ ]
44
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": [
4
+ "es2019",
5
+ "DOM",
6
+ "ES6",
7
+ "DOM.Iterable"
8
+ ],
9
+ "target": "es2015",
10
+ "module": "CommonJS",
11
+ "jsx": "react",
12
+ "allowJs": true,
13
+ "composite": true,
14
+ "declaration": true,
15
+ "sourceMap": true,
16
+ "skipLibCheck": true,
17
+ "experimentalDecorators": true,
18
+ "outDir": "dist",
19
+ "moduleResolution": "node",
20
+ "esModuleInterop": true,
21
+ "rootDir": ".",
22
+ "resolveJsonModule": true
23
+ },
24
+ "exclude": [
25
+ "dist",
26
+ "package.json"
27
+ ],
28
+ "include": [
29
+ "**/*",
30
+ "**/*.json"
31
+ ]
32
+ }
@@ -0,0 +1,29 @@
1
+ declare module '*.png' {
2
+ const value: any;
3
+ export = value;
4
+ }
5
+ declare module '*.svg' {
6
+ import type { FunctionComponent, SVGProps } from 'react';
7
+
8
+ export const ReactComponent: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
9
+ const src: string;
10
+ export default src;
11
+ }
12
+
13
+ // @TODO Gilad
14
+ declare module '*.jpg' {
15
+ const value: any;
16
+ export = value;
17
+ }
18
+ declare module '*.jpeg' {
19
+ const value: any;
20
+ export = value;
21
+ }
22
+ declare module '*.gif' {
23
+ const value: any;
24
+ export = value;
25
+ }
26
+ declare module '*.bmp' {
27
+ const value: any;
28
+ export = value;
29
+ }
@@ -0,0 +1,42 @@
1
+ declare module '*.module.css' {
2
+ const classes: { readonly [key: string]: string };
3
+ export default classes;
4
+ }
5
+ declare module '*.module.scss' {
6
+ const classes: { readonly [key: string]: string };
7
+ export default classes;
8
+ }
9
+ declare module '*.module.sass' {
10
+ const classes: { readonly [key: string]: string };
11
+ export default classes;
12
+ }
13
+
14
+ declare module '*.module.less' {
15
+ const classes: { readonly [key: string]: string };
16
+ export default classes;
17
+ }
18
+
19
+ declare module '*.less' {
20
+ const classes: { readonly [key: string]: string };
21
+ export default classes;
22
+ }
23
+
24
+ declare module '*.css' {
25
+ const classes: { readonly [key: string]: string };
26
+ export default classes;
27
+ }
28
+
29
+ declare module '*.sass' {
30
+ const classes: { readonly [key: string]: string };
31
+ export default classes;
32
+ }
33
+
34
+ declare module '*.scss' {
35
+ const classes: { readonly [key: string]: string };
36
+ export default classes;
37
+ }
38
+
39
+ declare module '*.mdx' {
40
+ const component: any;
41
+ export default component;
42
+ }