@teambit/tracker 1.0.1173 → 1.0.1175

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
+ {"version":3,"names":["_chai","data","require","_fsExtra","_interopRequireDefault","_path","_legacy","_harmonyTesting","_workspaceTesting","_workspace","_tracker","e","__esModule","default","describe","timeout","workspaces","compWithIgnoredJson","enableTrackAllFiles","workspacePath","configPath","path","join","content","fs","readFileSync","workspaceKey","includes","Error","writeFileSync","replace","setup","files","opts","workspaceData","mockWorkspace","push","trackAllFiles","Object","entries","forEach","filePath","outputFileSync","harmony","loadManyAspects","WorkspaceAspect","TrackerAspect","tracker","get","id","expectToReject","fn","messagePart","err","expect","message","to","have","string","after","Promise","all","map","destroyWorkspace","addedFiles","before","results","addForCLI","componentPaths","override","addedComponents","file","relativePath","it","include","not","main","compWithTsconfig","addWithTsconfigAsMain","compWithGeneratedFile","AUTO_GENERATED_MSG","filesOf"],"sources":["add-components.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { AUTO_GENERATED_MSG } from '@teambit/legacy.constants';\nimport { loadManyAspects } from '@teambit/harmony.testing.load-aspect';\nimport type { WorkspaceData } from '@teambit/workspace.testing.mock-workspace';\nimport { mockWorkspace, destroyWorkspace } from '@teambit/workspace.testing.mock-workspace';\nimport { WorkspaceAspect } from '@teambit/workspace';\nimport { TrackerAspect } from './tracker.aspect';\nimport type { TrackerMain } from './tracker.main.runtime';\n\n/**\n * which files `bit add` ends up tracking. one harmony load stands in for a process per command, so\n * the rules that pick the files are covered here rather than as e2e.\n */\ndescribe('the files bit add tracks', function () {\n this.timeout(0);\n\n const workspaces: WorkspaceData[] = [];\n\n /** a component whose own ignore file hides the .json next to its source */\n const compWithIgnoredJson = {\n 'comp1/index.js': 'module.exports = () => \"comp1\";\\n',\n 'comp1/.bitignore': '*.json\\n',\n 'comp1/hello.json': '{ \"hello\": \"world\" }\\n',\n };\n\n /** the workspace aspect holds the flag, and workspace.jsonc carries comments that JSON.parse rejects */\n function enableTrackAllFiles(workspacePath: string) {\n const configPath = path.join(workspacePath, 'workspace.jsonc');\n const content = fs.readFileSync(configPath, 'utf8');\n const workspaceKey = '\"teambit.workspace/workspace\": {';\n if (!content.includes(workspaceKey)) throw new Error(`\"${workspaceKey}\" is no longer in the mock workspace.jsonc`);\n fs.writeFileSync(configPath, content.replace(workspaceKey, `${workspaceKey}\\n \"trackAllFiles\": true,`));\n }\n\n async function setup(files: Record<string, string>, opts: { trackAllFiles?: boolean } = {}) {\n const workspaceData = mockWorkspace();\n workspaces.push(workspaceData);\n const { workspacePath } = workspaceData;\n if (opts.trackAllFiles) enableTrackAllFiles(workspacePath);\n Object.entries(files).forEach(([filePath, content]) =>\n fs.outputFileSync(path.join(workspacePath, filePath), content)\n );\n const harmony = await loadManyAspects([WorkspaceAspect, TrackerAspect], workspacePath);\n // addForCLI resolves componentPaths and main against the cwd, so the tests pass absolute paths\n return { workspacePath, tracker: harmony.get<TrackerMain>(TrackerAspect.id) };\n }\n\n /** chai has no async throw assertion that also matches a message */\n async function expectToReject(fn: () => Promise<unknown>, messagePart: string) {\n try {\n await fn();\n } catch (err: any) {\n expect(err.message).to.have.string(messagePart);\n return;\n }\n throw new Error(`expected to reject with \"${messagePart}\", but it resolved`);\n }\n\n after(async () => {\n await Promise.all(workspaces.map((workspaceData) => destroyWorkspace(workspaceData)));\n });\n\n describe('the ignore file of the component being added', () => {\n let addedFiles: string[];\n before(async () => {\n const { workspacePath, tracker } = await setup(compWithIgnoredJson);\n const results = await tracker.addForCLI({\n componentPaths: [path.join(workspacePath, 'comp1')],\n id: 'comp1',\n override: false,\n });\n addedFiles = results.addedComponents[0].files.map((file) => file.relativePath);\n });\n it('should apply it at add time, as the rescan does', () => {\n expect(addedFiles).to.include('index.js');\n expect(addedFiles).to.not.include('hello.json');\n });\n it('should keep the ignore file itself, it is a source of the component', () => {\n expect(addedFiles).to.include('.bitignore');\n });\n it('should refuse a main file it excludes, rather than track what the next rescan drops', async () => {\n const { workspacePath, tracker } = await setup(compWithIgnoredJson);\n await expectToReject(\n () =>\n tracker.addForCLI({\n componentPaths: [path.join(workspacePath, 'comp1')],\n id: 'comp1',\n main: path.join(workspacePath, 'comp1/hello.json'),\n override: false,\n }),\n 'was excluded from file list'\n );\n });\n });\n\n describe('a config file bit treats as generated, at the component root', () => {\n const compWithTsconfig = {\n 'comp1/index.js': 'module.exports = () => \"comp1\";\\n',\n 'comp1/tsconfig.json': '{}\\n',\n };\n const addWithTsconfigAsMain = async (trackAllFiles: boolean) => {\n const { workspacePath, tracker } = await setup(compWithTsconfig, { trackAllFiles });\n return tracker.addForCLI({\n componentPaths: [path.join(workspacePath, 'comp1')],\n id: 'comp1',\n main: path.join(workspacePath, 'comp1/tsconfig.json'),\n override: false,\n });\n };\n it('should refuse it as a main file, rather than track what the next rescan drops', async () => {\n // it used to fail further down with \"main file tsconfig.json was removed from <id>\", which\n // sends the user to \"bit remove\" for a component they are adding\n await expectToReject(() => addWithTsconfigAsMain(false), 'was excluded from file list');\n });\n it('should accept it with trackAllFiles on, where the rescan keeps it', async () => {\n const results = await addWithTsconfigAsMain(true);\n expect(results.addedComponents[0].files.map((file) => file.relativePath)).to.include('tsconfig.json');\n });\n });\n\n describe('a file bit generated, which carries its banner', () => {\n const compWithGeneratedFile = {\n 'comp1/index.js': 'module.exports = () => \"comp1\";\\n',\n 'comp1/package.json': `${AUTO_GENERATED_MSG}{ \"name\": \"comp1\" }\\n`,\n };\n const filesOf = async (trackAllFiles: boolean) => {\n const { workspacePath, tracker } = await setup(compWithGeneratedFile, { trackAllFiles });\n const results = await tracker.addForCLI({\n componentPaths: [path.join(workspacePath, 'comp1')],\n id: 'comp1',\n override: false,\n });\n return results.addedComponents[0].files.map((file) => file.relativePath);\n };\n it('should drop it by default, it is not source', async () => {\n expect(await filesOf(false)).to.not.include('package.json');\n });\n it('should keep it with trackAllFiles on, which is what the rescan does', async () => {\n // the rescan never looks at the banner, so dropping it here would leave the two disagreeing:\n // the file is missing from the add, then turns up as a new file on the next status\n expect(await filesOf(true)).to.include('package.json');\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -38,7 +38,7 @@ function determineMainFile(addedComponent, existingComponentMap) {
38
38
  const componentIdStr = addedComponent.componentId.toString();
39
39
  const files = addedComponent.files;
40
40
  const rootDir = existingComponentMap && existingComponentMap.rootDir;
41
- const strategies = [getExistingIfNotChanged, getUserSpecifiedMainFile, onlyOneFileEnteredUseIt, searchForFileNameIndex, searchForSameFileNameAsImmediateDir, searchForAngularEntryPoint];
41
+ const strategies = [getExistingIfNotChanged, getUserSpecifiedMainFile, workspaceRootDefault, onlyOneFileEnteredUseIt, searchForFileNameIndex, searchForSameFileNameAsImmediateDir, searchForAngularEntryPoint];
42
42
  for (const strategy of strategies) {
43
43
  const foundMainFile = strategy();
44
44
  if (foundMainFile) {
@@ -68,6 +68,15 @@ function determineMainFile(addedComponent, existingComponentMap) {
68
68
  }
69
69
  return null;
70
70
  }
71
+ /**
72
+ * the workspace-root component has no entry point of its own. workspace.jsonc, the file that makes
73
+ * the directory a workspace, stands in for it. it comes before the index search on purpose: an
74
+ * index file somewhere in the root's file-set is not the entry point of the workspace.
75
+ */
76
+ function workspaceRootDefault() {
77
+ if ((0, _legacy2().pathNormalizeToLinux)(addedComponent.trackDir) !== _legacy3().WORKSPACE_ROOT_DIR) return null;
78
+ return files.find(file => file.relativePath === _legacy().WORKSPACE_JSONC)?.relativePath;
79
+ }
71
80
  /**
72
81
  * user didn't enter mainFile and the component has only one file, use that file as the main file
73
82
  */
@@ -1 +1 @@
1
- {"version":3,"names":["path","data","_interopRequireWildcard","require","_legacy","_legacy2","_legacy3","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","determineMainFile","addedComponent","existingComponentMap","mainFile","componentIdStr","componentId","toString","files","rootDir","strategies","getExistingIfNotChanged","getUserSpecifiedMainFile","onlyOneFileEnteredUseIt","searchForFileNameIndex","searchForSameFileNameAsImmediateDir","searchForAngularEntryPoint","strategy","foundMainFile","mainFileString","DEFAULT_INDEX_NAME","DEFAULT_INDEX_EXTS","join","MissingMainFile","map","file","normalize","relativePath","_searchMainFile","pathNormalizeToLinux","length","ext","mainFileNameToSearch","searchResult","immediateDir","entryPoint","ANGULAR_BIT_ENTRY_POINT_FILE","baseMainFile","mainFileFromFiles","find","mainFileUsingRootDir","pathJoinLinux","potentialMainFiles","filter","basename","sortByNumOfDirs","a","b","split","DEFAULT_SEPARATOR","sort"],"sources":["determine-main-file.ts"],"sourcesContent":["import * as path from 'path';\n\nimport {\n ANGULAR_BIT_ENTRY_POINT_FILE,\n DEFAULT_INDEX_EXTS,\n DEFAULT_INDEX_NAME,\n DEFAULT_SEPARATOR,\n} from '@teambit/legacy.constants';\nimport type { PathLinux } from '@teambit/legacy.utils';\nimport { pathJoinLinux, pathNormalizeToLinux } from '@teambit/legacy.utils';\nimport type { ComponentMap } from '@teambit/legacy.bit-map';\nimport { MissingMainFile } from '@teambit/legacy.bit-map';\nimport type { AddedComponent } from './add-components';\n\nexport default function determineMainFile(\n addedComponent: AddedComponent,\n existingComponentMap: ComponentMap | null | undefined\n): PathLinux {\n const mainFile = addedComponent.mainFile;\n const componentIdStr = addedComponent.componentId.toString();\n const files = addedComponent.files;\n const rootDir = existingComponentMap && existingComponentMap.rootDir;\n const strategies: Function[] = [\n getExistingIfNotChanged,\n getUserSpecifiedMainFile,\n onlyOneFileEnteredUseIt,\n searchForFileNameIndex,\n searchForSameFileNameAsImmediateDir,\n searchForAngularEntryPoint,\n ];\n\n for (const strategy of strategies) {\n const foundMainFile = strategy();\n if (foundMainFile) {\n return foundMainFile;\n }\n }\n const mainFileString = `${DEFAULT_INDEX_NAME}.[${DEFAULT_INDEX_EXTS.join(', ')}]`;\n throw new MissingMainFile(\n componentIdStr,\n mainFileString,\n files.map((file) => path.normalize(file.relativePath))\n );\n\n /**\n * user didn't enter mainFile but the component already exists with mainFile\n */\n function getExistingIfNotChanged(): PathLinux | null | undefined {\n if (!mainFile && existingComponentMap) {\n return existingComponentMap.mainFile;\n }\n return null;\n }\n /**\n * user entered mainFile => search the mainFile in the files array, throw error if not found\n */\n function getUserSpecifiedMainFile(): PathLinux | null | undefined {\n if (mainFile) {\n const foundMainFile = _searchMainFile(pathNormalizeToLinux(mainFile));\n if (foundMainFile) return foundMainFile;\n throw new MissingMainFile(\n componentIdStr,\n mainFile,\n files.map((file) => path.normalize(file.relativePath))\n );\n }\n return null;\n }\n /**\n * user didn't enter mainFile and the component has only one file, use that file as the main file\n */\n function onlyOneFileEnteredUseIt(): PathLinux | null | undefined {\n if (files.length === 1) {\n return files[0].relativePath;\n }\n return null;\n }\n /**\n * user didn't enter mainFile and the component has multiple files, search for file name \"index\",\n * e.g. `index.js`, `index.css`, etc.\n */\n function searchForFileNameIndex(): PathLinux | null | undefined {\n for (const ext of DEFAULT_INDEX_EXTS) {\n const mainFileNameToSearch = `${DEFAULT_INDEX_NAME}.${ext}`;\n const searchResult = _searchMainFile(mainFileNameToSearch);\n if (searchResult) {\n return searchResult;\n }\n }\n return null;\n }\n /**\n * user didn't enter mainFile and the component has multiple files, search for file with the same\n * name as the directory (see #1714)\n */\n function searchForSameFileNameAsImmediateDir(): PathLinux | null | undefined {\n if (addedComponent.immediateDir) {\n for (const ext of DEFAULT_INDEX_EXTS) {\n const mainFileNameToSearch = `${addedComponent.immediateDir}.${ext}`;\n const searchResult = _searchMainFile(mainFileNameToSearch);\n if (searchResult) {\n return searchResult;\n }\n }\n }\n return null;\n }\n /**\n * The component is an angular component and uses the angular entry point\n */\n function searchForAngularEntryPoint(): PathLinux | null | undefined {\n for (const entryPoint of ANGULAR_BIT_ENTRY_POINT_FILE) {\n const searchResult = _searchMainFile(entryPoint);\n if (searchResult) {\n return searchResult;\n }\n }\n return null;\n }\n\n function _searchMainFile(baseMainFile: PathLinux): PathLinux | null | undefined {\n // search for an exact relative-path\n let mainFileFromFiles = files.find((file) => file.relativePath === baseMainFile);\n if (mainFileFromFiles) return baseMainFile;\n if (rootDir) {\n const mainFileUsingRootDir = files.find((file) => pathJoinLinux(rootDir, file.relativePath) === baseMainFile);\n if (mainFileUsingRootDir) return mainFileUsingRootDir.relativePath;\n }\n // search for a file-name\n const potentialMainFiles = files.filter((file) => path.basename(file.relativePath) === baseMainFile);\n if (!potentialMainFiles.length) return null;\n // when there are several files that met the criteria, choose the closer to the root\n const sortByNumOfDirs = (a, b) =>\n a.relativePath.split(DEFAULT_SEPARATOR).length - b.relativePath.split(DEFAULT_SEPARATOR).length;\n potentialMainFiles.sort(sortByNumOfDirs);\n mainFileFromFiles = potentialMainFiles[0];\n return mainFileFromFiles.relativePath;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["path","data","_interopRequireWildcard","require","_legacy","_legacy2","_legacy3","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","determineMainFile","addedComponent","existingComponentMap","mainFile","componentIdStr","componentId","toString","files","rootDir","strategies","getExistingIfNotChanged","getUserSpecifiedMainFile","workspaceRootDefault","onlyOneFileEnteredUseIt","searchForFileNameIndex","searchForSameFileNameAsImmediateDir","searchForAngularEntryPoint","strategy","foundMainFile","mainFileString","DEFAULT_INDEX_NAME","DEFAULT_INDEX_EXTS","join","MissingMainFile","map","file","normalize","relativePath","_searchMainFile","pathNormalizeToLinux","trackDir","WORKSPACE_ROOT_DIR","find","WORKSPACE_JSONC","length","ext","mainFileNameToSearch","searchResult","immediateDir","entryPoint","ANGULAR_BIT_ENTRY_POINT_FILE","baseMainFile","mainFileFromFiles","mainFileUsingRootDir","pathJoinLinux","potentialMainFiles","filter","basename","sortByNumOfDirs","a","b","split","DEFAULT_SEPARATOR","sort"],"sources":["determine-main-file.ts"],"sourcesContent":["import * as path from 'path';\n\nimport {\n ANGULAR_BIT_ENTRY_POINT_FILE,\n DEFAULT_INDEX_EXTS,\n DEFAULT_INDEX_NAME,\n DEFAULT_SEPARATOR,\n WORKSPACE_JSONC,\n} from '@teambit/legacy.constants';\nimport type { PathLinux } from '@teambit/legacy.utils';\nimport { pathJoinLinux, pathNormalizeToLinux } from '@teambit/legacy.utils';\nimport type { ComponentMap } from '@teambit/legacy.bit-map';\nimport { MissingMainFile, WORKSPACE_ROOT_DIR } from '@teambit/legacy.bit-map';\nimport type { AddedComponent } from './add-components';\n\nexport default function determineMainFile(\n addedComponent: AddedComponent,\n existingComponentMap: ComponentMap | null | undefined\n): PathLinux {\n const mainFile = addedComponent.mainFile;\n const componentIdStr = addedComponent.componentId.toString();\n const files = addedComponent.files;\n const rootDir = existingComponentMap && existingComponentMap.rootDir;\n const strategies: Function[] = [\n getExistingIfNotChanged,\n getUserSpecifiedMainFile,\n workspaceRootDefault,\n onlyOneFileEnteredUseIt,\n searchForFileNameIndex,\n searchForSameFileNameAsImmediateDir,\n searchForAngularEntryPoint,\n ];\n\n for (const strategy of strategies) {\n const foundMainFile = strategy();\n if (foundMainFile) {\n return foundMainFile;\n }\n }\n const mainFileString = `${DEFAULT_INDEX_NAME}.[${DEFAULT_INDEX_EXTS.join(', ')}]`;\n throw new MissingMainFile(\n componentIdStr,\n mainFileString,\n files.map((file) => path.normalize(file.relativePath))\n );\n\n /**\n * user didn't enter mainFile but the component already exists with mainFile\n */\n function getExistingIfNotChanged(): PathLinux | null | undefined {\n if (!mainFile && existingComponentMap) {\n return existingComponentMap.mainFile;\n }\n return null;\n }\n /**\n * user entered mainFile => search the mainFile in the files array, throw error if not found\n */\n function getUserSpecifiedMainFile(): PathLinux | null | undefined {\n if (mainFile) {\n const foundMainFile = _searchMainFile(pathNormalizeToLinux(mainFile));\n if (foundMainFile) return foundMainFile;\n throw new MissingMainFile(\n componentIdStr,\n mainFile,\n files.map((file) => path.normalize(file.relativePath))\n );\n }\n return null;\n }\n /**\n * the workspace-root component has no entry point of its own. workspace.jsonc, the file that makes\n * the directory a workspace, stands in for it. it comes before the index search on purpose: an\n * index file somewhere in the root's file-set is not the entry point of the workspace.\n */\n function workspaceRootDefault(): PathLinux | null | undefined {\n if (pathNormalizeToLinux(addedComponent.trackDir) !== WORKSPACE_ROOT_DIR) return null;\n return files.find((file) => file.relativePath === WORKSPACE_JSONC)?.relativePath;\n }\n /**\n * user didn't enter mainFile and the component has only one file, use that file as the main file\n */\n function onlyOneFileEnteredUseIt(): PathLinux | null | undefined {\n if (files.length === 1) {\n return files[0].relativePath;\n }\n return null;\n }\n /**\n * user didn't enter mainFile and the component has multiple files, search for file name \"index\",\n * e.g. `index.js`, `index.css`, etc.\n */\n function searchForFileNameIndex(): PathLinux | null | undefined {\n for (const ext of DEFAULT_INDEX_EXTS) {\n const mainFileNameToSearch = `${DEFAULT_INDEX_NAME}.${ext}`;\n const searchResult = _searchMainFile(mainFileNameToSearch);\n if (searchResult) {\n return searchResult;\n }\n }\n return null;\n }\n /**\n * user didn't enter mainFile and the component has multiple files, search for file with the same\n * name as the directory (see #1714)\n */\n function searchForSameFileNameAsImmediateDir(): PathLinux | null | undefined {\n if (addedComponent.immediateDir) {\n for (const ext of DEFAULT_INDEX_EXTS) {\n const mainFileNameToSearch = `${addedComponent.immediateDir}.${ext}`;\n const searchResult = _searchMainFile(mainFileNameToSearch);\n if (searchResult) {\n return searchResult;\n }\n }\n }\n return null;\n }\n /**\n * The component is an angular component and uses the angular entry point\n */\n function searchForAngularEntryPoint(): PathLinux | null | undefined {\n for (const entryPoint of ANGULAR_BIT_ENTRY_POINT_FILE) {\n const searchResult = _searchMainFile(entryPoint);\n if (searchResult) {\n return searchResult;\n }\n }\n return null;\n }\n\n function _searchMainFile(baseMainFile: PathLinux): PathLinux | null | undefined {\n // search for an exact relative-path\n let mainFileFromFiles = files.find((file) => file.relativePath === baseMainFile);\n if (mainFileFromFiles) return baseMainFile;\n if (rootDir) {\n const mainFileUsingRootDir = files.find((file) => pathJoinLinux(rootDir, file.relativePath) === baseMainFile);\n if (mainFileUsingRootDir) return mainFileUsingRootDir.relativePath;\n }\n // search for a file-name\n const potentialMainFiles = files.filter((file) => path.basename(file.relativePath) === baseMainFile);\n if (!potentialMainFiles.length) return null;\n // when there are several files that met the criteria, choose the closer to the root\n const sortByNumOfDirs = (a, b) =>\n a.relativePath.split(DEFAULT_SEPARATOR).length - b.relativePath.split(DEFAULT_SEPARATOR).length;\n potentialMainFiles.sort(sortByNumOfDirs);\n mainFileFromFiles = potentialMainFiles[0];\n return mainFileFromFiles.relativePath;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ function _chai() {
4
+ const data = require("chai");
5
+ _chai = function () {
6
+ return data;
7
+ };
8
+ return data;
9
+ }
10
+ function _componentId() {
11
+ const data = require("@teambit/component-id");
12
+ _componentId = function () {
13
+ return data;
14
+ };
15
+ return data;
16
+ }
17
+ function _determineMainFile() {
18
+ const data = _interopRequireDefault(require("./determine-main-file"));
19
+ _determineMainFile = function () {
20
+ return data;
21
+ };
22
+ return data;
23
+ }
24
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
25
+ const toFiles = paths => paths.map(relativePath => ({
26
+ relativePath,
27
+ test: false,
28
+ name: relativePath.split('/').pop()
29
+ }));
30
+ const addedComponent = (trackDir, files, mainFile) => ({
31
+ componentId: _componentId().ComponentID.fromObject({
32
+ name: 'comp'
33
+ }, 'my-scope'),
34
+ files: toFiles(files),
35
+ mainFile,
36
+ trackDir,
37
+ idFromPath: null,
38
+ immediateDir: trackDir.split('/').pop()
39
+ });
40
+ describe('determineMainFile', () => {
41
+ describe('the workspace root', () => {
42
+ // an index file at the root and a deeper one: neither is the entry point of a workspace
43
+ const rootFiles = ['.bitmap', 'README.md', 'index.ts', 'scripts/index.js', 'workspace.jsonc'];
44
+ it('should default to workspace.jsonc, over the index files', () => {
45
+ (0, _chai().expect)((0, _determineMainFile().default)(addedComponent('.', rootFiles), null)).to.equal('workspace.jsonc');
46
+ });
47
+ it('should take the main file the user gave over the default', () => {
48
+ (0, _chai().expect)((0, _determineMainFile().default)(addedComponent('.', rootFiles, 'README.md'), null)).to.equal('README.md');
49
+ });
50
+ it('should keep the main file of the existing entry when re-tracked without one', () => {
51
+ const existing = {
52
+ rootDir: '.',
53
+ mainFile: 'README.md'
54
+ };
55
+ (0, _chai().expect)((0, _determineMainFile().default)(addedComponent('.', rootFiles), existing)).to.equal('README.md');
56
+ });
57
+ });
58
+ describe('a regular directory', () => {
59
+ it('should resolve the index file, a workspace.jsonc inside it is a file like any other', () => {
60
+ const files = ['packages/comp1/index.ts', 'packages/comp1/workspace.jsonc'];
61
+ (0, _chai().expect)((0, _determineMainFile().default)(addedComponent('packages/comp1', files), null)).to.equal('packages/comp1/index.ts');
62
+ });
63
+ });
64
+ });
65
+
66
+ //# sourceMappingURL=determine-main-file.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_chai","data","require","_componentId","_determineMainFile","_interopRequireDefault","e","__esModule","default","toFiles","paths","map","relativePath","test","name","split","pop","addedComponent","trackDir","files","mainFile","componentId","ComponentID","fromObject","idFromPath","immediateDir","describe","rootFiles","it","expect","determineMainFile","to","equal","existing","rootDir"],"sources":["determine-main-file.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport { ComponentID } from '@teambit/component-id';\nimport type { ComponentMap, ComponentMapFile } from '@teambit/legacy.bit-map';\nimport determineMainFile from './determine-main-file';\nimport type { AddedComponent } from './add-components';\n\nconst toFiles = (paths: string[]): ComponentMapFile[] =>\n paths.map((relativePath) => ({ relativePath, test: false, name: relativePath.split('/').pop() as string }));\n\nconst addedComponent = (trackDir: string, files: string[], mainFile?: string): AddedComponent => ({\n componentId: ComponentID.fromObject({ name: 'comp' }, 'my-scope'),\n files: toFiles(files),\n mainFile,\n trackDir,\n idFromPath: null,\n immediateDir: trackDir.split('/').pop(),\n});\n\ndescribe('determineMainFile', () => {\n describe('the workspace root', () => {\n // an index file at the root and a deeper one: neither is the entry point of a workspace\n const rootFiles = ['.bitmap', 'README.md', 'index.ts', 'scripts/index.js', 'workspace.jsonc'];\n it('should default to workspace.jsonc, over the index files', () => {\n expect(determineMainFile(addedComponent('.', rootFiles), null)).to.equal('workspace.jsonc');\n });\n it('should take the main file the user gave over the default', () => {\n expect(determineMainFile(addedComponent('.', rootFiles, 'README.md'), null)).to.equal('README.md');\n });\n it('should keep the main file of the existing entry when re-tracked without one', () => {\n const existing = { rootDir: '.', mainFile: 'README.md' } as ComponentMap;\n expect(determineMainFile(addedComponent('.', rootFiles), existing)).to.equal('README.md');\n });\n });\n describe('a regular directory', () => {\n it('should resolve the index file, a workspace.jsonc inside it is a file like any other', () => {\n const files = ['packages/comp1/index.ts', 'packages/comp1/workspace.jsonc'];\n expect(determineMainFile(addedComponent('packages/comp1', files), null)).to.equal('packages/comp1/index.ts');\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+
3
+ function _chai() {
4
+ const data = require("chai");
5
+ _chai = function () {
6
+ return data;
7
+ };
8
+ return data;
9
+ }
10
+ function _fsExtra() {
11
+ const data = _interopRequireDefault(require("fs-extra"));
12
+ _fsExtra = function () {
13
+ return data;
14
+ };
15
+ return data;
16
+ }
17
+ function _path() {
18
+ const data = _interopRequireDefault(require("path"));
19
+ _path = function () {
20
+ return data;
21
+ };
22
+ return data;
23
+ }
24
+ function _harmonyTesting() {
25
+ const data = require("@teambit/harmony.testing.load-aspect");
26
+ _harmonyTesting = function () {
27
+ return data;
28
+ };
29
+ return data;
30
+ }
31
+ function _workspaceTesting() {
32
+ const data = require("@teambit/workspace.testing.mock-workspace");
33
+ _workspaceTesting = function () {
34
+ return data;
35
+ };
36
+ return data;
37
+ }
38
+ function _workspace() {
39
+ const data = require("@teambit/workspace");
40
+ _workspace = function () {
41
+ return data;
42
+ };
43
+ return data;
44
+ }
45
+ function _legacy() {
46
+ const data = require("@teambit/legacy.bit-map");
47
+ _legacy = function () {
48
+ return data;
49
+ };
50
+ return data;
51
+ }
52
+ function _tracker() {
53
+ const data = require("./tracker.aspect");
54
+ _tracker = function () {
55
+ return data;
56
+ };
57
+ return data;
58
+ }
59
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
60
+ /**
61
+ * tracking a component at the workspace root (rootDir "."). these cases only need `bit add` and the
62
+ * resulting .bitmap, so they run here rather than as e2e - one harmony load stands in for a process
63
+ * per command. the flows that need a remote (export, import onto ".", clone) stay in
64
+ * e2e/harmony/add-harmony.e2e.ts.
65
+ */
66
+ describe('tracking the workspace root', function () {
67
+ this.timeout(0);
68
+ async function setupWorkspace(files) {
69
+ const workspaceData = (0, _workspaceTesting().mockWorkspace)();
70
+ const {
71
+ workspacePath
72
+ } = workspaceData;
73
+ Object.entries(files).forEach(([filePath, content]) => _fsExtra().default.outputFileSync(_path().default.join(workspacePath, filePath), content));
74
+ const harmony = await (0, _harmonyTesting().loadManyAspects)([_workspace().WorkspaceAspect, _tracker().TrackerAspect], workspacePath);
75
+ return {
76
+ workspaceData,
77
+ workspacePath,
78
+ workspace: harmony.get(_workspace().WorkspaceAspect.id),
79
+ tracker: harmony.get(_tracker().TrackerAspect.id)
80
+ };
81
+ }
82
+
83
+ /** chai has no async throw assertion that also matches a message */
84
+ async function expectToReject(fn, messagePart) {
85
+ try {
86
+ await fn();
87
+ } catch (err) {
88
+ (0, _chai().expect)(err.message).to.have.string(messagePart);
89
+ return;
90
+ }
91
+ throw new Error(`expected to reject with "${messagePart}", but it resolved`);
92
+ }
93
+ const inWs = (tracked, relPath) => _path().default.join(tracked.workspacePath, relPath);
94
+
95
+ /** relative paths, as the command gets them: "." only means the workspace root when the cwd is it */
96
+ const addFrom = async (tracked, componentPaths, root) => {
97
+ const originalCwd = process.cwd();
98
+ process.chdir(tracked.workspacePath);
99
+ try {
100
+ return await tracked.tracker.addForCLI({
101
+ componentPaths,
102
+ override: false,
103
+ root
104
+ });
105
+ } finally {
106
+ process.chdir(originalCwd);
107
+ }
108
+ };
109
+ const rootDirOf = (tracked, name) => tracked.workspace.bitMap.getBitmapEntry(tracked.workspace.consumer.getParsedId(name), {
110
+ ignoreVersion: true
111
+ }).rootDir;
112
+ const mainFileOf = (tracked, name) => tracked.workspace.bitMap.getBitmapEntry(tracked.workspace.consumer.getParsedId(name), {
113
+ ignoreVersion: true
114
+ }).mainFile;
115
+ describe('re-adding and double-adding the workspace root', () => {
116
+ let tracked;
117
+ before(async () => {
118
+ tracked = await setupWorkspace({
119
+ 'README.md': '# workspace root\n'
120
+ });
121
+ await tracked.tracker.addForCLI({
122
+ componentPaths: [tracked.workspacePath],
123
+ id: 'ws-root',
124
+ main: inWs(tracked, 'README.md'),
125
+ override: false,
126
+ root: true
127
+ });
128
+ });
129
+ after(async () => {
130
+ await (0, _workspaceTesting().destroyWorkspace)(tracked.workspaceData);
131
+ });
132
+ it('should take the main file given explicitly over the default', () => {
133
+ (0, _chai().expect)(mainFileOf(tracked, 'ws-root')).to.equal('README.md');
134
+ });
135
+ it('should allow re-adding the same component', async () => {
136
+ _fsExtra().default.outputFileSync(_path().default.join(tracked.workspacePath, 'extra.md'), 'extra\n');
137
+ await tracked.tracker.addForCLI({
138
+ componentPaths: [tracked.workspacePath],
139
+ id: 'ws-root',
140
+ override: false
141
+ });
142
+ (0, _chai().expect)(rootDirOf(tracked, 'ws-root')).to.equal('.');
143
+ });
144
+ it('should allow re-adding it without repeating its name, and keep its main file', async () => {
145
+ await tracked.tracker.addForCLI({
146
+ componentPaths: [tracked.workspacePath],
147
+ override: false
148
+ });
149
+ // no second component was created out of the unnamed re-add
150
+ (0, _chai().expect)(tracked.workspace.bitMap.getAllRootDirs()).to.deep.equal(['.']);
151
+ (0, _chai().expect)(mainFileOf(tracked, 'ws-root')).to.equal('README.md');
152
+ });
153
+ it('should reject a second component claiming the workspace root', async () => {
154
+ await expectToReject(() => tracked.tracker.addForCLI({
155
+ componentPaths: [tracked.workspacePath],
156
+ id: 'another-root',
157
+ override: false
158
+ }), 'already tracked by');
159
+ });
160
+ it('should pick up dotfiles at add time, not only on the next rescan', async () => {
161
+ _fsExtra().default.outputFileSync(_path().default.join(tracked.workspacePath, '.npmrc'), 'registry=https://example.com\n');
162
+ const results = await tracked.tracker.addForCLI({
163
+ componentPaths: [tracked.workspacePath],
164
+ id: 'ws-root',
165
+ override: false
166
+ });
167
+ const files = results.addedComponents[0].files.map(file => file.relativePath);
168
+ (0, _chai().expect)(files).to.include('.npmrc');
169
+ // its auto-generated banner must not get it dropped, the rescan tracks it
170
+ (0, _chai().expect)(files).to.include('.bitmap');
171
+ });
172
+ });
173
+ describe('adding the workspace root and a nested component in one command', () => {
174
+ let addedComponents;
175
+ let tracked;
176
+ before(async () => {
177
+ tracked = await setupWorkspace({
178
+ 'index.js': 'module.exports = {};\n',
179
+ 'packages/comp1/index.js': 'module.exports = () => "comp1";\n',
180
+ 'packages/comp1/.npmrc': 'registry=https://example.com\n'
181
+ });
182
+ // relative paths, as the command gets them: "." is resolved by the same glob the CLI feeds, and
183
+ // a direct child would be dropped from the batch as a wildcard expansion of it
184
+ const originalCwd = process.cwd();
185
+ process.chdir(tracked.workspacePath);
186
+ try {
187
+ const results = await tracked.tracker.addForCLI({
188
+ componentPaths: [_legacy().WORKSPACE_ROOT_DIR, 'packages/comp1'],
189
+ override: false,
190
+ root: true
191
+ });
192
+ addedComponents = results.addedComponents.map(added => ({
193
+ id: added.id.toString(),
194
+ files: added.files.map(file => file.relativePath)
195
+ }));
196
+ } finally {
197
+ process.chdir(originalCwd);
198
+ }
199
+ });
200
+ after(async () => {
201
+ await (0, _workspaceTesting().destroyWorkspace)(tracked.workspaceData);
202
+ });
203
+ it('should list the dotfiles of a nested component at add time, as the rescan tracks them', () => {
204
+ const nested = addedComponents.find(added => added.id.endsWith('comp1'));
205
+ (0, _chai().expect)(nested?.files.some(file => file.endsWith('.npmrc'))).to.be.true;
206
+ });
207
+ it('should leave the nested component files out of the root, already at add time', () => {
208
+ // the nested component is not in .bitmap yet when the root is scanned, so the batch itself has
209
+ // to provide the exclusion. otherwise the two own the same files until the next rescan.
210
+ (0, _chai().expect)(addedComponents).to.have.lengthOf(2);
211
+ const root = addedComponents.find(added => !added.id.endsWith('comp1'));
212
+ (0, _chai().expect)(root?.files).to.include('index.js');
213
+ (0, _chai().expect)(root?.files.some(file => file.startsWith('packages/'))).to.be.false;
214
+ });
215
+ });
216
+ describe('adding a nested component that holds the main file of the workspace root', () => {
217
+ let tracked;
218
+ before(async () => {
219
+ tracked = await setupWorkspace({
220
+ 'packages/comp1/index.js': 'module.exports = () => "comp1";\n'
221
+ });
222
+ await tracked.tracker.addForCLI({
223
+ componentPaths: [tracked.workspacePath],
224
+ id: 'ws-root',
225
+ main: inWs(tracked, 'packages/comp1/index.js'),
226
+ override: false,
227
+ root: true
228
+ });
229
+ });
230
+ after(async () => {
231
+ await (0, _workspaceTesting().destroyWorkspace)(tracked.workspaceData);
232
+ });
233
+ it('should refuse, because the root would fail to load without its main file', async () => {
234
+ await expectToReject(() => tracked.tracker.addForCLI({
235
+ componentPaths: [inWs(tracked, 'packages/comp1')],
236
+ id: 'comp1',
237
+ override: false
238
+ }), 'main file of the workspace-root component');
239
+ });
240
+ it('should allow it when the root belongs to another lane, it owns nothing here', async () => {
241
+ // the root stays in .bitmap so a switch back can restore it. guarding its main file meanwhile
242
+ // would reject an add that is fine on this lane
243
+ const rootMap = tracked.workspace.consumer.bitMap.getWorkspaceRootMap();
244
+ (0, _chai().expect)(rootMap).to.not.be.undefined;
245
+ rootMap.isAvailableOnCurrentLane = false;
246
+ try {
247
+ const results = await tracked.tracker.addForCLI({
248
+ componentPaths: [inWs(tracked, 'packages/comp1')],
249
+ id: 'comp1-on-lane',
250
+ override: false
251
+ });
252
+ (0, _chai().expect)(results.addedComponents).to.have.lengthOf(1);
253
+ } finally {
254
+ rootMap.isAvailableOnCurrentLane = true;
255
+ }
256
+ });
257
+ it('should refuse even when the nested component ignores that file, its directory is what the root loses', async () => {
258
+ _fsExtra().default.outputFileSync(_path().default.join(tracked.workspacePath, 'packages/comp1/.bitignore'), 'index.js\n');
259
+ _fsExtra().default.outputFileSync(_path().default.join(tracked.workspacePath, 'packages/comp1/other.js'), '');
260
+ await expectToReject(() => tracked.tracker.addForCLI({
261
+ componentPaths: [inWs(tracked, 'packages/comp1')],
262
+ id: 'comp1',
263
+ override: false
264
+ }), 'main file of the workspace-root component');
265
+ });
266
+ });
267
+ describe('giving the workspace root a main file inside a component nested in it', () => {
268
+ let tracked;
269
+ before(async () => {
270
+ tracked = await setupWorkspace({
271
+ 'index.js': 'module.exports = {};\n',
272
+ 'packages/comp1/index.js': 'module.exports = () => "comp1";\n',
273
+ 'packages/nested-ws/.bitmap': '{}\n'
274
+ });
275
+ await tracked.tracker.addForCLI({
276
+ componentPaths: [inWs(tracked, 'packages/comp1')],
277
+ id: 'comp1',
278
+ override: false
279
+ });
280
+ });
281
+ after(async () => {
282
+ await (0, _workspaceTesting().destroyWorkspace)(tracked.workspaceData);
283
+ });
284
+ it('should refuse it, the scan of the root never yields a file of a component nested in it', async () => {
285
+ // the dir belongs to comp1, so the root's file-set excludes it. tracked anyway, the entry would
286
+ // survive until the next rescan dropped the file and the component failed to load without it
287
+ await expectToReject(() => tracked.tracker.addForCLI({
288
+ componentPaths: [tracked.workspacePath],
289
+ id: 'ws-root',
290
+ main: inWs(tracked, 'packages/comp1/index.js'),
291
+ override: false,
292
+ root: true
293
+ }), 'was excluded from file list');
294
+ });
295
+ it('should refuse the map of a nested workspace too, which no scan yields either', async () => {
296
+ // it is kept out of every scan rather than dropped by an ignore rule, so the ignore rules have
297
+ // nothing to say about it - the check has to ask the scan patterns, not only them
298
+ await expectToReject(() => tracked.tracker.addForCLI({
299
+ componentPaths: [tracked.workspacePath],
300
+ id: 'ws-root',
301
+ main: inWs(tracked, 'packages/nested-ws/.bitmap'),
302
+ override: false,
303
+ root: true
304
+ }), 'was excluded from file list');
305
+ });
306
+ });
307
+ describe('tracking the workspace root through the programmatic api', () => {
308
+ let tracked;
309
+ before(async () => {
310
+ tracked = await setupWorkspace({
311
+ 'README.md': '# workspace root\n'
312
+ });
313
+ });
314
+ after(async () => {
315
+ await (0, _workspaceTesting().destroyWorkspace)(tracked.workspaceData);
316
+ });
317
+ it('should take the given rootDir as the intent, the flag is for the command line', async () => {
318
+ // a caller naming the workspace root has already said so, as a resolved track-data entry
319
+ // declaring "." does. asking it for the flag would answer "run bit add . --root", which is
320
+ // not the command it is running
321
+ await tracked.tracker.track({
322
+ rootDir: tracked.workspacePath,
323
+ componentName: 'ws-root'
324
+ });
325
+ (0, _chai().expect)(rootDirOf(tracked, 'ws-root')).to.equal(_legacy().WORKSPACE_ROOT_DIR);
326
+ });
327
+ });
328
+ describe('the --root flag, which spells out the intent to track the workspace root', () => {
329
+ let tracked;
330
+ before(async () => {
331
+ tracked = await setupWorkspace({
332
+ 'index.js': 'module.exports = {};\n',
333
+ 'packages/comp1/index.js': 'module.exports = () => "comp1";\n'
334
+ });
335
+ });
336
+ after(async () => {
337
+ await (0, _workspaceTesting().destroyWorkspace)(tracked.workspaceData);
338
+ });
339
+ it('should refuse the workspace root without it, naming the command that does it', async () => {
340
+ await expectToReject(() => addFrom(tracked, [_legacy().WORKSPACE_ROOT_DIR]), 'bit add . --root');
341
+ });
342
+ it('should refuse it when none of the paths is the workspace root, rather than ignore it', async () => {
343
+ await expectToReject(() => addFrom(tracked, ['packages/comp1'], true), 'none of the given paths is the workspace root');
344
+ });
345
+ it('should leave an ordinary component alone, the flag is for the root and nothing else', async () => {
346
+ const results = await addFrom(tracked, ['packages/comp1']);
347
+ (0, _chai().expect)(results.addedComponents).to.have.lengthOf(1);
348
+ (0, _chai().expect)(rootDirOf(tracked, 'comp1')).to.equal('packages/comp1');
349
+ });
350
+ it('should track the workspace root with it', async () => {
351
+ const results = await addFrom(tracked, [_legacy().WORKSPACE_ROOT_DIR], true);
352
+ (0, _chai().expect)(results.addedComponents).to.have.lengthOf(1);
353
+ (0, _chai().expect)(rootDirOf(tracked, results.addedComponents[0].id.toStringWithoutVersion())).to.equal(_legacy().WORKSPACE_ROOT_DIR);
354
+ });
355
+ });
356
+ describe('adding the workspace root together with a component directly inside it', () => {
357
+ let tracked;
358
+ before(async () => {
359
+ tracked = await setupWorkspace({
360
+ 'index.js': 'module.exports = {};\n',
361
+ 'comp1/index.js': 'module.exports = () => "comp1";\n'
362
+ });
363
+ });
364
+ after(async () => {
365
+ await (0, _workspaceTesting().destroyWorkspace)(tracked.workspaceData);
366
+ });
367
+ it('should track both, the root is not a wildcard expansion of the directory below it', async () => {
368
+ const results = await addFrom(tracked, [_legacy().WORKSPACE_ROOT_DIR, 'comp1'], true);
369
+ (0, _chai().expect)(results.addedComponents).to.have.lengthOf(2);
370
+ (0, _chai().expect)(rootDirOf(tracked, 'comp1')).to.equal('comp1');
371
+ const root = results.addedComponents.find(added => added.id.fullName !== 'comp1');
372
+ (0, _chai().expect)(rootDirOf(tracked, root.id.toStringWithoutVersion())).to.equal(_legacy().WORKSPACE_ROOT_DIR);
373
+ });
374
+ });
375
+ });
376
+
377
+ //# sourceMappingURL=track-workspace-root.spec.js.map