Skip to content

Commit

Permalink
test(extract): adds integration test + covers corner case for when th…
Browse files Browse the repository at this point in the history
…e preserveSymlinks flag is set to true
  • Loading branch information
sverweij committed Nov 12, 2023
1 parent bc1b9cd commit 3c6e23d
Show file tree
Hide file tree
Showing 26 changed files with 382 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .c8rc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"checkCoverage": true,
"statements": 99.89,
"branches": 98.72,
"branches": 98.76,
"functions": 100,
"lines": 99.89,
"exclude": [
Expand Down
47 changes: 35 additions & 12 deletions src/extract/resolve/module-classifiers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,15 @@ function isWebPackAliased(pModuleName, pAliasObject) {
}

/**
* @param {string} pModuleName
* @param {string} pResolvedModuleName
* @param {object} pManifest
* @returns {boolean}
*/
function isWorkspaceAliased(pResolvedModuleName, pManifest) {
// eslint-disable-next-line max-lines-per-function
function isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest) {
// reference: https://docs.npmjs.com/cli/v10/using-npm/workspaces
return (
if (pManifest?.workspaces) {
// workspaces are an array of globs that match the (sub) workspace
// folder itself only.
//
Expand All @@ -147,16 +149,37 @@ function isWorkspaceAliased(pResolvedModuleName, pManifest) {
//
// This is why we chuck a `/**` at the end of each workspace glob, which
// transforms it into a 'starts with' glob. And yeah, you can have a /
// at the end of a glob and because double slashes are taken literally
// we have a ternary operator to prevent that.
pManifest?.workspaces &&
isMatch(
pResolvedModuleName,
pManifest.workspaces.map((pWorkspace) =>
// at the end of a glob. And because double slashes are taken literally
// we have a ternary operator to prevent those.
//
// oh and: ```picomatch.isMatch('asdf', 'asdf/**') === true``` so
// in case it's only 'asdf' that's in the resolved module name for some reason
// we're good as well.
const lModuleFriendlyWorkspaceGlobs = pManifest.workspaces.map(
(pWorkspace) =>
pWorkspace.endsWith("/") ? `${pWorkspace}**` : `${pWorkspace}/**`,
),
)
);
);
if (isMatch(pResolvedModuleName, lModuleFriendlyWorkspaceGlobs)) {
return true;
}
// it's possible to run node with --preserve-symlinks, in which case
// the symlinked workspace folders are not resolved to their realpath.
// So we need to check both the thing in node_modules _and_ the resolved
// thing. Annoyingly, the symlink in node_modules is the `name` attribute
// of the workspace, not the path of the workspace itself. So if it's
// in node_modules we need to check against the unresolved modulename.
//
// Other then the detection for when symlinks are resolved to their realpath
// (the if above), this is a 'best effort' detection only for now; there's
// guaranteed to be scenarios where this will fail. How often is the
// --preserve-symlinks flag used in practice, though?
const lModuleFriendlyWorkspaceGlobsWithNodeModules =
lModuleFriendlyWorkspaceGlobs.map(
(pWorkspace) => `(node_modules/)?${pWorkspace}`,
);
return isMatch(pModuleName, lModuleFriendlyWorkspaceGlobsWithNodeModules);
}
return false;
}

/**
Expand Down Expand Up @@ -199,7 +222,7 @@ export function getAliasTypes(
if (isWebPackAliased(pModuleName, pResolveOptions.alias)) {
return ["aliased", "aliased-webpack"];
}
if (isWorkspaceAliased(pResolvedModuleName, pManifest)) {
if (isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest)) {
return ["aliased", "aliased-workspace"];
}
if (
Expand Down
12 changes: 12 additions & 0 deletions test/cli/__fixtures__/workspaces-mono-repo/apps/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import frenchThing from "chose";
import englishThing from "thing";
import germanThing from "ding";
import chineseThing from "3kq578f";

import englishBooks from "libs/books/index.mjs";
import frenchBooks from "libs/livres/index.mjs";
import germanBooks from "libs/bücher/index.mjs";
import chineseBooks from "libs/图书/index.mjs";

console.log(frenchThing, englishThing, germanThing, chineseThing);
console.log(englishBooks, frenchBooks, germanBooks, chineseBooks);
206 changes: 206 additions & 0 deletions test/cli/__fixtures__/workspaces-mono-repo/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
{
"modules": [
{
"source": "apps/index.mjs",
"dependencies": [
{
"module": "3kq578f",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "packages/事物/index.js",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
{
"module": "chose",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "packages/chose/index.js",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
{
"module": "ding",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "packages/ding/index.js",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
{
"module": "libs/books/index.mjs",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "libs/books/index.mjs",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
{
"module": "libs/bücher/index.mjs",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "libs/bücher/index.mjs",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
{
"module": "libs/livres/index.mjs",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "libs/livres/index.mjs",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
{
"module": "libs/图书/index.mjs",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "libs/图书/index.mjs",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
{
"module": "thing",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "packages/thing/index.js",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": ["aliased", "aliased-workspace", "local"],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
}
],
"dependents": [],
"orphan": false,
"valid": true
},
{
"source": "packages/事物/index.js",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
},
{
"source": "packages/chose/index.js",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
},
{
"source": "packages/ding/index.js",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
},
{
"source": "libs/books/index.mjs",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
},
{
"source": "libs/bücher/index.mjs",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
},
{
"source": "libs/livres/index.mjs",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
},
{
"source": "libs/图书/index.mjs",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
},
{
"source": "packages/thing/index.js",
"dependencies": [],
"dependents": ["apps/index.mjs"],
"orphan": false,
"valid": true
}
],
"summary": {
"violations": [],
"error": 0,
"warn": 0,
"info": 0,
"ignore": 0,
"totalCruised": 9,
"totalDependenciesCruised": 8,
"optionsUsed": {
"baseDir": "test/cli/__fixtures__/workspaces-mono-repo",
"combinedDependencies": false,
"doNotFollow": {
"path": "node_modules"
},
"exoticRequireStrings": [],
"externalModuleResolutionStrategy": "node_modules",
"metrics": false,
"moduleSystems": ["es6", "cjs", "tsd", "amd"],
"outputTo": "test/cli/__output__/workspaces-mono-repo.json",
"outputType": "json",
"preserveSymlinks": false,
"tsPreCompilationDeps": false,
"args": "apps"
},
"ruleSetUsed": {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default "hello from books in the library";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default "Hallo von Bücher in der Bibliothek";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default "bonjour de livres dans la bibliothèque";
4 changes: 4 additions & 0 deletions test/cli/__fixtures__/workspaces-mono-repo/libs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "libs",
"version": "1.0.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default "你好,来自图书馆的书籍";

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions test/cli/__fixtures__/workspaces-mono-repo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "workspaces-mono-repo",
"version": "1.0.0",
"main": "index.js",
"workspaces": [
"libs",
"packages/*"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = "pacquet chose";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "chose",
"version": "1.0.0",
"main": "index.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = "Ding Pakket";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "ding",
"version": "1.0.0",
"main": "index.js"
}
Loading

0 comments on commit 3c6e23d

Please sign in to comment.