-
-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/node-pkg-v2' into devShells
- Loading branch information
Showing
4 changed files
with
275 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
149 changes: 149 additions & 0 deletions
149
src/subsystems/nodejs/translators/package-lock-v2/default.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
# TODO use translate2 | ||
# TODO use package.json for v1 lock files | ||
{ | ||
dlib, | ||
lib, | ||
... | ||
}: let | ||
b = builtins; | ||
l = lib // builtins; | ||
nodejsUtils = import ../utils.nix {inherit lib;}; | ||
|
||
translate = { | ||
translatorName, | ||
utils, | ||
pkgs, | ||
... | ||
}: { | ||
project, | ||
source, | ||
tree, | ||
# translator args | ||
# name | ||
# nodejs | ||
... | ||
} @ args: let | ||
b = builtins; | ||
|
||
name = | ||
if (args.name or "{automatic}") != "{automatic}" | ||
then args.name | ||
else project.name; | ||
tree = args.tree.getNodeFromPath project.relPath; | ||
relPath = project.relPath; | ||
source = "${args.source}/${relPath}"; | ||
workspaces = project.subsystemInfo.workspaces or []; | ||
|
||
getResolved = tree: project: let | ||
lock = | ||
(nodejsUtils.getWorkspaceLockFile tree project "package-lock.json").jsonContent; | ||
resolved = import ./v2-parse.nix {inherit lib lock source;}; | ||
in | ||
resolved; | ||
|
||
resolved = getResolved args.tree project; | ||
|
||
packageVersion = resolved.self.version or "unknown"; | ||
|
||
rootDependencies = resolved.self.deps; | ||
|
||
identifyGitSource = dependencyObject: | ||
# TODO: when integrity is there, and git url is github then use tarball instead | ||
# ! (dependencyObject ? integrity) && | ||
dlib.identifyGitUrl dependencyObject.url; | ||
|
||
getVersion = dependencyObject: dependencyObject.version; | ||
|
||
getPath = dependencyObject: | ||
lib.removePrefix "file:" dependencyObject.url; | ||
|
||
stripDep = dep: l.removeAttrs dep ["pname" "version" "deps"]; | ||
in | ||
utils.simpleTranslate | ||
({ | ||
getDepByNameVer, | ||
dependenciesByOriginalID, | ||
... | ||
}: rec { | ||
inherit translatorName; | ||
location = relPath; | ||
|
||
# values | ||
inputData = resolved.allDeps; | ||
|
||
defaultPackage = name; | ||
|
||
packages = | ||
{"${defaultPackage}" = packageVersion;} | ||
// (nodejsUtils.getWorkspacePackages tree workspaces); | ||
|
||
mainPackageDependencies = resolved.self.deps; | ||
|
||
subsystemName = "nodejs"; | ||
|
||
subsystemAttrs = {nodejsVersion = args.nodejs;}; | ||
|
||
# functions | ||
serializePackages = inputData: inputData; | ||
|
||
getName = dependencyObject: dependencyObject.pname; | ||
|
||
inherit getVersion; | ||
|
||
# TODO handle npm link maybe? | ||
getSourceType = dependencyObject: | ||
if identifyGitSource dependencyObject | ||
then "git" | ||
else if lib.hasPrefix "file:" dependencyObject.url | ||
then "path" | ||
else "http"; | ||
|
||
sourceConstructors = { | ||
git = dependencyObject: | ||
(stripDep dependencyObject) | ||
// (dlib.parseGitUrl dependencyObject.url); | ||
|
||
http = dependencyObject: (stripDep dependencyObject); | ||
|
||
path = dependencyObject: | ||
(stripDep dependencyObject) | ||
// (dlib.construct.pathSource { | ||
path = getPath dependencyObject; | ||
rootName = project.name; | ||
rootVersion = packageVersion; | ||
}); | ||
}; | ||
|
||
getDependencies = dependencyObject: dependencyObject.deps; | ||
}); | ||
in rec { | ||
version = 2; | ||
|
||
type = "pure"; | ||
|
||
inherit translate; | ||
|
||
extraArgs = { | ||
name = { | ||
description = "The name of the main package"; | ||
examples = [ | ||
"react" | ||
"@babel/code-frame" | ||
]; | ||
default = "{automatic}"; | ||
type = "argument"; | ||
}; | ||
|
||
# TODO: this should either be removed or only used to select | ||
# the nodejs version for translating, not for building. | ||
nodejs = { | ||
description = "nodejs version to use for building"; | ||
default = "16"; | ||
examples = [ | ||
"14" | ||
"16" | ||
]; | ||
type = "argument"; | ||
}; | ||
}; | ||
} |
104 changes: 104 additions & 0 deletions
104
src/subsystems/nodejs/translators/package-lock-v2/v2-parse.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# This parses a v2 package-lock.json file. This format includes all information | ||
# to get correct dependencies, including peer dependencies and multiple | ||
# versions. lock.packages is a set that includes the path of each dep, and | ||
# this function teases it apart to know exactly which dep is being resolved. | ||
# The format of the lockfile is documented at | ||
# https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json/ | ||
{ | ||
lib, | ||
lock, | ||
source, | ||
}: | ||
assert (lib.elem lock.lockfileVersion [2 3]); let | ||
b = builtins; | ||
# { "node_modules/@foo/bar/node_modules/meep": pkg; ... } | ||
pkgs = lock.packages; | ||
lockName = lock.name or "unnamed"; | ||
lockVersion = lock.version or "unknown"; | ||
|
||
# First part is always "" and path doesn't start with / | ||
toPath = parts: let | ||
joined = b.concatStringsSep "/node_modules/" parts; | ||
len = b.stringLength joined; | ||
sliced = b.substring 1 len joined; | ||
in | ||
sliced; | ||
toParts = path: b.filter b.isString (b.split "/?node_modules/" path); | ||
|
||
getDep = name: parts: | ||
if b.length parts == 0 | ||
then null | ||
else pkgs.${toPath (parts ++ [name])} or (getDep name (lib.init parts)); | ||
resolveDep = name: parts: isOptional: let | ||
dep = getDep name parts; | ||
in | ||
if dep == null | ||
then | ||
if !isOptional | ||
then b.abort "Cannot resolve dependency ${name} from ${parts}" | ||
else null | ||
else { | ||
inherit name; | ||
inherit (dep) version; | ||
}; | ||
resolveDeps = nameSet: parts: isOptional: | ||
if nameSet == null | ||
then [] | ||
else let | ||
depNames = b.attrNames nameSet; | ||
resolved = b.map (n: resolveDep n parts isOptional) depNames; | ||
in | ||
b.filter (d: d != null) resolved; | ||
|
||
mapPkg = path: let | ||
parts = toParts path; | ||
pname = let | ||
n = lib.last parts; | ||
in | ||
if n == "" | ||
then lockName | ||
else n; | ||
in | ||
{ | ||
version ? "unknown", | ||
# URL to content - only main package is not defined | ||
resolved ? "file://${source}", | ||
# hash for content | ||
integrity ? null, | ||
# platforms this package works on | ||
os ? null, | ||
# this is a dev dependency | ||
dev ? false, | ||
# this is an optional dependency | ||
optional ? false, | ||
# this is an optional dev dependency | ||
devOptional ? false, | ||
# set of binary scripts { name = relativePath } | ||
bin ? {}, | ||
# pkg needs to run install scripts | ||
hasInstallScript ? false, | ||
dependencies ? null, | ||
devDependencies ? null, | ||
peerDependencies ? null, | ||
optionalDependencies ? null, | ||
peerDependenciesMeta ? null, | ||
... | ||
}: let | ||
deps = | ||
lib.unique | ||
((resolveDeps dependencies parts false) | ||
++ (resolveDeps devDependencies parts true) | ||
++ (resolveDeps optionalDependencies parts true) | ||
++ (resolveDeps peerDependencies parts true) | ||
++ (resolveDeps peerDependenciesMeta parts true)); | ||
in { | ||
inherit pname version deps os dev optional devOptional bin; | ||
url = resolved; | ||
hash = integrity; | ||
# Storing negation so other translators don't have to have this feature | ||
noInstall = !hasInstallScript; | ||
}; | ||
|
||
allDeps = lib.mapAttrsToList mapPkg pkgs; | ||
self = lib.findFirst (d: d.pname == lockName && d.version == lockVersion) (b.abort "Could not find main package") allDeps; | ||
in {inherit allDeps self;} |