fix: nodejs discoverer: exclude workspace children properly

This commit is contained in:
DavHau 2022-12-13 14:23:06 +07:00
parent 011b8ba238
commit c924a9edbc

View File

@ -10,29 +10,7 @@
inherit tree;
};
in
filterProjects projects;
# One translator call can process a whole workspace containing all
# sub-packages of that workspace.
# Therefore we can filter out projects which are children of a workspace.
filterProjects = projects: let
workspaceRoots =
l.filter
(proj: proj.subsystemInfo.workspaces or [] != [])
projects;
allWorkspaceChildren =
l.flatten
(l.map
(root: root.subsystemInfo.workspaces)
workspaceRoots);
childrenRemoved =
l.filter
(proj: (! l.elem proj.relPath allWorkspaceChildren))
projects;
in
childrenRemoved;
projects;
getTranslatorNames = tree: let
packageJson = tree.files."package.json".jsonContent;
@ -51,49 +29,48 @@
in
translators;
# returns the parsed package.json of a given directory
getPackageJson = dirPath:
l.fromJSON (l.readFile "${dirPath}/package.json");
# returns all relative paths to workspaces defined by a glob
getWorkspacePaths = glob: tree:
if l.hasSuffix "*" glob
then let
prefix = l.removeSuffix "*" glob;
path = "${tree.fullPath}/${prefix}";
getWorkspacePaths = glob: tree: let
paths =
if l.hasSuffix "*" glob
then let
prefix = l.removeSuffix "*" glob;
path = "${tree.fullPath}/${prefix}";
dirNames =
if l.pathExists path
then dlib.listDirs path
else
l.trace
"WARNING: Detected workspace ${glob} does not exist."
[];
existingWsPaths =
l.filter
(wsPath:
if l.pathExists "${path}/${wsPath}/package.json"
then true
else let
notExistingPath =
dlib.sanitizeRelativePath "${prefix}/${wsPath}";
in
dirNames =
if l.pathExists path
then dlib.listDirs path
else
l.trace
"WARNING: Detected workspace ${notExistingPath} does not exist."
false)
dirNames;
in
l.map (dname: "${prefix}/${dname}") existingWsPaths
else if l.pathExists "${tree.fullPath}/${glob}/package.json"
then [glob]
else
l.trace
"WARNING: Detected workspace ${glob} does not exist."
[];
"WARNING: Detected workspace ${glob} does not exist."
[];
existingWsPaths =
l.filter
(wsPath:
if l.pathExists "${path}/${wsPath}/package.json"
then true
else let
notExistingPath =
dlib.sanitizeRelativePath "${prefix}/${wsPath}";
in
l.trace
"WARNING: Detected workspace ${notExistingPath} does not exist."
false)
dirNames;
in
l.map (dname: "${prefix}/${dname}") existingWsPaths
else if l.pathExists "${tree.fullPath}/${glob}/package.json"
then [glob]
else
l.trace
"WARNING: Detected workspace ${glob} does not exist."
[];
in
map dlib.sanitizeRelativePath paths;
# collect project info for workspaces defined by current package.json
getWorkspaces = tree: parentInfo: let
getWorkspaceRelPaths = tree: parentInfo: let
packageJson = tree.files."package.json".jsonContent;
workspacesRaw = packageJson.workspaces or [];
@ -110,29 +87,7 @@
in
l.flatten
(l.forEach workspacesFlattened
(glob: let
workspacePaths = getWorkspacePaths glob tree;
in
l.forEach workspacePaths
(wPath: makeWorkspaceProjectInfo tree wPath parentInfo)));
makeWorkspaceProjectInfo = tree: wsRelPath: parentInfo:
dlib.construct.discoveredProject {
name =
(getPackageJson "${tree.fullPath}/${wsRelPath}").name
or "${parentInfo.name}/${wsRelPath}";
subsystem = "nodejs";
relPath = dlib.sanitizeRelativePath "${tree.relPath}/${wsRelPath}";
translators =
l.unique
(
(lib.filter (trans: l.elem trans ["package-lock" "yarn-lock"]) parentInfo.translators)
++ (getTranslatorNames "${tree.fullPath}/${wsRelPath}")
);
subsystemInfo = {
workspaceParent = tree.relPath;
};
};
(glob: getWorkspacePaths glob tree));
discoverInternal = {
tree,
@ -165,35 +120,41 @@
name = tree.files."package.json".jsonContent.name or tree.relPath;
subsystem = "nodejs";
translators = getTranslatorNames tree;
subsystemInfo = l.optionalAttrs (workspaces != []) {
subsystemInfo = l.optionalAttrs (workspaceRelPaths != []) {
workspaces =
l.map
(w: l.removePrefix "${tree.relPath}/" w.relPath)
workspaces;
(w: l.removePrefix "${tree.relPath}/" w)
workspaceRelPaths;
};
};
workspaces = getWorkspaces tree currentProjectInfo;
workspaceRelPaths = getWorkspaceRelPaths tree currentProjectInfo;
# list of all projects infos found by the current iteration
foundProjects =
# current directories project info
[currentProjectInfo]
# workspaces defined by the current directory
++ workspaces;
excludePaths =
l.map
(childRelPath:
dlib.sanitizeRelativePath
(currentProjectInfo.relPath + "/" + childRelPath))
workspaceRelPaths;
# contains all workspace children
excludes =
l.genAttrs
excludePaths
(_: null);
# index of already found projects
# This is needed, because sub-projects also contain a `package.json`,
# and would otherwise be discovered again as an independent project.
alreadyDiscovered' =
alreadyDiscovered
// (l.genAttrs
(l.map (p: p.relPath) foundProjects)
(relPath: null));
// excludes
// {
${currentProjectInfo.relPath} = null;
};
in
# l.trace tree.directories
# the current directory
foundProjects
[currentProjectInfo]
# sub-directories
# Thanks to `alreadyDiscovered`, workspace projects won't be discovered
# a second time.