├── .gitignore ├── LICENSE ├── README.md ├── bin ├── nijs-build.js ├── nijs-build │ ├── interface.js │ └── operations.js ├── nijs-execute.js ├── nijs-execute │ ├── interface.js │ └── operations.js └── wrapper.js ├── default.nix ├── lib ├── ast │ ├── NixASTNode.js │ ├── NixAssert.js │ ├── NixAttrReference.js │ ├── NixBlock.js │ ├── NixExpression.js │ ├── NixFile.js │ ├── NixFunInvocation.js │ ├── NixFunction.js │ ├── NixIf.js │ ├── NixImport.js │ ├── NixInherit.js │ ├── NixInlineJS.js │ ├── NixLet.js │ ├── NixMergeAttrs.js │ ├── NixObject.js │ ├── NixRecursiveAttrSet.js │ ├── NixStorePath.js │ ├── NixURL.js │ ├── NixValue.js │ ├── NixWith.js │ └── util │ │ └── inherit.js ├── build.js ├── execute │ ├── builder.sh │ └── index.js ├── funProxy.nix ├── generate.js ├── importPackage.nix ├── importPackageAsync.nix ├── inlineProxy.nix ├── nijs.js └── nixToJS.nix ├── node-env.nix ├── node-packages.nix ├── package.json ├── release.nix └── tests ├── custom-npm-pkgs ├── default.nix ├── node-env.nix ├── node-packages.json └── node-packages.nix ├── execute.nix ├── pkgs-async.js ├── pkgs-async ├── createFileWithMessageTest.js ├── fetchurl │ ├── builder.sh │ ├── index.js │ └── mirrors.json ├── file.js ├── hello.js ├── stdenv.js ├── test.js └── zlib.js ├── pkgs.js ├── pkgs ├── HelloModel.js ├── HelloModel │ └── HelloSourceModel.js ├── addressPerson.js ├── addressPersonInformally.js ├── addressPersons.js ├── append File B │ └── text.txt ├── appendFileA │ └── text.txt ├── appendFilesTest.js ├── bzip2.js ├── conditionals.js ├── createFileWithMessageTest.js ├── curl.js ├── fetchurl │ ├── builder.sh │ ├── index.js │ └── mirrors.json ├── file.js ├── hello.js ├── nijs.js ├── nodejs │ ├── build-node-package.sh │ ├── buildNodePackage.js │ ├── index.js │ └── setup-hook.sh ├── numbers.js ├── objToXML.js ├── openssl.js ├── optparse.js ├── perl.js ├── python │ ├── builder.sh │ ├── deterministic-build.patch │ ├── index.js │ ├── nix-store-mtime.patch │ ├── search-path.patch │ └── setup-hook.sh ├── sayHello.js ├── sayHello2.js ├── slasp.js ├── stdenv.js ├── stringWriteTest.js ├── sumTest.js ├── underscoreTest.js ├── utillinux.js ├── wget.js ├── writeTextFile.js └── zlib.js ├── proxytests.nix └── proxytests ├── appendTwoStrings.nix ├── createFileWithMessage.nix ├── createFileWithUnderscore.nix ├── indirectCat.nix ├── indirectionWget.nix ├── message.txt ├── printObjectAndReturnBye.nix ├── returnAttrSetStrings.nix ├── returnEscapedString.nix ├── sum.nix ├── timerTest.nix └── underscoreTest.nix /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Sander van der Burg 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /bin/nijs-build.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var wrapper = require('./wrapper.js'); 4 | wrapper.wrapInterface("nijs-build/interface.js"); 5 | -------------------------------------------------------------------------------- /bin/nijs-build/interface.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var optparse = require('optparse'); 4 | var operations = require('./operations.js'); 5 | 6 | /* Define command-line options */ 7 | 8 | var switches = [ 9 | ['-h', '--help', 'Shows help sections'], 10 | ['-v', '--version', 'Shows the version'], 11 | ['--show-trace', 'Causes Nix to print out a stack trace in case of Nix expression evaluation errors'], 12 | ['-K', '--keep-failed', 'Specifies that in case of a build failure, the temporary directory should not be deleted'], 13 | ['-o', '--out-link FILE', 'Change the name of the symlink to the output path created from result to outlink'], 14 | ['-A', '--attr NAME', 'Selects an instance of the top-level packages module'], 15 | ['--no-out-link', 'Do not create a symlink to the output path'], 16 | ['--eval-only', 'Causes the tool to only generate a Nix expression without evaluating it'], 17 | ['--async', 'Indicates whether the deployment modules are defined asynchronously'], 18 | ['--format', 'Indicates whether to nicely format to expression (i.e. generating whitespaces) or not'] 19 | ]; 20 | 21 | var parser = new optparse.OptionParser(switches); 22 | 23 | /* Set some variables and their default values */ 24 | 25 | var help = false; 26 | var version = false; 27 | var showTrace = false; 28 | var keepFailed = false; 29 | var outLink = null; 30 | var attr = null; 31 | var noOutLink = false; 32 | var evalOnly = false; 33 | var executable = ""; 34 | var filename = null; 35 | var async = false; 36 | var format = false; 37 | 38 | /* Define process rules for option parameters */ 39 | 40 | parser.on(function(arg, value) { 41 | process.stderr.write(arg + ": invalid option\n"); 42 | process.exit(1); 43 | }); 44 | 45 | parser.on('help', function(arg, value) { 46 | help = true; 47 | }); 48 | 49 | parser.on('version', function(arg, value) { 50 | version = true; 51 | }); 52 | 53 | parser.on('show-trace', function(arg, value) { 54 | showTrace = true; 55 | }); 56 | 57 | parser.on('keep-failed', function(arg, value) { 58 | keepFailed = true; 59 | }); 60 | 61 | parser.on('out-link', function(arg, value) { 62 | outLink = value; 63 | }); 64 | 65 | parser.on('attr', function(arg, value) { 66 | attr = value; 67 | }); 68 | 69 | parser.on('no-out-link', function(arg, value) { 70 | noOutLink = true; 71 | }); 72 | 73 | parser.on('eval-only', function(arg, value) { 74 | evalOnly = true; 75 | }); 76 | 77 | parser.on('async', function(arg, value) { 78 | async = true; 79 | }); 80 | 81 | parser.on('format', function(arg, value) { 82 | format = true; 83 | }); 84 | 85 | 86 | /* Define process rules for non-option parameters */ 87 | 88 | parser.on(1, function(opt) { 89 | executable = opt; 90 | }); 91 | 92 | parser.on(2, function(opt) { 93 | filename = opt; 94 | }); 95 | 96 | /* Do the actual command-line parsing */ 97 | 98 | parser.parse(process.argv); 99 | 100 | /* Display the help, if it has been requested */ 101 | 102 | if(help) { 103 | function displayTab(len, maxlen) { 104 | for(var i = 0; i < maxlen - len; i++) { 105 | process.stdout.write(" "); 106 | } 107 | } 108 | 109 | process.stdout.write("Usage: nijs-build [options] -A package pkgs.js\n\n"); 110 | 111 | process.stdout.write("Converts a given CommonJS module defining a Nix expression in a semi-abstract\n"); 112 | process.stdout.write("syntax into a Nix expression and builds it using `nix-build'\n\n"); 113 | 114 | process.stdout.write("Options:\n"); 115 | 116 | var maxlen = 20; 117 | 118 | for(var i = 0; i < switches.length; i++) { 119 | 120 | var currentSwitch = switches[i]; 121 | 122 | process.stdout.write(" "); 123 | 124 | if(currentSwitch.length == 3) { 125 | process.stdout.write(currentSwitch[0] + ", "+currentSwitch[1]); 126 | displayTab(currentSwitch[0].length + 2 + currentSwitch[1].length, maxlen); 127 | process.stdout.write(currentSwitch[2]); 128 | } else { 129 | process.stdout.write(currentSwitch[0]); 130 | displayTab(currentSwitch[0].length, maxlen); 131 | process.stdout.write(currentSwitch[1]); 132 | } 133 | 134 | process.stdout.write("\n"); 135 | } 136 | 137 | process.exit(0); 138 | } 139 | 140 | /* Display the version, if it has been requested */ 141 | 142 | if(version) { 143 | var versionNumber = fs.readFileSync(path.join("..", "..", "version")); 144 | process.stdout.write(executable + " (nijs "+versionNumber+")\n\n"); 145 | process.stdout.write("Copyright (C) 2012-2015 Sander van der Burg\n"); 146 | process.exit(0); 147 | } 148 | 149 | /* Verify the input parameters */ 150 | 151 | if(filename === null) { 152 | process.stderr.write("No packages CommonJS module is specified!\n"); 153 | process.exit(1); 154 | } 155 | 156 | if(attr === null) { 157 | process.stderr.write("No package has been selected!\n"); 158 | process.exit(1); 159 | } 160 | 161 | /* Perform the desired operation */ 162 | 163 | if(evalOnly) { 164 | operations.evaluateModule({ 165 | filename : filename, 166 | attr : attr, 167 | async : async, 168 | format : format 169 | }); 170 | } else { 171 | operations.nijsBuild({ 172 | filename : filename, 173 | attr : attr, 174 | showTrace : showTrace, 175 | keepFailed : keepFailed, 176 | outLink : outLink, 177 | noOutLink : noOutLink, 178 | async : async, 179 | format : format 180 | }); 181 | } 182 | -------------------------------------------------------------------------------- /bin/nijs-build/operations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module nijs-build.operations 3 | */ 4 | var path = require('path'); 5 | var slasp = require('slasp'); 6 | var nijs = require('../../lib/nijs.js'); 7 | 8 | /** 9 | * Imports the given package composition CommonJS module and evaluates the 10 | * specified package. 11 | * 12 | * @param {String} filename Path to the package composition CommonJS module 13 | * @param {String} attr Name of the package to evaluate 14 | * @param {Boolean} format Indicates whether to nicely format to expression (i.e. generating whitespaces) or not 15 | * @return {String} A string containing the generated Nix expression 16 | */ 17 | function evaluatePackage(filename, attr, format) { 18 | var pkgs = require(path.resolve(filename)).pkgs; 19 | var pkg = pkgs[attr](); 20 | var expr = nijs.jsToNix(pkg, format); 21 | return expr; 22 | } 23 | 24 | /** 25 | * Imports the given package composition CommonJS module and asynchronously 26 | * evaluates the specified package. 27 | * 28 | * @param {String} filename Path to the package composition CommonJS module 29 | * @param {String} attr Name of the package to evaluate 30 | * @param {Boolean} format Indicates whether to nicely format to expression (i.e. generating whitespaces) or not 31 | * @param {function(Object, Object)} callback Callback that gets invoked with either an error set if the operation failed, or a string containing the generated Nix expression 32 | */ 33 | function evaluatePackageAsync(filename, attr, format, callback) { 34 | var pkgs = require(path.resolve(filename)).pkgs; 35 | 36 | slasp.sequence([ 37 | function(callback) { 38 | pkgs[attr](callback); 39 | }, 40 | 41 | function(callback, pkg) { 42 | var expr = nijs.jsToNix(pkg, format); 43 | callback(null, expr); 44 | } 45 | ], callback); 46 | } 47 | 48 | /** 49 | * Evaluates the given package expression and redirects it to the standard output. 50 | * 51 | * @param {Object} args Arguments to this function 52 | * @param {String} args.filename Path to the package composition CommonJS module 53 | * @param {String} args.attr Name of the package to evaluate 54 | * @param {Boolean} args.format Indicates whether to nicely format to expression (i.e. generating whitespaces) or not 55 | * @param {Boolean} args.async Indicates whether the deployment modules are defined asynchronously 56 | */ 57 | exports.evaluateModule = function(args) { 58 | if(args.async) { 59 | evaluatePackageAsync(args.filename, args.attr, args.format, function(err, expr) { 60 | process.stdout.write(expr + "\n"); 61 | }); 62 | } else { 63 | var expr = evaluatePackage(args.filename, args.attr, args.format); 64 | process.stdout.write(expr + "\n"); 65 | } 66 | }; 67 | 68 | /** 69 | * Evaluates the given package expression and invokes nix-build to build it. 70 | * 71 | * @param {Object} args Arguments to this function 72 | * @param {String} args.filename Path to the package composition CommonJS module 73 | * @param {String} args.attr Name of the package to evaluate 74 | * @param {String} args.showTrace Indicates whether an error trace must be shown 75 | * @param {String} args.keepFailed Specifies whether the build result must be kept in case of an error 76 | * @param {String} args.outLink Specifies the path to the resulting output symlink 77 | * @param {Boolean} args.noOutLink Disables the creation of the result symlink 78 | * @param {Boolean} args.async Indicates whether the deployment modules are defined asynchronously 79 | * @param {Boolean} args.format Indicates whether to nicely format to expression (i.e. generating whitespaces) or not 80 | */ 81 | exports.nijsBuild = function(args) { 82 | /* Compose parameters to nix-build */ 83 | var params = []; 84 | 85 | if(args.showTrace) 86 | params.push("--show-trace"); 87 | 88 | if(args.keepFailed) 89 | params.push("-K"); 90 | 91 | if(args.outLink !== null) { 92 | params.push("-o"); 93 | params.push(args.outLink); 94 | } 95 | 96 | if(args.noOutLink) 97 | params.push("--no-out-link"); 98 | 99 | /* Evaluate the package */ 100 | 101 | slasp.sequence([ 102 | function(callback) { 103 | if(args.async) { 104 | evaluatePackageAsync(args.filename, args.attr, args.format, callback); 105 | } else { 106 | var expr = evaluatePackage(args.filename, args.attr, args.format); 107 | callback(null, expr); 108 | } 109 | }, 110 | 111 | function(callback, expr) { 112 | /* Call nix-build */ 113 | nijs.callNixBuild({ 114 | nixExpression : expr, 115 | params : params, 116 | callback : callback 117 | }); 118 | } 119 | 120 | ], function(err, result) { 121 | if(err) { 122 | process.stderr.write(err + "\n"); 123 | process.exit(1); 124 | } else { 125 | process.stdout.write(result + "\n"); 126 | } 127 | }); 128 | }; 129 | -------------------------------------------------------------------------------- /bin/nijs-execute.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var wrapper = require('./wrapper.js'); 4 | wrapper.wrapInterface("nijs-execute/interface.js"); 5 | -------------------------------------------------------------------------------- /bin/nijs-execute/interface.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var optparse = require('optparse'); 4 | var operations = require('./operations.js'); 5 | 6 | /* Define command-line options */ 7 | 8 | var switches = [ 9 | ['-h', '--help', 'Shows help sections'], 10 | ['-v', '--version', 'Shows the version'], 11 | ['-o', '--output', 'Change the output path in which build packages are stored'], 12 | ['-A', '--attr NAME', 'Selects an instance of the top-level packages module'], 13 | ['--tmpdir', 'Change the temp dir location in which immediate artifacts are stored'] 14 | ]; 15 | 16 | var parser = new optparse.OptionParser(switches); 17 | 18 | /* Set some variables and their default values */ 19 | 20 | var help = false; 21 | var version = false; 22 | var output = null; 23 | var attr = null; 24 | var tmpdir = null; 25 | var executable = ""; 26 | var filename = null; 27 | 28 | /* Define process rules for option parameters */ 29 | 30 | parser.on(function(arg, value) { 31 | process.stderr.write(arg + ": invalid option\n"); 32 | process.exit(1); 33 | }); 34 | 35 | parser.on('help', function(arg, value) { 36 | help = true; 37 | }); 38 | 39 | parser.on('version', function(arg, value) { 40 | version = true; 41 | }); 42 | 43 | parser.on('output', function(arg, value) { 44 | output = value; 45 | }); 46 | 47 | parser.on('attr', function(arg, value) { 48 | attr = value; 49 | }); 50 | 51 | parser.on('tmpdir', function(arg, value) { 52 | tmpdir = value; 53 | }); 54 | 55 | /* Define process rules for non-option parameters */ 56 | 57 | parser.on(1, function(opt) { 58 | executable = opt; 59 | }); 60 | 61 | parser.on(2, function(opt) { 62 | filename = opt; 63 | }); 64 | 65 | /* Do the actual command-line parsing */ 66 | 67 | parser.parse(process.argv); 68 | 69 | /* Display the help, if it has been requested */ 70 | 71 | if(help) { 72 | function displayTab(len, maxlen) { 73 | for(var i = 0; i < maxlen - len; i++) { 74 | process.stdout.write(" "); 75 | } 76 | } 77 | 78 | process.stdout.write("Usage: nijs-execute [options] -A package pkgs.js\n\n"); 79 | 80 | process.stdout.write("Directly executes the a given CommonJS module defining a set of package\n"); 81 | process.stdout.write("configurations, making it possible to directly build NiJS packages without the\n"); 82 | process.stdout.write("Nix package manager.\n\n"); 83 | 84 | process.stdout.write("Options:\n"); 85 | 86 | var maxlen = 20; 87 | 88 | for(var i = 0; i < switches.length; i++) { 89 | 90 | var currentSwitch = switches[i]; 91 | 92 | process.stdout.write(" "); 93 | 94 | if(currentSwitch.length == 3) { 95 | process.stdout.write(currentSwitch[0] + ", "+currentSwitch[1]); 96 | displayTab(currentSwitch[0].length + 2 + currentSwitch[1].length, maxlen); 97 | process.stdout.write(currentSwitch[2]); 98 | } else { 99 | process.stdout.write(currentSwitch[0]); 100 | displayTab(currentSwitch[0].length, maxlen); 101 | process.stdout.write(currentSwitch[1]); 102 | } 103 | 104 | process.stdout.write("\n"); 105 | } 106 | 107 | process.exit(0); 108 | } 109 | 110 | /* Display the version, if it has been requested */ 111 | 112 | if(version) { 113 | var versionNumber = fs.readFileSync(path.join("..", "..", "version")); 114 | process.stdout.write(executable + " (nijs "+versionNumber+")\n\n"); 115 | process.stdout.write("Copyright (C) 2012-2015 Sander van der Burg\n"); 116 | process.exit(0); 117 | } 118 | 119 | /* Verify the input parameters */ 120 | 121 | if(filename === null) { 122 | process.stderr.write("No packages CommonJS module is specified!\n"); 123 | process.exit(1); 124 | } 125 | 126 | if(attr === null) { 127 | process.stderr.write("No package has been selected!\n"); 128 | process.exit(1); 129 | } 130 | 131 | /* Perform the desired operation */ 132 | 133 | operations.nijsExecute({ 134 | filename : filename, 135 | attr : attr, 136 | output : output, 137 | tmpdir : tmpdir 138 | }); 139 | -------------------------------------------------------------------------------- /bin/nijs-execute/operations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module nijs-execute.operations 3 | */ 4 | 5 | var path = require('path'); 6 | var nijs = require('../../lib/nijs.js'); 7 | 8 | /** 9 | * Directly executes the given asynchronous package expression module. 10 | * 11 | * @param {Object} args Arguments to this function 12 | * @param {String} args.filename Path to the package composition CommonJS module 13 | * @param {String} args.attr Name of the package to evaluate 14 | * @param {String} args.tmpdir Folder in which the temp files are stored 15 | * @param {String} args.output Folder in which the output files are stored 16 | */ 17 | exports.nijsExecute = function(args) { 18 | NIJS_EXECUTE = true; // Global variable that can be used by packages indicating that we use nijs-execute 19 | 20 | /* Set the tmpdir */ 21 | if(args.tmpdir) 22 | NIJS_EXECUTE_TMPDIR = args.tmpdir; 23 | else if(process.env['TMPDIR']) 24 | NIJS_EXECUTE_TMPDIR = process.env['TMPDIR']; 25 | else 26 | NIJS_EXECUTE_TMPDIR = path.join(process.env['HOME'], ".nijs", "tmp"); 27 | 28 | /* Set the output dir */ 29 | 30 | if(args.output) 31 | NIJS_EXECUTE_OUTPUT = args.output; 32 | else if(process.env['NIJS_STORE']) 33 | NIJS_EXECUTE_OUTPUT = process.env['NIJS_STORE']; 34 | else 35 | NIJS_EXECUTE_OUTPUT = path.join(process.env['HOME'], ".nijs", "store"); 36 | 37 | var pkgs = require(path.resolve(args.filename)).pkgs; 38 | var pkg = pkgs[args.attr]; 39 | 40 | pkg(function(err, result) { 41 | if(err) { 42 | process.stderr.write(err.toString() + "\n"); 43 | process.exit(1); 44 | } else { 45 | process.stdout.write(result + "\n"); 46 | } 47 | }); 48 | }; 49 | -------------------------------------------------------------------------------- /bin/wrapper.js: -------------------------------------------------------------------------------- 1 | var child_process = require('child_process'); 2 | var path = require('path'); 3 | 4 | function wrapInterface(interfaceFile) { 5 | /* Set the command-line arguments */ 6 | var args = process.argv; 7 | 8 | /* Take the node interpreter path */ 9 | var nodeCommand = args.shift(); 10 | 11 | /* Discard the node script */ 12 | args.shift(); 13 | 14 | /* Determine the path to the interface */ 15 | var interfacePath = path.join(path.dirname(module.filename), interfaceFile); 16 | 17 | /* Compose command line arguments to invoke the interface */ 18 | args = [ interfacePath ].concat(args); 19 | 20 | /* 21 | * Compose environment that contains nijs and its dependencies in the NODE_PATH 22 | * environment variable 23 | */ 24 | var nijsPath = path.resolve(path.join(path.dirname(module.filename), "..", "..")); 25 | 26 | var newEnv = process.env; 27 | 28 | if(newEnv.NODE_PATH === undefined || newEnv.NODE_PATH == "") 29 | newEnv.NODE_PATH = nijsPath + path.delimiter + path.join(nijsPath, "nijs", "node_modules"); 30 | else 31 | newEnv.NODE_PATH = nijsPath + path.delimiter + path.join(nijsPath, "nijs", "node_modules") + path.delimiter + newEnv.NODE_PATH; 32 | 33 | /* Spawn the interface process */ 34 | var nijsBuildProcess = child_process.spawn(nodeCommand, args, { env: newEnv }); 35 | 36 | nijsBuildProcess.stdout.on("data", function(data) { 37 | process.stdout.write(data); 38 | }); 39 | 40 | nijsBuildProcess.stderr.on("data", function(data) { 41 | process.stderr.write(data); 42 | }); 43 | 44 | nijsBuildProcess.on("exit", function(code) { 45 | process.exit(code); 46 | }); 47 | 48 | } 49 | 50 | exports.wrapInterface = wrapInterface; 51 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | # This file has been generated by node2nix 1.11.1. Do not edit! 2 | 3 | {pkgs ? import { 4 | inherit system; 5 | }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-12_x"}: 6 | 7 | let 8 | nodeEnv = import ./node-env.nix { 9 | inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript; 10 | inherit pkgs nodejs; 11 | libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null; 12 | }; 13 | in 14 | import ./node-packages.nix { 15 | inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit; 16 | inherit nodeEnv; 17 | } 18 | -------------------------------------------------------------------------------- /lib/ast/NixASTNode.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | var NixObject = require('./NixObject.js').NixObject; 3 | var inherit = require('./util/inherit.js').inherit; 4 | 5 | /** 6 | * Creates a new NixASTNode instance. 7 | * 8 | * @class NixASTNode 9 | * @extends NixObject 10 | * @classdesc Defines an AST node that is composed of an arbitrary data 11 | * structure that can be translated into a Nix expression. This prototype is 12 | * supposted to be extended by other prototypes so that they can expose their 13 | * properties as a Nix expression. 14 | * Alternatively, the constructor can be used as an adapter for any object 15 | * implementing a toNixAST function member. 16 | * 17 | * @constructor 18 | * @param {Object} An object implementing a toNixAST function member (optional) 19 | */ 20 | function NixASTNode(obj) { 21 | if(obj !== undefined && typeof obj.toNixAST === "function") { 22 | this.toNixAST = obj.toNixAST; 23 | } 24 | } 25 | 26 | /* NixASTNode inherits from NixObject */ 27 | inherit(NixObject, NixASTNode); 28 | 29 | /** 30 | * Returns an arbitrary data structure that will be translated into a Nix 31 | * expression. 32 | * 33 | * @method 34 | * @return {Object} Arbitrary data structure 35 | */ 36 | NixASTNode.prototype.toNixAST = function() { 37 | throw "toNixAST() is not implemented, please use a prototype that inherits from NixASTNode or provide an object with a toNixAST() function as a property as constructor parameter"; 38 | }; 39 | 40 | /** 41 | * @see NixObject#toNixExpr 42 | */ 43 | NixASTNode.prototype.toNixExpr = function(indentLevel, format) { 44 | return nijs.jsToIndentedNix(this.toNixAST(), indentLevel, format); 45 | }; 46 | 47 | exports.NixASTNode = NixASTNode; 48 | -------------------------------------------------------------------------------- /lib/ast/NixAssert.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixBlock = require('./NixBlock.js').NixBlock; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixAssert instance. 7 | * 8 | * @class NixAssert 9 | * @extends NixBlock 10 | * @classdesc Captures the abstract syntax of a Nix assert statement. 11 | * 12 | * @constructor 13 | * @param {Object} args Arguments to this function 14 | * @param {Mixed} args.conditionExpr An object representing an expression evaluating to a boolean 15 | * @param {Mixed} args.body Expression that gets evaluated if the condition is true. If it is false, the evaluation aborts with an error. 16 | */ 17 | function NixAssert(args) { 18 | this.conditionExpr = args.conditionExpr; 19 | this.body = args.body; 20 | } 21 | 22 | /* NixAssert inherits from NixBlock */ 23 | inherit(NixBlock, NixAssert); 24 | 25 | /** 26 | * @see NixObject#toNixExpr 27 | */ 28 | NixAssert.prototype.toNixExpr = function(indentLevel, format) { 29 | return "assert " + nijs.jsToIndentedNix(this.conditionExpr, indentLevel, format) + ";\n" + 30 | nijs.generateIndentation(indentLevel, format) + nijs.jsToIndentedNix(this.body, indentLevel, format); 31 | }; 32 | 33 | exports.NixAssert = NixAssert; 34 | -------------------------------------------------------------------------------- /lib/ast/NixAttrReference.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixObject = require('./NixObject.js').NixObject; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixAttrReference instance. 7 | * 8 | * @class NixAttrReference 9 | * @extends NixObject 10 | * @classdesc Captures the abstract syntax of a Nix of an expression yielding an 11 | * attribute set and an expression yielding an attribute name that references a 12 | * member of the former attribute set. 13 | * 14 | * @constructor 15 | * @param {Object} args Arguments to this function 16 | * @param {Mixed} args.attrSetExpr An object representing an expression that yields an attribute set 17 | * @param {Mixed} args.refExpr An object representing an expression that yields an attribute name 18 | * @param {Mixed} args.orExpr An optional object representing an expression that gets evaluated if the reference does not exist. 19 | */ 20 | function NixAttrReference(args) { 21 | this.attrSetExpr = args.attrSetExpr; 22 | this.refExpr = args.refExpr; 23 | this.orExpr = args.orExpr; 24 | } 25 | 26 | /* NixAttrReference inherits from NixObject */ 27 | inherit(NixObject, NixAttrReference); 28 | 29 | /** 30 | * @see NixObject#toNixExpr 31 | */ 32 | NixAttrReference.prototype.toNixExpr = function(indentLevel, format) { 33 | 34 | /* Generate the sub expression that yields the attribute set */ 35 | var attrSetExprStr = nijs.jsToIndentedNix(this.attrSetExpr, indentLevel, format); 36 | 37 | if(this.attrSetExpr instanceof nijs.NixBlock) { // Some object require ( ) around them to make them work 38 | attrSetExprStr = this.attrSetExpr.wrapInParenthesis(attrSetExprStr); 39 | } 40 | 41 | /* Generate the sub expression that yields the parameter */ 42 | var refExprStr = nijs.jsToIndentedNix(this.refExpr, indentLevel, format); 43 | 44 | if(this.refExpr instanceof nijs.NixBlock) { // Some objects require ( ) around them to make them work 45 | refExprStr = this.refExpr.wrapInParenthesis(refExprStr); 46 | } 47 | 48 | /* Generate the or expression that gets evaluated if the reference does not exist */ 49 | var orExprStr; 50 | 51 | if(this.orExpr === undefined) { 52 | orExprStr = ""; 53 | } else { 54 | orExprStr = nijs.jsToIndentedNix(this.orExpr, indentLevel, format); 55 | 56 | if(this.orExpr instanceof nijs.NixBlock) { // Some objects require ( ) around them to make them work 57 | orExprStr = this.orExpr.wrapInParenthesis(orExprStr); 58 | } 59 | 60 | orExprStr = " or " + orExprStr; 61 | } 62 | 63 | /* Return the generated sub expression */ 64 | return attrSetExprStr + "." + refExprStr + orExprStr; 65 | }; 66 | 67 | exports.NixAttrReference = NixAttrReference; 68 | -------------------------------------------------------------------------------- /lib/ast/NixBlock.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixObject = require('./NixObject.js').NixObject; 3 | 4 | /** 5 | * Creates a new NixBlock instance. 6 | * 7 | * @class NixBlock 8 | * @extends NixObject 9 | * @classdesc Creates a Nix block object that contains a sub expression that 10 | * might need parenthesis ( ) around them in certain contexts, such as a list. 11 | * 12 | * @constructor 13 | */ 14 | function NixBlock() { 15 | }; 16 | 17 | /* NixBlock inherits from NixObject */ 18 | inherit(NixObject, NixBlock); 19 | 20 | /** 21 | * Wraps an expression in a block within parenthesis. 22 | * 23 | * @method 24 | * @param {String} expr String containing a Nix expression block 25 | * @return {String} The same expression within parenthesis 26 | */ 27 | NixBlock.prototype.wrapInParenthesis = function(expr) { 28 | return "(" + expr + ")"; 29 | }; 30 | 31 | exports.NixBlock = NixBlock; 32 | -------------------------------------------------------------------------------- /lib/ast/NixExpression.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixValue = require('./NixValue.js').NixValue; 3 | 4 | /** 5 | * Creates a new NixExpression instance. 6 | * 7 | * @class NixExpression 8 | * @extends NixValue 9 | * @classdesc A Nix object that contains an already generated Nix expression. 10 | * 11 | * @constructor 12 | * @param {String} value Value containing a Nix expression 13 | */ 14 | function NixExpression(value) { 15 | NixValue.call(this, value); 16 | }; 17 | 18 | /* NixExpression inherits from NixValue */ 19 | inherit(NixValue, NixExpression); 20 | 21 | /** 22 | * @see NixObject#toNixExpr 23 | */ 24 | NixExpression.prototype.toNixExpr = function(indentLevel, format) { 25 | return this.value; 26 | }; 27 | 28 | exports.NixExpression = NixExpression; 29 | -------------------------------------------------------------------------------- /lib/ast/NixFile.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var inherit = require('./util/inherit.js').inherit; 3 | var NixValue = require('./NixValue.js').NixValue; 4 | 5 | /** 6 | * Creates a new NixFile instance. 7 | * 8 | * @class NixFile 9 | * @extends NixValue 10 | * @classdesc A Nix file object that gets imported into the Nix store. Paths to 11 | * a file may be absolute (starting with a /) or relative. For relative paths a 12 | * module reference must be given so that it can be correctly resolved to a 13 | * correct absolute path. 14 | * 15 | * @constructor 16 | * @param {Object} args Arguments to this function 17 | * @param {String} args.value An absolute or relative path to a file 18 | * @param {Module} args.module Reference to the CommonJS module that refers to a relative path (not needed for absolute paths) 19 | */ 20 | 21 | function NixFile(args) { 22 | NixValue.call(this, args.value); 23 | this.module = args.module; 24 | }; 25 | 26 | /* NixFile inherits from NixValue */ 27 | inherit(NixValue, NixFile); 28 | 29 | /** 30 | * @see NixObject#toNixExpr 31 | */ 32 | NixFile.prototype.toNixExpr = function(indentLevel, format) { 33 | 34 | var actualPath; 35 | 36 | /* 37 | * If the path does not start with a / and a module is 38 | * defined, we consider the file to have a relative path 39 | * and we have to add the module's dirname as prefix 40 | */ 41 | if(this.value.substring(0, 1) != '/' && this.module !== undefined) { 42 | var dir = path.dirname(this.module.filename); 43 | actualPath = path.resolve(path.join(dir, this.value)) /* Compase a resolved path that does not contain any relative path components */ 44 | } else { 45 | actualPath = this.value; 46 | } 47 | 48 | /* Generate Nix file object */ 49 | if(actualPath.indexOf(" ") == -1) 50 | return actualPath; /* Filenames without spaces can be placed verbatim */ 51 | else 52 | return '/. + "' + actualPath.replace(/\"/g, '\\"') + '"'; /* Filenames with spaces require some extra steps for conversion */ 53 | }; 54 | 55 | exports.NixFile = NixFile; 56 | -------------------------------------------------------------------------------- /lib/ast/NixFunInvocation.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixBlock = require('./NixBlock.js').NixBlock; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixFunInvocation instance. 7 | * 8 | * @class NixFunInvocation 9 | * @extends NixBlock 10 | * @classdesc Captures the abstract syntax of a Nix function invocation 11 | * consisting of an expression yielding a function definition and an expression 12 | * capturing the parameter. 13 | * 14 | * @constructor 15 | * @param {Object} args Arguments to this function 16 | * @param {Mixed} args.funExpr An object representing an expression that yields a function definition 17 | * @param {Mixed} args.paramExpr An object representing an expression that yields the function parameter 18 | */ 19 | 20 | function NixFunInvocation(args) { 21 | this.funExpr = args.funExpr; 22 | this.paramExpr = args.paramExpr; 23 | } 24 | 25 | /* NixFunInvocation inherits from NixBlock */ 26 | inherit(NixBlock, NixFunInvocation); 27 | 28 | /** 29 | * @see NixObject#toNixExpr 30 | */ 31 | NixFunInvocation.prototype.toNixExpr = function(indentLevel, format) { 32 | 33 | /* Generate the sub expression that yields the function definition */ 34 | var funExprStr = nijs.jsToIndentedNix(this.funExpr, indentLevel, format); 35 | 36 | if(this.funExpr instanceof nijs.NixBlock && !(this.funExpr instanceof nijs.NixFunInvocation)) { // Some objects require ( ) around them to make them work 37 | funExprStr = this.funExpr.wrapInParenthesis(funExprStr); 38 | } 39 | 40 | /* Generate the sub expression that yields the parameter */ 41 | var paramExprStr = nijs.jsToIndentedNix(this.paramExpr, indentLevel, format); 42 | 43 | if(this.paramExpr instanceof nijs.NixBlock) { // Some objects require ( ) around them to make them work 44 | paramExprStr = this.paramExpr.wrapInParenthesis(paramExprStr); 45 | } 46 | 47 | /* Return the generated sub expression */ 48 | return funExprStr + " " + paramExprStr; 49 | }; 50 | 51 | exports.NixFunInvocation = NixFunInvocation; 52 | -------------------------------------------------------------------------------- /lib/ast/NixFunction.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixBlock = require('./NixBlock.js').NixBlock; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixFunction instance. 7 | * 8 | * @class NixFunction 9 | * @extends NixBlock 10 | * @classdesc Captures the abstract syntax of a Nix function consisting of an 11 | * argument and function body. 12 | * 13 | * @constructor 14 | * @param {Object} args Arguments to this function 15 | * @param {Mixed} args.argSpec Argument specification of the function. If a string is 16 | * given then the resulting function takes a single parameter with that name. 17 | * If an array or object is given, then it's converted to an attribute set 18 | * taking multiple parameters. In the former case, the array values correspond 19 | * to the parameter names. In the latter case, the object keys are used as 20 | * parameter names and their values are considered default values. 21 | * @param {Mixed} args.body The body of the function, which can be a JavaScript object or an instance of the NixObject prototype 22 | */ 23 | function NixFunction(args) { 24 | if(args.argSpec === null) { 25 | throw "Cannot derivate function argument specification from a null reference"; 26 | } else if(typeof args.argSpec == "string" || typeof args.argSpec == "object") { 27 | this.argSpec = args.argSpec; 28 | this.body = args.body; 29 | } else { 30 | throw "Cannot derive function argument specification from an object of type: "+args.argSpec; 31 | } 32 | } 33 | 34 | /* NixFunction inherits from NixBlock */ 35 | inherit(NixBlock, NixFunction); 36 | 37 | /** 38 | * @see NixObject#toNixExpr 39 | */ 40 | NixFunction.prototype.toNixExpr = function(indentLevel, format) { 41 | var expr = ""; 42 | 43 | /* Generate the function header */ 44 | if(typeof this.argSpec == "string") { 45 | expr += this.argSpec + ": "; // Use a positional argument when the argument attribute is a string 46 | } else { 47 | expr += "{"; 48 | 49 | if(Array.isArray(this.argSpec)) { 50 | // An array gets converted into an argument attribute set with no default parameters 51 | for(var i = 0; i < this.argSpec.length; i++) { 52 | expr += this.argSpec[i]; 53 | 54 | if(i < this.argSpec.length - 1) 55 | expr += ", "; 56 | } 57 | } else { 58 | var first = true; 59 | 60 | // An object gets converted into an argument attribute set in which the keys correspond to the parameter names and values to the default parameters 61 | for(var varName in this.argSpec) { 62 | var value = this.argSpec[varName]; 63 | 64 | if(first) 65 | first = false; 66 | else 67 | expr += ", "; 68 | 69 | expr += varName; 70 | 71 | /* If the value is defined, consider it a default value */ 72 | if(value !== undefined) 73 | expr += " ? " + nijs.jsToIndentedNix(value, indentLevel + 1, format); 74 | } 75 | } 76 | 77 | expr += "}:\n\n" + nijs.generateIndentation(indentLevel, format); 78 | } 79 | 80 | /* Generate the function body */ 81 | expr += nijs.jsToIndentedNix(this.body, indentLevel, format); 82 | 83 | /* Return the generated expression */ 84 | return expr; 85 | }; 86 | 87 | exports.NixFunction = NixFunction; 88 | -------------------------------------------------------------------------------- /lib/ast/NixIf.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixBlock = require('./NixBlock.js').NixBlock; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixIf instance. 7 | * 8 | * @class NixIf 9 | * @extends NixBlock 10 | * @classdesc Captures the abstract syntax of a Nix of if-then-else statement. 11 | * 12 | * @constructor 13 | * @param {Object} args Arguments to this function 14 | * @param {Mixed} args.ifExpr An object representing an expression evaluating to a boolean 15 | * @param {Mixed} args.thenExpr Expression that gets evaluated if the condition is true 16 | * @param {Mixed} args.elseExpr Expression that gets evaluated if the condition is false 17 | */ 18 | function NixIf(args) { 19 | this.ifExpr = args.ifExpr; 20 | this.thenExpr = args.thenExpr; 21 | this.elseExpr = args.elseExpr; 22 | } 23 | 24 | /* NixIf inherits from NixBlock */ 25 | inherit(NixBlock, NixIf); 26 | 27 | /** 28 | * @see NixObject#toNixExpr 29 | */ 30 | NixIf.prototype.toNixExpr = function(indentLevel, format) { 31 | return "if " + nijs.jsToIndentedNix(this.ifExpr, indentLevel, format) + 32 | " then " + nijs.jsToIndentedNix(this.thenExpr, indentLevel, format) + 33 | " else " + nijs.jsToIndentedNix(this.elseExpr, indentLevel, format); 34 | }; 35 | 36 | exports.NixIf = NixIf; 37 | -------------------------------------------------------------------------------- /lib/ast/NixImport.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var inherit = require('./util/inherit.js').inherit; 3 | var NixFunInvocation = require('./NixFunInvocation.js').NixFunInvocation; 4 | var NixExpression = require('./NixExpression.js').NixExpression; 5 | 6 | /** 7 | * Creates a new NixImport instance. 8 | * 9 | * @class NixImport 10 | * @extends NixFunInvocation 11 | * @classdesc A Nix object that imports an external Nix expression file 12 | * 13 | * @constructor 14 | * @param {String} value A sub expression referring to an external Nix expression file 15 | */ 16 | 17 | function NixImport(value) { 18 | NixFunInvocation.call(this, { 19 | funExpr: new NixExpression("import"), 20 | paramExpr: value 21 | }); 22 | }; 23 | 24 | /* NixImport inherits from NixFunInvocation */ 25 | inherit(NixFunInvocation, NixImport); 26 | 27 | exports.NixImport = NixImport; 28 | -------------------------------------------------------------------------------- /lib/ast/NixInherit.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixObject = require('./NixObject.js').NixObject; 3 | 4 | /** 5 | * Creates a new NixInherit instance. 6 | * 7 | * @class NixInherit 8 | * @extends NixObject 9 | * @classdesc Captures the abstract syntax of a Nix inherit statement that 10 | * imports a value into the current lexical scope. Inheriting value `a` is 11 | * semantically equivalent to the assignment `a = a` in the Nix expression 12 | * language. 13 | * 14 | * @constructor 15 | * @param {String} scope Name of the scope or undefined to inherit from the current lexical scope 16 | */ 17 | function NixInherit(scope) { 18 | this.scope = scope; 19 | } 20 | 21 | /* NixInherit inherits from NixObject */ 22 | inherit(NixObject, NixInherit); 23 | 24 | /** 25 | * @see NixObject#toNixExpr 26 | */ 27 | NixInherit.prototype.toNixExpr = function(indentLevel, format) { 28 | var expr = "inherit"; 29 | 30 | if(this.scope !== undefined) { 31 | expr += " (" + this.scope + ")"; 32 | } 33 | 34 | return expr; 35 | }; 36 | 37 | /** 38 | * Checks whether this object is equal to another NixInherit object. 39 | * 40 | * @method 41 | * @return {Boolean} true, if and only if, both objects have the same properties and inherit from the same prototype. 42 | */ 43 | NixInherit.prototype.equals = function(nixInherit) { 44 | return (nixInherit instanceof NixInherit && this.scope === nixInherit.scope); 45 | }; 46 | 47 | exports.NixInherit = NixInherit; 48 | -------------------------------------------------------------------------------- /lib/ast/NixInlineJS.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixFunInvocation = require('./NixFunInvocation.js').NixFunInvocation; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixInlineJS instance. 7 | * 8 | * @class NixInlineJS 9 | * @extends NixFunInvocation 10 | * @classdesc Creates embedded shell code in a string performing a Node.js 11 | * invocation to execute an inline JavaScript code fragment. 12 | * 13 | * @constructor 14 | * @param {Object} args Arguments to the function 15 | * @param {Function} args.code A JavaScript function containing code that must be executed 16 | * @param {Object[]} args.requires An array of objects representing var-module pairs used to include CommonJS modules. 17 | * var contains the identifier of the variable, the module the path to the CommonJS module 18 | * @param {Object[]} args.module An array of Nix expressions containing Node.js packages that this function must utilise. 19 | */ 20 | function NixInlineJS(args) { 21 | 22 | /* Compose the NixInlineJS function's parameters */ 23 | var params = {}; 24 | 25 | if(typeof args.code == "function") { 26 | params.codeIsFunction = true; 27 | params.code = args.code.toString(); 28 | } else { 29 | params.codeIsFunction = false; 30 | params.code = args.code; 31 | } 32 | 33 | if(args.requires === undefined) 34 | params.requires = []; 35 | else 36 | params.requires = args.requires; 37 | 38 | if(args.modules === undefined) 39 | params.modules = []; 40 | else 41 | params.modules = args.modules; 42 | 43 | /* Construct function invocation object to the nijsInlineProxy */ 44 | NixFunInvocation.call(this, { 45 | funExpr: new nijs.NixExpression("nijsInlineProxy"), 46 | paramExpr: params 47 | }); 48 | } 49 | 50 | /* NixInlineJS inherits from NixFunInvocation */ 51 | inherit(NixFunInvocation, NixInlineJS); 52 | 53 | exports.NixInlineJS = NixInlineJS; 54 | -------------------------------------------------------------------------------- /lib/ast/NixLet.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixBlock = require('./NixBlock.js').NixBlock; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixLet instance. 7 | * 8 | * @class NixLet 9 | * @extends NixBlock 10 | * @classdesc Captures the abstract syntax of a Nix let block containing local variables. 11 | * 12 | * @constructor 13 | * @param {Object} args Arguments to this function 14 | * @param {Object} args.value An arbitrary object that should be represented as a let block. This object is stored as a reference. 15 | * @param {Object} args.body Body of the let block containing an expression that should get evaluated 16 | */ 17 | function NixLet(args) { 18 | this.value = args.value; 19 | this.body = args.body; 20 | } 21 | 22 | /* NixLet inherits from NixBlock */ 23 | inherit(NixBlock, NixLet); 24 | 25 | /** 26 | * @see NixObject#toNixExpr 27 | */ 28 | NixLet.prototype.toNixExpr = function(indentLevel, format) { 29 | var indentation = nijs.generateIndentation(indentLevel, format); 30 | 31 | return "let\n" + 32 | nijs.objectMembersToAttrsMembers(this.value, indentLevel + 1, format) + 33 | indentation + "in\n" + 34 | indentation + nijs.jsToIndentedNix(this.body, indentLevel, format); 35 | }; 36 | 37 | exports.NixLet = NixLet; 38 | -------------------------------------------------------------------------------- /lib/ast/NixMergeAttrs.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixBlock = require('./NixBlock.js').NixBlock; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixMergeAttrs instance. 7 | * 8 | * @class NixMergeAttrs 9 | * @extends NixBlock 10 | * @classdesc Captures the abstract syntax of the Nix attribute set merge 11 | * operator // which merges the fields of two sets together. If there are 12 | * duplicate key names the latter takes precedence over the former. 13 | * 14 | * @constructor 15 | * @param {Object} args Arguments to this function 16 | * @param {Mixed} args.left An object yielding an attribute set 17 | * @param {Mixed} args.right An object yielding an attribute set 18 | */ 19 | 20 | function NixMergeAttrs(args) { 21 | this.left = args.left; 22 | this.right = args.right; 23 | } 24 | 25 | /* NixMergeAttrs inherits from NixBlock */ 26 | inherit(NixBlock, NixMergeAttrs); 27 | 28 | /** 29 | * @see NixObject#toNixExpr 30 | */ 31 | NixMergeAttrs.prototype.toNixExpr = function(indentLevel, format) { 32 | /* Generate the sub expression that yields the left attribute set */ 33 | var leftExpr = nijs.jsToIndentedNix(this.left, indentLevel, format); 34 | 35 | if(this.left instanceof nijs.NixBlock) { // Some objects require ( ) around them to make them work 36 | leftExpr = this.left.wrapInParenthesis(leftExpr); 37 | } 38 | 39 | /* Generate the sub expression that yields the right attribute set */ 40 | var rightExpr = nijs.jsToIndentedNix(this.right, indentLevel, format); 41 | 42 | if(this.right instanceof nijs.NixBlock) { // Some objects require ( ) around them to make them work 43 | rightExpr = this.right.wrapInParenthesis(rightExpr); 44 | } 45 | 46 | /* Return the generated sub expression */ 47 | return leftExpr + " // " + rightExpr; 48 | }; 49 | 50 | exports.NixMergeAttrs = NixMergeAttrs; 51 | -------------------------------------------------------------------------------- /lib/ast/NixObject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a new NixObject instance. 3 | * 4 | * @class NixObject 5 | * @classdesc Creates a Nix object that captures properties of Nix expression 6 | * language constructs for which no JavaScript equivalent is available. 7 | * 8 | * @constructor 9 | */ 10 | function NixObject() { 11 | }; 12 | 13 | /** 14 | * Converts the Nix object to a string containing the equivalent Nix expression 15 | * 16 | * @method 17 | * @param {Number} indentLevel The indentation level of the resulting sub expression 18 | * @param {Boolean} format Indicates whether to nicely format to expression (i.e. generating whitespaces) or not 19 | * @return {String} String with the equivalent Nix expression 20 | */ 21 | NixObject.prototype.toNixExpr = function(indentLevel, format) { 22 | throw "toNixExpr() is not implemented, please use a prototype that inherits from NixObject"; 23 | }; 24 | 25 | exports.NixObject = NixObject; 26 | -------------------------------------------------------------------------------- /lib/ast/NixRecursiveAttrSet.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixValue = require('./NixValue.js').NixValue; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixRecursiveAttrSet instance. 7 | * 8 | * @class NixRecursiveAttrSet 9 | * @extends NixValue 10 | * @classdesc A recursive attribute set in which members can refer to each other. 11 | * 12 | * @constructor 13 | * @param {Object} value An arbitrary object that should be represented as a recursive attribute set. This object is stored as a reference. 14 | */ 15 | function NixRecursiveAttrSet(value) { 16 | NixValue.call(this, value); 17 | } 18 | 19 | /* NixRecursiveAttrSet inherits from NixValue */ 20 | inherit(NixValue, NixRecursiveAttrSet); 21 | 22 | /** 23 | * @see NixObject#toNixExpr 24 | */ 25 | NixRecursiveAttrSet.prototype.toNixExpr = function(indentLevel, format) { 26 | if(Object.keys(this.value).length == 0) { 27 | return "rec {}"; 28 | } else { 29 | return "rec {\n" + 30 | nijs.objectMembersToAttrsMembers(this.value, indentLevel + 1, format) + 31 | nijs.generateIndentation(indentLevel, format) + "}"; 32 | } 33 | }; 34 | 35 | exports.NixRecursiveAttrSet = NixRecursiveAttrSet; 36 | -------------------------------------------------------------------------------- /lib/ast/NixStorePath.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var inherit = require('./util/inherit.js').inherit; 3 | var NixFunInvocation = require('./NixFunInvocation.js').NixFunInvocation; 4 | var NixExpression = require('./NixExpression.js').NixExpression; 5 | 6 | /** 7 | * Creates a new NixStorePath instance. 8 | * 9 | * @class NixStorePath 10 | * @extends NixFunInvocation 11 | * @classdesc A Nix object that represents a reference to a file that resides in 12 | * the Nix store. This object is useful to directly refer to something that is 13 | * in the Nix store, without copying it. 14 | * 15 | * @constructor 16 | * @param {String} value A sub expression referring to a Nix store file 17 | */ 18 | 19 | function NixStorePath(value) { 20 | NixFunInvocation.call(this, { 21 | funExpr: new NixExpression("builtins.storePath"), 22 | paramExpr: value 23 | }); 24 | }; 25 | 26 | /* NixStorePath inherits from NixFunInvocation */ 27 | inherit(NixFunInvocation, NixStorePath); 28 | 29 | exports.NixStorePath = NixStorePath; 30 | -------------------------------------------------------------------------------- /lib/ast/NixURL.js: -------------------------------------------------------------------------------- 1 | var url = require('url'); 2 | var inherit = require('./util/inherit.js').inherit; 3 | var NixValue = require('./NixValue.js').NixValue; 4 | 5 | /** 6 | * Creates a new NixURL instance. 7 | * 8 | * @class NixURL 9 | * @extends NixValue 10 | * @classdesc A Nix URL object that gets validated by the Nix expression evaluator. 11 | * 12 | * @constructor 13 | * @param {String} value Value containing a URL 14 | */ 15 | function NixURL(value) { 16 | NixValue.call(this, value); 17 | }; 18 | 19 | /* NixURL inherits from NixValue */ 20 | inherit(NixValue, NixURL); 21 | 22 | /** 23 | * @see NixObject#toNixExpr 24 | */ 25 | NixURL.prototype.toNixExpr = function(indentLevel, format) { 26 | var parsedURL = url.parse(this.value); 27 | 28 | if(parsedURL.href.indexOf('#') == -1) 29 | return parsedURL.href; 30 | else 31 | return '"' + parsedURL.href + '"'; // If the URL contains # symbol, then return a string. Otherwise, Nix sees it as a comment. 32 | }; 33 | 34 | exports.NixURL = NixURL; 35 | -------------------------------------------------------------------------------- /lib/ast/NixValue.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixObject = require('./NixObject.js').NixObject; 3 | 4 | /** 5 | * Creates a new NixValue instance. 6 | * 7 | * @class NixValue 8 | * @extends NixObject 9 | * @classdesc Creates a Nix value object that captures common properties of 10 | * value objects in the Nix expression language, for which is no equivalent 11 | * JavaScript object available. 12 | * 13 | * @constructor 14 | * @param {Mixed} value Value of the reference 15 | */ 16 | function NixValue(value) { 17 | this.value = value; 18 | }; 19 | 20 | /* NixValue inherits from NixObject */ 21 | inherit(NixObject, NixValue); 22 | 23 | exports.NixValue = NixValue; 24 | -------------------------------------------------------------------------------- /lib/ast/NixWith.js: -------------------------------------------------------------------------------- 1 | var inherit = require('./util/inherit.js').inherit; 2 | var NixBlock = require('./NixBlock.js').NixBlock; 3 | var nijs = require('../nijs.js'); 4 | 5 | /** 6 | * Creates a new NixWith instance. 7 | * 8 | * @class NixWith 9 | * @extends NixBlock 10 | * @classdesc Captures the abstract syntax of a Nix with block importing 11 | * variables of the attribute set parameter into the lexical scope of the body 12 | * 13 | * @constructor 14 | * @param {Object} args Arguments to this function 15 | * @param {Object} args.withExpr An expression yielding an attribute set 16 | * @param {Object} args.body Body of the let block containing an arbitrary expression in which the members of the attribute set are imported 17 | */ 18 | function NixWith(args) { 19 | this.withExpr = args.withExpr; 20 | this.body = args.body; 21 | } 22 | 23 | /* NixWith inherits from NixBlock */ 24 | inherit(NixBlock, NixWith); 25 | 26 | /** 27 | * @see NixObject#toNixExpr 28 | */ 29 | NixWith.prototype.toNixExpr = function(indentLevel, format) { 30 | return "with "+nijs.jsToIndentedNix(this.withExpr, indentLevel, format)+";\n\n"+ 31 | nijs.generateIndentation(indentLevel, format) + nijs.jsToIndentedNix(this.body, indentLevel, format); 32 | }; 33 | 34 | exports.NixWith = NixWith; 35 | -------------------------------------------------------------------------------- /lib/ast/util/inherit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module inherit 3 | */ 4 | 5 | function inherit(parent, child) { 6 | function F() {}; /* Dummy constructor function used to create an empty object with a prototype containing the parent's class definition */ 7 | F.prototype = parent.prototype; /* Assign the parent constructor function's prototype property (not the real prototype) to the dummy constructor function. */ 8 | child.prototype = new F(); /* Create an instance of the dummy constructor. This call returns an empty object, which prototype contains the parent's class definition */ 9 | child.prototype.constructor = child; /* Set the constructor to our child constructor function again, as it has been changed by the parent's prototype */ 10 | } 11 | 12 | /** 13 | * Do a simulated class inheritance using a function representing the 14 | * constructor of a base class and a function representing the constructor of 15 | * a child class. I could (of course) use yet another particular library to do 16 | * this, but this will also introduce another dependency on another package. 17 | * Therefore, I did it myself. 18 | * 19 | * I don't dislike the concept of prototypes, but the way it's implemented in 20 | * JavaScript is just too crazy. You have to do some crazy stuff to properly set 21 | * prototypes, as we cannot control them directly. Anyway, this function 22 | * abstracts over that burden so that we don't have to repeat this every time. 23 | * 24 | * @function 25 | * @param {Function} parent Constructor function of the simulated parent class 26 | * @param {Function} child Constructor function of the simulated child class 27 | */ 28 | exports.inherit = inherit; 29 | -------------------------------------------------------------------------------- /lib/build.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains utility functions that build packages with the Nix package manager 3 | * @module build 4 | */ 5 | var path = require('path'); 6 | var child_process = require('child_process'); 7 | var nijs = require('./nijs.js'); 8 | 9 | function nixBuild(args) { 10 | var output = ""; 11 | 12 | /* Spawn nix-build process */ 13 | var nixBuildProcess = child_process.spawn("nix-build", args.params.concat(["-"])); 14 | 15 | nixBuildProcess.stdin.write(args.expression); 16 | nixBuildProcess.stdin.end(); 17 | 18 | nixBuildProcess.stdout.on("data", function(data) { 19 | output += data; /* Capture the Nix store path */ 20 | }); 21 | 22 | nixBuildProcess.stderr.on("data", function(data) { 23 | process.stderr.write(data); 24 | }); 25 | 26 | nixBuildProcess.on("exit", function(code) { 27 | if(code == 0) 28 | args.callback(null, output.substring(0, output.length - 1)); 29 | else 30 | args.callback("nix-build exited with status: "+code); 31 | }); 32 | }; 33 | 34 | /** 35 | * Invokes the nix-build process to evaluate a given nix object containing a Nix 36 | * expression. As a side-effect, the declared package gets built. 37 | * 38 | * @function 39 | * @param {Object} args Nix build parameters 40 | * @param {String} args.expression A string containing a Nix expression 41 | * @param {String[]} args.params An array of strings representing command-line parameters passed to nix-build 42 | * @param {function(number, string)} args.callback Callback function that gets called with the non-zero exit status if the build fails, or the resulting Nix store path if it succeeds 43 | */ 44 | exports.nixBuild = nixBuild; 45 | 46 | function callNixBuild(args) { 47 | var pkgsExpression; 48 | 49 | if(args.pkgsExpression === undefined) 50 | pkgsExpression = "import {}"; 51 | else 52 | pkgsExpression = args.pkgsExpression; 53 | 54 | /* 55 | * Hacky way to determine whether nijs is deployed by Nix or NPM. 56 | * If deployed by the latter, we need to somehow get it in the Nix store 57 | * when invoking JavaScript functions or inline JavaScript 58 | */ 59 | 60 | var modulePathComponents = module.filename.split(path.sep); 61 | var nijsPath; 62 | 63 | if(modulePathComponents.length >= 8) { 64 | var rootPathComponent = modulePathComponents[modulePathComponents.length - 6]; 65 | 66 | if(rootPathComponent.substring(32, 33) == "-") // This looks very much like a Nix store path 67 | nijsPath = "builtins.storePath " + path.resolve(path.join(path.dirname(module.filename), "..", "..", "..", "..")); 68 | else 69 | nijsPath = "builtins.getAttr (builtins.currentSystem) ((import " + path.resolve(path.join(path.dirname(module.filename), "..", "release.nix")) + " {}).build)"; 70 | } 71 | 72 | /* Generate a Nix expression and evaluate it */ 73 | var expression = "let\n"+ 74 | " pkgs = " + pkgsExpression + ";\n"+ 75 | " nijs = "+ nijsPath + ";\n"+ 76 | ' nijsFunProxy = import "${nijs}/lib/node_modules/nijs/lib/funProxy.nix" { inherit (pkgs) stdenv lib nodejs; inherit nijs; };\n'+ 77 | ' nijsInlineProxy = import "${nijs}/lib/node_modules/nijs/lib/inlineProxy.nix" { inherit (pkgs) stdenv lib writeTextFile nodejs; inherit nijs; };\n'+ 78 | "in\n" + 79 | args.nixExpression; 80 | 81 | nixBuild({ 82 | expression : expression, 83 | params : args.params, 84 | callback : args.callback 85 | }); 86 | } 87 | 88 | /** 89 | * Augments a given Nix object with a Nix expression with a Nixpkgs and NiJS 90 | * reference and executes nix-build to evaluate the expression. 91 | * 92 | * @function 93 | * @param {Object} args Nix build parameters 94 | * @param {String} args.nixExpression A string that contains a Nix expression 95 | * @param {String[]} args.params An array of strings representing command-line parameters passed to nix-build 96 | * @param {String} args.pkgsExpression An optional string containing a Nix expression importing the Nix packages collection. Defaults to the system's nixpkgs setting. 97 | * @param {function(number, string)} args.callback Callback function that gets called with the non-zero exit status if the build fails, or the resulting Nix store path if it succeeds 98 | */ 99 | exports.callNixBuild = callNixBuild; 100 | -------------------------------------------------------------------------------- /lib/execute/builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # Set the TZ (timezone) environment variable, otherwise commands like 4 | # `date' will complain (e.g., `Tue Mar 9 10:01:47 Local time zone must 5 | # be set--see zic manual page 2004'). 6 | export TZ=UTC 7 | 8 | addToSearchPath() 9 | { 10 | local varName="$1" 11 | local value="$2" 12 | 13 | if [ -d "$value" ] 14 | then 15 | eval export $varName="$value${!varName:+:}${!varName}" 16 | fi 17 | } 18 | 19 | addToPATH() 20 | { 21 | addToSearchPath PATH "$1/bin" 22 | } 23 | 24 | addToCPATH() 25 | { 26 | addToSearchPath CPATH "$1/include" 27 | } 28 | 29 | addToLIBRARY_PATH() 30 | { 31 | addToSearchPath LIBRARY_PATH "$1/lib" 32 | addToSearchPath LIBRARY_PATH "$1/lib32" 33 | addToSearchPath LIBRARY_PATH "$1/lib64" 34 | } 35 | 36 | envHooks=( "addToPATH" "addToCPATH" "addToLIBRARY_PATH" ) 37 | 38 | addToEnv() 39 | { 40 | local pkg=$1 41 | 42 | for i in "${envHooks[@]}" 43 | do 44 | $i "$pkg" 45 | done 46 | } 47 | 48 | addEnvHooks() 49 | { 50 | local hostOffset="$1" # Ignored in this builder, but for feature parity with Nixpkgs stdenv 51 | envHooks+=("$2") 52 | } 53 | 54 | importBuildInputs() 55 | { 56 | local buildInputs="$@" 57 | 58 | # Modify environment variables (such as PATH) so that the build inputs can be found 59 | 60 | for i in $buildInputs 61 | do 62 | addToEnv $i 63 | done 64 | } 65 | 66 | addPropagatedBuildInputs() 67 | { 68 | for i in $@ 69 | do 70 | if [ -f $i/nix-support/propagated-build-inputs ] 71 | then 72 | local extraBuildInputs="$(cat $i/nix-support/propagated-build-inputs)" 73 | buildInputs="$buildInputs $extraBuildInputs" 74 | addPropagatedBuildInputs $extraBuildInputs 75 | fi 76 | done 77 | } 78 | 79 | sourceSetupHooks() 80 | { 81 | for i in $@ 82 | do 83 | if [ -f $i/nix-support/setup-hook ] 84 | then 85 | source $i/nix-support/setup-hook 86 | fi 87 | done 88 | } 89 | 90 | addPropagatedBuildInputs $buildInputs $propagatedBuildInputs 91 | sourceSetupHooks $buildInputs $propagatedBuildInputs 92 | importBuildInputs $buildInputs $propagatedBuildInputs 93 | 94 | # If propagated build inputs are set, write them to nix-support/propagated-build-inputs 95 | 96 | if [ -n "$propagatedBuildInputs" ] 97 | then 98 | mkdir -p $out/nix-support 99 | echo "$propagatedBuildInputs" > $out/nix-support/propagated-build-inputs 100 | fi 101 | 102 | 103 | # Run a hook. A hook can be defined as function/alias/builtin, a file 104 | # representing a script or process, or a string containing shell code 105 | 106 | runHook() 107 | { 108 | local hookName=$1 109 | local hookType=$(type -t $hookName) 110 | 111 | if [ -z "${!hookName}" ] 112 | then 113 | case "$hookType" in 114 | function|alias|builtin) 115 | $hookName 116 | ;; 117 | file) 118 | source $hookName 119 | ;; 120 | *) 121 | eval "${!hookName}" 122 | ;; 123 | esac 124 | else 125 | eval "${!hookName}" 126 | fi 127 | } 128 | 129 | # Execute a particular phase. Every phase has a pre and post hook, 130 | # which can be configured by the user. Every phase can be disabled 131 | # by setting the dont to true / 1. 132 | 133 | executePhase() 134 | { 135 | local phase=$1 136 | local dontVariableName=dont${phase^} 137 | 138 | if [ -z "${!dontVariableName}" ] 139 | then 140 | runHook pre${phase^} 141 | runHook ${phase}Phase 142 | runHook post${phase^} 143 | fi 144 | } 145 | 146 | # TODO something with buildinputs 147 | 148 | unpackFile() 149 | { 150 | local packedFile="$1" 151 | 152 | case "$packedFile" in 153 | *.tar|*.tar.gz|*.tar.bz2|*.tgz|*.tar.xz|*.tar.lzma) 154 | tar xfv "$packedFile" 155 | ;; 156 | *.zip) 157 | unzip "$packedFile" 158 | ;; 159 | esac 160 | } 161 | 162 | unpackPhase() 163 | { 164 | # Unpack source files 165 | if [ ! -z "$src" ] 166 | then 167 | srcs=$src 168 | fi 169 | 170 | for i in $srcs 171 | do 172 | unpackFile $i 173 | done 174 | 175 | # Enter source directory 176 | if [ -z "$sourceRoot" ] 177 | then 178 | cd * 179 | else 180 | cd $sourceRoot 181 | fi 182 | } 183 | 184 | uncompressFile() 185 | { 186 | local file="$1" 187 | 188 | for i in $uncompressHooks 189 | do 190 | case "$i" in 191 | *.gz) 192 | gzip -cd "$i" 193 | ;; 194 | *.bz2) 195 | bzip2 -cd "$i" 196 | ;; 197 | *.xz) 198 | xz -d < "$i" 199 | ;; 200 | esac 201 | done 202 | } 203 | 204 | patchPhase() 205 | { 206 | for i in $patches 207 | do 208 | case "$i" in 209 | *.patch | *.diff) 210 | cat "$i" | patch $patchFlags 211 | ;; 212 | *) 213 | uncompressFile "$i" | patch $patchFlags 214 | ;; 215 | esac 216 | done 217 | } 218 | 219 | configurePhase() 220 | { 221 | if [ -x $configureScript ] 222 | then 223 | eval $configureScript $prefix $configureFlags 224 | fi 225 | } 226 | 227 | buildPhase() 228 | { 229 | if [ -f $makefile ] 230 | then 231 | eval make -f $makefile $makeFlags $buildFlags 232 | fi 233 | } 234 | 235 | installPhase() 236 | { 237 | if [ -f $makefile ] 238 | then 239 | eval make -f $makefile $makeFlags $installFlags install 240 | fi 241 | } 242 | 243 | if [ -z "$buildCommand" ] 244 | then 245 | # Set some default values 246 | 247 | if [ -z "$configureScript" ] 248 | then 249 | configureScript="./configure" 250 | fi 251 | 252 | if [ -z "$prefix" ] 253 | then 254 | prefix='--prefix=$out' 255 | fi 256 | 257 | if [ -z "$makefile" ] 258 | then 259 | makefile="Makefile" 260 | fi 261 | 262 | if [ -z "$phases" ] 263 | then 264 | phases="unpack patch configure build install" 265 | fi 266 | 267 | # Execute phases 268 | 269 | for phase in $phases 270 | do 271 | executePhase $phase 272 | done 273 | else 274 | eval "$buildCommand" 275 | fi 276 | -------------------------------------------------------------------------------- /lib/execute/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains utility functions that can be used to execute a NiJS package specification directly 3 | * @module execute 4 | */ 5 | var fs = require('fs'); 6 | var path = require('path'); 7 | var child_process = require('child_process'); 8 | var slasp = require('slasp'); 9 | var nijs = require('../nijs.js'); 10 | 11 | function convertToShellArg(arg, callback) { 12 | slasp.when(function(callback) { 13 | callback(arg === null); 14 | }, function(callback) { 15 | callback(null, ""); 16 | }, function() { 17 | slasp.circuit(function(callback) { 18 | callback(null, typeof arg); 19 | }, function(result) { 20 | switch(result) { 21 | case "boolean": 22 | if(arg) 23 | callback(null, "1"); 24 | else 25 | callback(null, ""); 26 | break; 27 | 28 | case "string": 29 | case "number": 30 | case "xml": 31 | callback(null, arg.toString()); 32 | break; 33 | 34 | case "object": 35 | if(Array.isArray(arg)) { 36 | var convertedArg = ""; 37 | var i; 38 | 39 | slasp.from(function(callback) { 40 | i = 0; 41 | callback(null); 42 | }, function(callback) { 43 | callback(null, i < arg.length); 44 | }, function(callback) { 45 | i++; 46 | callback(null); 47 | }, function(callback) { 48 | slasp.sequence([ 49 | function(callback) { 50 | if(i > 0) 51 | convertedArg += " "; 52 | 53 | convertToShellArg(arg[i], callback); 54 | }, 55 | 56 | function(callback, shellArg) { 57 | convertedArg += shellArg; 58 | callback(null); 59 | } 60 | ], callback); 61 | }, function(err) { 62 | if(err) 63 | callback(err); 64 | else 65 | callback(null, convertedArg); 66 | }); 67 | } else if(arg instanceof nijs.NixURL) { 68 | callback(null, arg.value); 69 | } else if(arg instanceof nijs.NixFile) { 70 | var filePath; 71 | 72 | slasp.sequence([ 73 | function(callback) { 74 | if(arg.module === undefined) 75 | filePath = arg.value; 76 | else 77 | filePath = path.join(path.dirname(arg.module.filename), arg.value); 78 | 79 | fs.exists(filePath, function(exists) { 80 | callback(null, exists); 81 | }); 82 | }, 83 | 84 | function(_, exists) { 85 | if(exists) 86 | callback(null, filePath); 87 | else 88 | callback(filePath + " does not exists!"); 89 | } 90 | ], callback); 91 | } else if(arg instanceof nijs.NixExpression) { 92 | nijs.callNixBuild({ 93 | nixExpression : arg, 94 | params : [ "--no-out-link" ], 95 | callback : callback 96 | }); 97 | } else if(arg instanceof nijs.NixInlineJS) { 98 | var buildCommand = 'cat > $out << "___EOF___"\n' + 99 | "(\n" + 100 | "export NODE_PATH=" + path.resolve(path.join(path.dirname(module.filename), "..", "..", "..")) + ":" + path.resolve(path.join(path.dirname(module.filename), "..", "..", "node_modules")) + "\n" + 101 | "(\n"+ 102 | 'cat << "__EOF__"\n' + 103 | "var nijs = require('nijs');\n"; 104 | 105 | for(var i = 0; i < arg.paramExpr.requires.length; i++) { 106 | var require = arg.paramExpr.requires[i]; 107 | buildCommand += "var " + require['var'] + " = require('" + require.module + "');\n"; 108 | } 109 | 110 | if(arg.paramExpr.codeIsFunction) 111 | buildCommand += "(" + arg.paramExpr.code.toString() + ")();\n"; 112 | else 113 | buildCommand += arg.paramExpr.code.toString() + "\n"; 114 | 115 | buildCommand += "__EOF__\n" + 116 | ") | node\n" + 117 | ")\n" + 118 | "___EOF___\n" + 119 | "chmod 755 $out\n"; 120 | 121 | evaluateDerivation({ 122 | name: "inline-proxy" + (arg.paramExpr.name ? "-" + arg.paramExpr.name : ""), 123 | buildCommand : buildCommand 124 | }, callback); 125 | } else if(arg instanceof nijs.NixRecursiveAttrSet) { 126 | evaluateDerivation(arg.value, callback); 127 | } else { 128 | evaluateDerivation(arg, callback); 129 | } 130 | break; 131 | 132 | case "undefined": 133 | callback(null, "undefined"); 134 | break; 135 | 136 | default: 137 | callback("Encountered an object of an unknown type"); 138 | } 139 | }, callback); 140 | }, callback); 141 | } 142 | 143 | /** 144 | * Converts an object with function parameters to a representation that can be 145 | * used as environment variables in a builder environment. 146 | * 147 | * @function 148 | * @param {Object} args An object representing the function arguments that must be converted 149 | * @param {function(Object, Object)} callback Callback that gets invoked if an error occured or if the work is done. 150 | */ 151 | exports.convertToShellArg = convertToShellArg; 152 | 153 | function createFolder(folder, callback) { 154 | fs.mkdir(folder, function(err) { 155 | if(err) { 156 | if(err.code == "EEXIST") // If the directory already exists, assume it's fine 157 | callback(null); 158 | else 159 | callback(err); 160 | } else { 161 | callback(null); 162 | } 163 | }); 164 | } 165 | 166 | function evaluateDerivation(args, callback) { 167 | var shellArgs = {}; 168 | var builderTempDir; 169 | var out; 170 | 171 | slasp.sequence([ 172 | function(callback) { 173 | /* Ignore meta attributes */ 174 | delete args.meta; 175 | 176 | /* We must have a name */ 177 | if(args.name === undefined) 178 | callback("The derivation must have a name!\n"); 179 | 180 | /* Convert derivation arguments to shell arguments */ 181 | slasp.fromEach(function(callback) { callback(null, args); }, function(argName, callback) { 182 | slasp.sequence([ 183 | function(callback) { 184 | convertToShellArg(args[argName], callback); 185 | }, 186 | 187 | function(callback, shellArg) { 188 | shellArgs[argName] = shellArg; 189 | callback(null); 190 | } 191 | ], callback); 192 | }, callback); 193 | }, 194 | 195 | function(callback) { 196 | createFolder(path.dirname(NIJS_EXECUTE_TMPDIR), callback); 197 | }, 198 | 199 | function(callback) { 200 | createFolder(NIJS_EXECUTE_TMPDIR, callback); 201 | }, 202 | 203 | function(callback) { 204 | createFolder(path.dirname(NIJS_EXECUTE_OUTPUT), callback); 205 | }, 206 | 207 | function(callback) { 208 | createFolder(NIJS_EXECUTE_OUTPUT, callback); 209 | }, 210 | 211 | function(callback) { 212 | /* Generate output path */ 213 | out = path.join(NIJS_EXECUTE_OUTPUT, args.name); 214 | 215 | /* Generate temp dir for the builder */ 216 | builderTempDir = path.join(NIJS_EXECUTE_TMPDIR, args.name); 217 | createFolder(builderTempDir, callback); 218 | }, 219 | 220 | function() { 221 | /* Generate builder environment */ 222 | 223 | var builderEnv = { 224 | "NIJS_STORE" : NIJS_EXECUTE_OUTPUT, 225 | "NIJS_BUILD_TOP" : NIJS_EXECUTE_TMPDIR, 226 | "TMPDIR" : NIJS_EXECUTE_TMPDIR, 227 | "TEMPDIR" : NIJS_EXECUTE_TMPDIR, 228 | "TMP" : NIJS_EXECUTE_TMPDIR, 229 | "TEMP" : NIJS_EXECUTE_TMPDIR, 230 | "PATH" : process.env['PATH'], 231 | "HOME" : "/homeless-shelter", 232 | "out" : out 233 | }; 234 | 235 | /* Merge shellArgs into the builder environment */ 236 | 237 | for(var name in shellArgs) { 238 | builderEnv[name] = shellArgs[name]; 239 | } 240 | 241 | /* Execute builder process */ 242 | 243 | var builder; 244 | 245 | if(builderEnv.builder) 246 | builder = builderEnv.builder; 247 | else 248 | builder = path.join(path.dirname(module.filename), "builder.sh"); 249 | 250 | var builderProcess = child_process.spawn("/bin/sh", [ builder ], { cwd : builderTempDir, env : builderEnv }); 251 | 252 | builderProcess.stderr.on("data", function(data) { 253 | process.stderr.write(data); 254 | }); 255 | 256 | builderProcess.stdout.on("data", function(data) { 257 | process.stdout.write(data); 258 | }); 259 | 260 | builderProcess.on("exit", function(code) { 261 | if(code == 0) 262 | callback(null, path.join(NIJS_EXECUTE_OUTPUT, args.name)); 263 | else 264 | callback("builder exited with status: " + code); 265 | }); 266 | } 267 | ], callback); 268 | } 269 | 270 | /** 271 | * Directly executes derivations asynchronously. 272 | * 273 | * @function 274 | * @param {Object} args Parameters to pass to the builder environment. 275 | * @param {function(Object, Object)} callback Callback that gets invoked if an error occured or if the work is done. 276 | */ 277 | exports.evaluateDerivation = evaluateDerivation; 278 | -------------------------------------------------------------------------------- /lib/funProxy.nix: -------------------------------------------------------------------------------- 1 | {stdenv, lib, nodejs, nijs}: 2 | {name ? null, function, args, modules ? [], requires ? [], NODE_PATH ? "", async ? false, format ? false}: 3 | 4 | let 5 | nixToJS = import ./nixToJS.nix { inherit lib; }; 6 | in 7 | import (stdenv.mkDerivation { 8 | name = "function-proxy${if name == null then "" else "-${name}"}.nix"; 9 | inherit NODE_PATH; 10 | buildInputs = [ nodejs nijs ] ++ modules; 11 | buildCommand = '' 12 | ( 13 | cat < this is analogous to JSON 96 | ) { 97 | var indentation = generateIndentation(indentLevel, format); 98 | var attrKey = objectKeyToAttrName(attrName); 99 | 100 | /* Create the converted Nix expression */ 101 | str += indentation + attrKey + " = " + jsToIndentedNix(attrValue, indentLevel, format) + ";\n"; 102 | } 103 | } 104 | 105 | return str; 106 | } 107 | 108 | /** 109 | * Converts members of an object to members of an attribute set 110 | * 111 | * @function 112 | * @param {Object} obj Object to convert 113 | * @param {Number} indentLevel The indentation level of the resulting sub expression 114 | * @param {Boolean} format Indicates whether to nicely format to expression (i.e. generating whitespaces) or not 115 | * @return {String} A string containing the Nix attribute set members 116 | */ 117 | exports.objectMembersToAttrsMembers = objectMembersToAttrsMembers; 118 | 119 | function objectToIndentedNix(arg, indentLevel, format) { 120 | var expr; 121 | 122 | if(Object.keys(arg).length == 0) { 123 | expr = "{}"; // For empty object, write a single line attribute set without linefeeds between object members 124 | } else { 125 | var indentation = generateIndentation(indentLevel, format); 126 | 127 | expr = "{\n" + 128 | objectMembersToAttrsMembers(arg, indentLevel + 1, format) + 129 | indentation + "}"; 130 | } 131 | 132 | return expr; 133 | } 134 | 135 | function arrayToIndentedNix(arg, indentLevel, format) { 136 | var expr; 137 | 138 | if(arg.length == 0) { 139 | expr = "[]"; // For empty arrays, write a single line empty list without linefeeds between elements 140 | } else { 141 | expr = "[\n"; 142 | 143 | var indentation = generateIndentation(indentLevel, format); 144 | 145 | for(var i = 0; i < arg.length; i++) { 146 | var listMemberExpr = jsToIndentedNix(arg[i], indentLevel + 1, format); 147 | 148 | /* Some objects in a list require ( ) wrapped around them to make them work, because whitespaces are in principle the delimiter symbols in lists */ 149 | if(arg[i] instanceof nijs.NixBlock) { 150 | listMemberExpr = arg[i].wrapInParenthesis(listMemberExpr); 151 | } 152 | 153 | expr += generateIndentation(indentLevel + 1, format) + listMemberExpr + "\n"; 154 | } 155 | 156 | expr += indentation + "]"; 157 | } 158 | 159 | return expr; 160 | } 161 | 162 | function booleanToIndentedNix(arg) { 163 | if(arg) 164 | return "true"; 165 | else 166 | return "false"; 167 | } 168 | 169 | function stringToIndentedNix(arg) { 170 | return '"'+arg.replace(/\\/g, '\\\\').replace(/\"/g, '\\"')+'"'; // Escape \ and " 171 | } 172 | 173 | function xmlToIndentedNix(arg) { 174 | return '"'+arg.toXMLString().replace(/\"/g, '\\"')+'"'; 175 | } 176 | 177 | function functionToIndentedNix(arg, indentLevel, format) { 178 | var expr = ""; 179 | var indentation = generateIndentation(indentLevel + 1, format); 180 | 181 | for(var i = 0; i < arg.length; i++) 182 | expr += "arg" + i + ": "; 183 | 184 | expr += "\n" + indentation + "nijsFunProxy {\n" + 185 | indentation + " function = ''"+arg.toString()+"'';\n" + 186 | indentation + " args = [\n"; 187 | 188 | for(var i = 0; i < arg.length; i++) 189 | expr += indentation + " arg" + i + "\n"; 190 | 191 | expr += indentation + " ];\n" + 192 | indentation + "}"; 193 | 194 | return expr; 195 | } 196 | 197 | function jsToIndentedNix() { 198 | var expr = ""; 199 | var indentLevel = arguments[arguments.length - 2]; 200 | var format = arguments[arguments.length - 1]; 201 | 202 | for(var i = 0; i < arguments.length - 2; i++) { 203 | 204 | var arg = arguments[i]; 205 | 206 | if(i > 0) 207 | expr += " "; /* Add white space between every argument */ 208 | 209 | if(arg === null) { 210 | expr += "null"; /* We must check for the null reference explicitly */ 211 | } else { 212 | 213 | /* Use a type match to determine the conversion from a JavaScript object to a Nix expression language object */ 214 | var type = typeof arg; 215 | 216 | switch(type) { 217 | case "boolean": 218 | expr += booleanToIndentedNix(arg); 219 | break; 220 | 221 | case "number": 222 | expr += arg; 223 | break; 224 | 225 | case "string": 226 | expr += stringToIndentedNix(arg); 227 | break; 228 | 229 | case "object": 230 | if(Array.isArray(arg)) { // Arrays are also objects, but this will tell us the difference 231 | expr += arrayToIndentedNix(arg, indentLevel, format); 232 | } else if(arg instanceof nijs.NixObject) { 233 | expr += arg.toNixExpr(indentLevel, format); // NixObject instances represent Nix expression language constructs that have no JavaScript equivalent 234 | } else { 235 | expr += objectToIndentedNix(arg, indentLevel, format); // If nothing else matches, we treat it is an ordinary object 236 | } 237 | break; 238 | 239 | case "function": 240 | expr += functionToIndentedNix(arg, indentLevel, format); 241 | break; 242 | 243 | case "xml": 244 | expr += xmlToIndentedNix(arg); 245 | break; 246 | 247 | case "undefined": 248 | expr += "null"; 249 | break; 250 | } 251 | } 252 | } 253 | 254 | return expr; 255 | } 256 | 257 | /** 258 | * Converts a collection of JavaScript objects to a semantically equivalent or 259 | * similar Nix expression language object. It also uses indentation to format the 260 | * resulting sub expression more nicely. 261 | * 262 | * @function 263 | * @param {...*} var_args A variable amount of parameters that can be of any JavaScript object type. 264 | * The second last parameter is a numeric value must be provided to specify the indentation level of the resulting sub expression. 265 | * The last parameter is a boolean value indicating whether to nicely format to expression (i.e. generating whitespaces) or not 266 | * @return {String} A string containing the converted Nix expression language object 267 | */ 268 | exports.jsToIndentedNix = jsToIndentedNix; 269 | 270 | function jsToNix() { 271 | var args = Array.prototype.slice.call(arguments, 0); 272 | 273 | var format = args[args.length - 1]; // Take last parameter 274 | args[args.length - 1] = 0; // Change last parameter by the indent level: 0 275 | args.push(format); // Append format boolean parameter to arguments array 276 | 277 | return jsToIndentedNix.apply(this, args, format); 278 | } 279 | 280 | /** 281 | * Converts a collection of JavaScript objects to a semantically equivalent or 282 | * similar Nix expression language object. 283 | * 284 | * @function 285 | * @param {...*} var_args A variable amount of parameters that can be of any JavaScript object type. 286 | * The last parameter is a boolean value indicating whether to nicely format to expression (i.e. generating whitespaces) or not 287 | * @return {String} A string containing the converted Nix expression language object 288 | */ 289 | exports.jsToNix = jsToNix; 290 | -------------------------------------------------------------------------------- /lib/importPackage.nix: -------------------------------------------------------------------------------- 1 | {nixpkgs, system, nijs}: 2 | {pkgsJsFile, attrName, format ? false}: 3 | 4 | let 5 | pkgs = import nixpkgs { inherit system; }; 6 | 7 | nijsInlineProxy = import ./inlineProxy.nix { 8 | inherit (pkgs) stdenv lib writeTextFile nodejs; 9 | inherit nijs; 10 | }; 11 | in 12 | import (pkgs.stdenv.mkDerivation { 13 | name = "importPackage-${attrName}.nix"; 14 | 15 | buildCommand = nijsInlineProxy { 16 | name = "importPackage-${attrName}-buildCommand"; 17 | requires = [ 18 | { var = "fs"; module = "fs"; } 19 | { var = "pkgsJsFile"; module = pkgsJsFile; } 20 | ]; 21 | code = '' 22 | var expr = new nijs.NixLet({ 23 | value : { 24 | pkgs : new nijs.NixFunInvocation({ 25 | funExpr: new nijs.NixImport(new nijs.NixStorePath('${nixpkgs}')), 26 | paramExpr: { 27 | system: '${system}' 28 | } 29 | }), 30 | nijs : new nijs.NixStorePath('${nijs}'), 31 | nijsFunProxy: new nijs.NixFunInvocation({ 32 | funExpr: new nijs.NixImport(new nijs.NixStorePath("${nijs}/lib/node_modules/nijs/lib/funProxy.nix")), 33 | paramExpr: { 34 | stdenv: new nijs.NixInherit("pkgs"), 35 | lib: new nijs.NixInherit("pkgs"), 36 | nodejs: new nijs.NixInherit("pkgs"), 37 | nijs: new nijs.NixInherit() 38 | } 39 | }), 40 | nijsInlineProxy : new nijs.NixFunInvocation({ 41 | funExpr: new nijs.NixImport(new nijs.NixStorePath("${nijs}/lib/node_modules/nijs/lib/inlineProxy.nix")), 42 | paramExpr: { 43 | stdenv: new nijs.NixInherit("pkgs"), 44 | lib: new nijs.NixInherit("pkgs"), 45 | writeTextFile: new nijs.NixInherit("pkgs"), 46 | nodejs: new nijs.NixInherit("pkgs"), 47 | nijs: new nijs.NixInherit() 48 | } 49 | }) 50 | }, 51 | body : pkgsJsFile.pkgs['${attrName}']() 52 | }); 53 | 54 | fs.writeFileSync(process.env['out'], nijs.jsToNix(expr, ${if format then "true" else "false"})); 55 | ''; 56 | }; 57 | }) 58 | -------------------------------------------------------------------------------- /lib/importPackageAsync.nix: -------------------------------------------------------------------------------- 1 | {nixpkgs, system, nijs}: 2 | {pkgsJsFile, attrName, format ? false}: 3 | 4 | let 5 | pkgs = import nixpkgs { inherit system; }; 6 | 7 | nijsInlineProxy = import ./inlineProxy.nix { 8 | inherit (pkgs) stdenv lib writeTextFile nodejs; 9 | inherit nijs; 10 | }; 11 | 12 | # Create a wrapper package that exposes the slasp library that comes with nijs 13 | slasp = pkgs.stdenv.mkDerivation { 14 | name = "slasp-wrapper"; 15 | buildCommand = '' 16 | mkdir -p $out/lib/node_modules 17 | ln -s ${nijs}/lib/node_modules/nijs/node_modules/slasp $out/lib/node_modules 18 | ''; 19 | }; 20 | in 21 | import (pkgs.stdenv.mkDerivation { 22 | name = "importPackageAsync-${attrName}.nix"; 23 | 24 | buildCommand = nijsInlineProxy { 25 | name = "importPackageAsync-${attrName}-buildCommand"; 26 | modules = [ slasp ]; 27 | requires = [ 28 | { var = "fs"; module = "fs"; } 29 | { var = "slasp"; module = "slasp"; } 30 | { var = "pkgsJsFile"; module = pkgsJsFile; } 31 | ]; 32 | code = '' 33 | slasp.sequence([ 34 | function(callback) { 35 | pkgsJsFile.pkgs['${attrName}'](callback); 36 | }, 37 | 38 | function(callback, _expr) { 39 | var expr = new nijs.NixLet({ 40 | value : { 41 | pkgs : new nijs.NixFunInvocation({ 42 | funExpr: new nijs.NixImport(new nijs.NixStorePath('${nixpkgs}')), 43 | paramExpr: { 44 | system: '${system}' 45 | } 46 | }), 47 | nijs : new nijs.NixStorePath('${nijs}'), 48 | nijsFunProxy: new nijs.NixFunInvocation({ 49 | funExpr: new nijs.NixImport(new nijs.NixStorePath("${nijs}/lib/node_modules/nijs/lib/funProxy.nix")), 50 | paramExpr: { 51 | stdenv: new nijs.NixInherit("pkgs"), 52 | lib: new nijs.NixInherit("pkgs"), 53 | nodejs: new nijs.NixInherit("pkgs"), 54 | nijs: new nijs.NixInherit() 55 | } 56 | }), 57 | nijsInlineProxy : new nijs.NixFunInvocation({ 58 | funExpr: new nijs.NixImport(new nijs.NixStorePath("${nijs}/lib/node_modules/nijs/lib/inlineProxy.nix")), 59 | paramExpr: { 60 | stdenv: new nijs.NixInherit("pkgs"), 61 | lib: new nijs.NixInherit("pkgs"), 62 | writeTextFile: new nijs.NixInherit("pkgs"), 63 | nodejs: new nijs.NixInherit("pkgs"), 64 | nijs: new nijs.NixInherit() 65 | } 66 | }) 67 | }, 68 | body : _expr 69 | }); 70 | 71 | fs.writeFile(process.env['out'], nijs.jsToNix(expr, ${if format then "true" else "false"}), callback); 72 | }, 73 | ], function(err) { 74 | if(err) { 75 | process.stderr.write(err + '\n'); 76 | process.exit(1); 77 | } 78 | }); 79 | ''; 80 | }; 81 | }) 82 | -------------------------------------------------------------------------------- /lib/inlineProxy.nix: -------------------------------------------------------------------------------- 1 | {stdenv, lib, writeTextFile, nodejs, nijs}: 2 | {name ? null, code, modules ? [], requires ? [], NODE_PATH ? "", codeIsFunction ? false}: 3 | 4 | writeTextFile { 5 | name = "inline-proxy${if name == null then "" else "-${name}"}"; 6 | executable = true; 7 | text = '' 8 | ( 9 | buildInputs="${nodejs}" 10 | source ${stdenv}/setup 11 | export NODE_PATH=$NODE_PATH${lib.optionalString (NODE_PATH != "") ''''${NODE_PATH:+:}${NODE_PATH}''} 12 | addNodePath ${nijs} 13 | ${lib.concatMapStrings (module: "addNodePath ${module}\n") modules} 14 | 15 | ( 16 | cat << "__EOF__" 17 | var nijs = require('nijs'); 18 | ${lib.concatMapStrings (require: "var ${require.var} = require('${require.module}');\n") requires} 19 | 20 | ${if codeIsFunction then '' 21 | var fun = ${code}; 22 | fun(); 23 | '' else code} 24 | __EOF__ 25 | ) | ${nodejs}/bin/node) 26 | ''; 27 | } 28 | -------------------------------------------------------------------------------- /lib/nijs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module nijs 3 | */ 4 | 5 | var generate = require('./generate.js'); 6 | var execute = require('./execute'); 7 | var build = require('./build.js'); 8 | 9 | /* Prototypes for abstract syntax objects */ 10 | var NixObject = require('./ast/NixObject.js').NixObject; 11 | var NixValue = require('./ast/NixValue.js').NixValue; 12 | var NixBlock = require('./ast/NixBlock.js').NixBlock; 13 | var NixFile = require('./ast/NixFile.js').NixFile; 14 | var NixURL = require('./ast/NixURL.js').NixURL; 15 | var NixRecursiveAttrSet = require('./ast/NixRecursiveAttrSet.js').NixRecursiveAttrSet; 16 | var NixLet = require('./ast/NixLet.js').NixLet; 17 | var NixExpression = require('./ast/NixExpression.js').NixExpression; 18 | var NixFunction = require('./ast/NixFunction.js').NixFunction; 19 | var NixFunInvocation = require('./ast/NixFunInvocation.js').NixFunInvocation; 20 | var NixAttrReference = require('./ast/NixAttrReference.js').NixAttrReference; 21 | var NixWith = require('./ast/NixWith.js').NixWith; 22 | var NixInherit = require('./ast/NixInherit.js').NixInherit; 23 | var NixInlineJS = require('./ast/NixInlineJS.js').NixInlineJS; 24 | var NixImport = require('./ast/NixImport.js').NixImport; 25 | var NixAssert = require('./ast/NixAssert.js').NixAssert; 26 | var NixIf = require('./ast/NixIf.js').NixIf; 27 | var NixStorePath = require('./ast/NixStorePath.js').NixStorePath; 28 | var NixMergeAttrs = require('./ast/NixMergeAttrs.js').NixMergeAttrs; 29 | var NixASTNode = require('./ast/NixASTNode.js').NixASTNode; 30 | 31 | exports.NixObject = NixObject; 32 | exports.NixValue = NixValue; 33 | exports.NixBlock = NixBlock; 34 | exports.NixFile = NixFile; 35 | exports.NixURL = NixURL; 36 | exports.NixRecursiveAttrSet = NixRecursiveAttrSet; 37 | exports.NixLet = NixLet; 38 | exports.NixExpression = NixExpression; 39 | exports.NixFunction = NixFunction; 40 | exports.NixFunInvocation = NixFunInvocation; 41 | exports.NixAttrReference = NixAttrReference; 42 | exports.NixWith = NixWith; 43 | exports.NixInherit = NixInherit; 44 | exports.NixInlineJS = NixInlineJS; 45 | exports.NixImport = NixImport; 46 | exports.NixStorePath = NixStorePath; 47 | exports.NixAssert = NixAssert; 48 | exports.NixIf = NixIf; 49 | exports.NixMergeAttrs = NixMergeAttrs; 50 | exports.NixASTNode = NixASTNode; 51 | 52 | /* Generate operations */ 53 | exports.generateIndentation = generate.generateIndentation; 54 | exports.objectMembersToAttrsMembers = generate.objectMembersToAttrsMembers; 55 | exports.jsToIndentedNix = generate.jsToIndentedNix; 56 | exports.jsToNix = generate.jsToNix; 57 | 58 | /* Build operations */ 59 | exports.nixBuild = build.nixBuild; 60 | exports.callNixBuild = build.callNixBuild; 61 | 62 | /* Execute operations */ 63 | exports.convertToShellArg = execute.convertToShellArg; 64 | exports.evaluateDerivation = execute.evaluateDerivation; 65 | -------------------------------------------------------------------------------- /lib/nixToJS.nix: -------------------------------------------------------------------------------- 1 | {lib}: 2 | expr: 3 | 4 | let 5 | nixToJS = expr: 6 | let 7 | exprType = builtins.typeOf expr; 8 | in 9 | if exprType == "int" then builtins.toString expr 10 | else if exprType == "bool" then 11 | if expr then "true" else "false" 12 | else if exprType == "string" then "\"${expr}\"" 13 | else if exprType == "path" then "new nijs.NixStorePath(\"${expr}\")" 14 | else if exprType == "null" then "null" 15 | else if exprType == "set" then "{ ${lib.concatMapStrings (elem: "\"${elem}\" : ${nixToJS (builtins.getAttr elem expr)},\n") (builtins.attrNames expr)} }" 16 | else if exprType == "list" then "[ ${lib.concatMapStrings (elem: nixToJS elem + ",\n") expr} ]" 17 | else if exprType == "lambda" then "Cannot convert a lambda to JavaScript" 18 | else "\"${expr}\""; # It's most likely a Nix store path that gets evaluated if none of the other types match. Simply convert this to a string 19 | in 20 | nixToJS expr 21 | -------------------------------------------------------------------------------- /node-env.nix: -------------------------------------------------------------------------------- 1 | # This file originates from node2nix 2 | 3 | {lib, stdenv, nodejs, python2, pkgs, libtool, runCommand, writeTextFile, writeShellScript}: 4 | 5 | let 6 | # Workaround to cope with utillinux in Nixpkgs 20.09 and util-linux in Nixpkgs master 7 | utillinux = if pkgs ? utillinux then pkgs.utillinux else pkgs.util-linux; 8 | 9 | python = if nodejs ? python then nodejs.python else python2; 10 | 11 | # Create a tar wrapper that filters all the 'Ignoring unknown extended header keyword' noise 12 | tarWrapper = runCommand "tarWrapper" {} '' 13 | mkdir -p $out/bin 14 | 15 | cat > $out/bin/tar <> $out/nix-support/hydra-build-products 40 | ''; 41 | }; 42 | 43 | # Common shell logic 44 | installPackage = writeShellScript "install-package" '' 45 | installPackage() { 46 | local packageName=$1 src=$2 47 | 48 | local strippedName 49 | 50 | local DIR=$PWD 51 | cd $TMPDIR 52 | 53 | unpackFile $src 54 | 55 | # Make the base dir in which the target dependency resides first 56 | mkdir -p "$(dirname "$DIR/$packageName")" 57 | 58 | if [ -f "$src" ] 59 | then 60 | # Figure out what directory has been unpacked 61 | packageDir="$(find . -maxdepth 1 -type d | tail -1)" 62 | 63 | # Restore write permissions to make building work 64 | find "$packageDir" -type d -exec chmod u+x {} \; 65 | chmod -R u+w "$packageDir" 66 | 67 | # Move the extracted tarball into the output folder 68 | mv "$packageDir" "$DIR/$packageName" 69 | elif [ -d "$src" ] 70 | then 71 | # Get a stripped name (without hash) of the source directory. 72 | # On old nixpkgs it's already set internally. 73 | if [ -z "$strippedName" ] 74 | then 75 | strippedName="$(stripHash $src)" 76 | fi 77 | 78 | # Restore write permissions to make building work 79 | chmod -R u+w "$strippedName" 80 | 81 | # Move the extracted directory into the output folder 82 | mv "$strippedName" "$DIR/$packageName" 83 | fi 84 | 85 | # Change to the package directory to install dependencies 86 | cd "$DIR/$packageName" 87 | } 88 | ''; 89 | 90 | # Bundle the dependencies of the package 91 | # 92 | # Only include dependencies if they don't exist. They may also be bundled in the package. 93 | includeDependencies = {dependencies}: 94 | lib.optionalString (dependencies != []) ( 95 | '' 96 | mkdir -p node_modules 97 | cd node_modules 98 | '' 99 | + (lib.concatMapStrings (dependency: 100 | '' 101 | if [ ! -e "${dependency.packageName}" ]; then 102 | ${composePackage dependency} 103 | fi 104 | '' 105 | ) dependencies) 106 | + '' 107 | cd .. 108 | '' 109 | ); 110 | 111 | # Recursively composes the dependencies of a package 112 | composePackage = { name, packageName, src, dependencies ? [], ... }@args: 113 | builtins.addErrorContext "while evaluating node package '${packageName}'" '' 114 | installPackage "${packageName}" "${src}" 115 | ${includeDependencies { inherit dependencies; }} 116 | cd .. 117 | ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} 118 | ''; 119 | 120 | pinpointDependencies = {dependencies, production}: 121 | let 122 | pinpointDependenciesFromPackageJSON = writeTextFile { 123 | name = "pinpointDependencies.js"; 124 | text = '' 125 | var fs = require('fs'); 126 | var path = require('path'); 127 | 128 | function resolveDependencyVersion(location, name) { 129 | if(location == process.env['NIX_STORE']) { 130 | return null; 131 | } else { 132 | var dependencyPackageJSON = path.join(location, "node_modules", name, "package.json"); 133 | 134 | if(fs.existsSync(dependencyPackageJSON)) { 135 | var dependencyPackageObj = JSON.parse(fs.readFileSync(dependencyPackageJSON)); 136 | 137 | if(dependencyPackageObj.name == name) { 138 | return dependencyPackageObj.version; 139 | } 140 | } else { 141 | return resolveDependencyVersion(path.resolve(location, ".."), name); 142 | } 143 | } 144 | } 145 | 146 | function replaceDependencies(dependencies) { 147 | if(typeof dependencies == "object" && dependencies !== null) { 148 | for(var dependency in dependencies) { 149 | var resolvedVersion = resolveDependencyVersion(process.cwd(), dependency); 150 | 151 | if(resolvedVersion === null) { 152 | process.stderr.write("WARNING: cannot pinpoint dependency: "+dependency+", context: "+process.cwd()+"\n"); 153 | } else { 154 | dependencies[dependency] = resolvedVersion; 155 | } 156 | } 157 | } 158 | } 159 | 160 | /* Read the package.json configuration */ 161 | var packageObj = JSON.parse(fs.readFileSync('./package.json')); 162 | 163 | /* Pinpoint all dependencies */ 164 | replaceDependencies(packageObj.dependencies); 165 | if(process.argv[2] == "development") { 166 | replaceDependencies(packageObj.devDependencies); 167 | } 168 | replaceDependencies(packageObj.optionalDependencies); 169 | 170 | /* Write the fixed package.json file */ 171 | fs.writeFileSync("package.json", JSON.stringify(packageObj, null, 2)); 172 | ''; 173 | }; 174 | in 175 | '' 176 | node ${pinpointDependenciesFromPackageJSON} ${if production then "production" else "development"} 177 | 178 | ${lib.optionalString (dependencies != []) 179 | '' 180 | if [ -d node_modules ] 181 | then 182 | cd node_modules 183 | ${lib.concatMapStrings (dependency: pinpointDependenciesOfPackage dependency) dependencies} 184 | cd .. 185 | fi 186 | ''} 187 | ''; 188 | 189 | # Recursively traverses all dependencies of a package and pinpoints all 190 | # dependencies in the package.json file to the versions that are actually 191 | # being used. 192 | 193 | pinpointDependenciesOfPackage = { packageName, dependencies ? [], production ? true, ... }@args: 194 | '' 195 | if [ -d "${packageName}" ] 196 | then 197 | cd "${packageName}" 198 | ${pinpointDependencies { inherit dependencies production; }} 199 | cd .. 200 | ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} 201 | fi 202 | ''; 203 | 204 | # Extract the Node.js source code which is used to compile packages with 205 | # native bindings 206 | nodeSources = runCommand "node-sources" {} '' 207 | tar --no-same-owner --no-same-permissions -xf ${nodejs.src} 208 | mv node-* $out 209 | ''; 210 | 211 | # Script that adds _integrity fields to all package.json files to prevent NPM from consulting the cache (that is empty) 212 | addIntegrityFieldsScript = writeTextFile { 213 | name = "addintegrityfields.js"; 214 | text = '' 215 | var fs = require('fs'); 216 | var path = require('path'); 217 | 218 | function augmentDependencies(baseDir, dependencies) { 219 | for(var dependencyName in dependencies) { 220 | var dependency = dependencies[dependencyName]; 221 | 222 | // Open package.json and augment metadata fields 223 | var packageJSONDir = path.join(baseDir, "node_modules", dependencyName); 224 | var packageJSONPath = path.join(packageJSONDir, "package.json"); 225 | 226 | if(fs.existsSync(packageJSONPath)) { // Only augment packages that exist. Sometimes we may have production installs in which development dependencies can be ignored 227 | console.log("Adding metadata fields to: "+packageJSONPath); 228 | var packageObj = JSON.parse(fs.readFileSync(packageJSONPath)); 229 | 230 | if(dependency.integrity) { 231 | packageObj["_integrity"] = dependency.integrity; 232 | } else { 233 | packageObj["_integrity"] = "sha1-000000000000000000000000000="; // When no _integrity string has been provided (e.g. by Git dependencies), add a dummy one. It does not seem to harm and it bypasses downloads. 234 | } 235 | 236 | if(dependency.resolved) { 237 | packageObj["_resolved"] = dependency.resolved; // Adopt the resolved property if one has been provided 238 | } else { 239 | packageObj["_resolved"] = dependency.version; // Set the resolved version to the version identifier. This prevents NPM from cloning Git repositories. 240 | } 241 | 242 | if(dependency.from !== undefined) { // Adopt from property if one has been provided 243 | packageObj["_from"] = dependency.from; 244 | } 245 | 246 | fs.writeFileSync(packageJSONPath, JSON.stringify(packageObj, null, 2)); 247 | } 248 | 249 | // Augment transitive dependencies 250 | if(dependency.dependencies !== undefined) { 251 | augmentDependencies(packageJSONDir, dependency.dependencies); 252 | } 253 | } 254 | } 255 | 256 | if(fs.existsSync("./package-lock.json")) { 257 | var packageLock = JSON.parse(fs.readFileSync("./package-lock.json")); 258 | 259 | if(![1, 2].includes(packageLock.lockfileVersion)) { 260 | process.stderr.write("Sorry, I only understand lock file versions 1 and 2!\n"); 261 | process.exit(1); 262 | } 263 | 264 | if(packageLock.dependencies !== undefined) { 265 | augmentDependencies(".", packageLock.dependencies); 266 | } 267 | } 268 | ''; 269 | }; 270 | 271 | # Reconstructs a package-lock file from the node_modules/ folder structure and package.json files with dummy sha1 hashes 272 | reconstructPackageLock = writeTextFile { 273 | name = "addintegrityfields.js"; 274 | text = '' 275 | var fs = require('fs'); 276 | var path = require('path'); 277 | 278 | var packageObj = JSON.parse(fs.readFileSync("package.json")); 279 | 280 | var lockObj = { 281 | name: packageObj.name, 282 | version: packageObj.version, 283 | lockfileVersion: 1, 284 | requires: true, 285 | dependencies: {} 286 | }; 287 | 288 | function augmentPackageJSON(filePath, dependencies) { 289 | var packageJSON = path.join(filePath, "package.json"); 290 | if(fs.existsSync(packageJSON)) { 291 | var packageObj = JSON.parse(fs.readFileSync(packageJSON)); 292 | dependencies[packageObj.name] = { 293 | version: packageObj.version, 294 | integrity: "sha1-000000000000000000000000000=", 295 | dependencies: {} 296 | }; 297 | processDependencies(path.join(filePath, "node_modules"), dependencies[packageObj.name].dependencies); 298 | } 299 | } 300 | 301 | function processDependencies(dir, dependencies) { 302 | if(fs.existsSync(dir)) { 303 | var files = fs.readdirSync(dir); 304 | 305 | files.forEach(function(entry) { 306 | var filePath = path.join(dir, entry); 307 | var stats = fs.statSync(filePath); 308 | 309 | if(stats.isDirectory()) { 310 | if(entry.substr(0, 1) == "@") { 311 | // When we encounter a namespace folder, augment all packages belonging to the scope 312 | var pkgFiles = fs.readdirSync(filePath); 313 | 314 | pkgFiles.forEach(function(entry) { 315 | if(stats.isDirectory()) { 316 | var pkgFilePath = path.join(filePath, entry); 317 | augmentPackageJSON(pkgFilePath, dependencies); 318 | } 319 | }); 320 | } else { 321 | augmentPackageJSON(filePath, dependencies); 322 | } 323 | } 324 | }); 325 | } 326 | } 327 | 328 | processDependencies("node_modules", lockObj.dependencies); 329 | 330 | fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2)); 331 | ''; 332 | }; 333 | 334 | prepareAndInvokeNPM = {packageName, bypassCache, reconstructLock, npmFlags, production}: 335 | let 336 | forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com"; 337 | in 338 | '' 339 | # Pinpoint the versions of all dependencies to the ones that are actually being used 340 | echo "pinpointing versions of dependencies..." 341 | source $pinpointDependenciesScriptPath 342 | 343 | # Patch the shebangs of the bundled modules to prevent them from 344 | # calling executables outside the Nix store as much as possible 345 | patchShebangs . 346 | 347 | # Deploy the Node.js package by running npm install. Since the 348 | # dependencies have been provided already by ourselves, it should not 349 | # attempt to install them again, which is good, because we want to make 350 | # it Nix's responsibility. If it needs to install any dependencies 351 | # anyway (e.g. because the dependency parameters are 352 | # incomplete/incorrect), it fails. 353 | # 354 | # The other responsibilities of NPM are kept -- version checks, build 355 | # steps, postprocessing etc. 356 | 357 | export HOME=$TMPDIR 358 | cd "${packageName}" 359 | runHook preRebuild 360 | 361 | ${lib.optionalString bypassCache '' 362 | ${lib.optionalString reconstructLock '' 363 | if [ -f package-lock.json ] 364 | then 365 | echo "WARNING: Reconstruct lock option enabled, but a lock file already exists!" 366 | echo "This will most likely result in version mismatches! We will remove the lock file and regenerate it!" 367 | rm package-lock.json 368 | else 369 | echo "No package-lock.json file found, reconstructing..." 370 | fi 371 | 372 | node ${reconstructPackageLock} 373 | ''} 374 | 375 | node ${addIntegrityFieldsScript} 376 | ''} 377 | 378 | npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} rebuild 379 | 380 | if [ "''${dontNpmInstall-}" != "1" ] 381 | then 382 | # NPM tries to download packages even when they already exist if npm-shrinkwrap is used. 383 | rm -f npm-shrinkwrap.json 384 | 385 | npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} install 386 | fi 387 | ''; 388 | 389 | # Builds and composes an NPM package including all its dependencies 390 | buildNodePackage = 391 | { name 392 | , packageName 393 | , version ? null 394 | , dependencies ? [] 395 | , buildInputs ? [] 396 | , production ? true 397 | , npmFlags ? "" 398 | , dontNpmInstall ? false 399 | , bypassCache ? false 400 | , reconstructLock ? false 401 | , preRebuild ? "" 402 | , dontStrip ? true 403 | , unpackPhase ? "true" 404 | , buildPhase ? "true" 405 | , meta ? {} 406 | , ... }@args: 407 | 408 | let 409 | extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "preRebuild" "unpackPhase" "buildPhase" "meta" ]; 410 | in 411 | stdenv.mkDerivation ({ 412 | name = "${name}${if version == null then "" else "-${version}"}"; 413 | buildInputs = [ tarWrapper python nodejs ] 414 | ++ lib.optional (stdenv.isLinux) utillinux 415 | ++ lib.optional (stdenv.isDarwin) libtool 416 | ++ buildInputs; 417 | 418 | inherit nodejs; 419 | 420 | inherit dontStrip; # Stripping may fail a build for some package deployments 421 | inherit dontNpmInstall preRebuild unpackPhase buildPhase; 422 | 423 | compositionScript = composePackage args; 424 | pinpointDependenciesScript = pinpointDependenciesOfPackage args; 425 | 426 | passAsFile = [ "compositionScript" "pinpointDependenciesScript" ]; 427 | 428 | installPhase = '' 429 | source ${installPackage} 430 | 431 | # Create and enter a root node_modules/ folder 432 | mkdir -p $out/lib/node_modules 433 | cd $out/lib/node_modules 434 | 435 | # Compose the package and all its dependencies 436 | source $compositionScriptPath 437 | 438 | ${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }} 439 | 440 | # Create symlink to the deployed executable folder, if applicable 441 | if [ -d "$out/lib/node_modules/.bin" ] 442 | then 443 | ln -s $out/lib/node_modules/.bin $out/bin 444 | 445 | # Patch the shebang lines of all the executables 446 | ls $out/bin/* | while read i 447 | do 448 | file="$(readlink -f "$i")" 449 | chmod u+rwx "$file" 450 | patchShebangs "$file" 451 | done 452 | fi 453 | 454 | # Create symlinks to the deployed manual page folders, if applicable 455 | if [ -d "$out/lib/node_modules/${packageName}/man" ] 456 | then 457 | mkdir -p $out/share 458 | for dir in "$out/lib/node_modules/${packageName}/man/"* 459 | do 460 | mkdir -p $out/share/man/$(basename "$dir") 461 | for page in "$dir"/* 462 | do 463 | ln -s $page $out/share/man/$(basename "$dir") 464 | done 465 | done 466 | fi 467 | 468 | # Run post install hook, if provided 469 | runHook postInstall 470 | ''; 471 | 472 | meta = { 473 | # default to Node.js' platforms 474 | platforms = nodejs.meta.platforms; 475 | } // meta; 476 | } // extraArgs); 477 | 478 | # Builds a node environment (a node_modules folder and a set of binaries) 479 | buildNodeDependencies = 480 | { name 481 | , packageName 482 | , version ? null 483 | , src 484 | , dependencies ? [] 485 | , buildInputs ? [] 486 | , production ? true 487 | , npmFlags ? "" 488 | , dontNpmInstall ? false 489 | , bypassCache ? false 490 | , reconstructLock ? false 491 | , dontStrip ? true 492 | , unpackPhase ? "true" 493 | , buildPhase ? "true" 494 | , ... }@args: 495 | 496 | let 497 | extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" ]; 498 | in 499 | stdenv.mkDerivation ({ 500 | name = "node-dependencies-${name}${if version == null then "" else "-${version}"}"; 501 | 502 | buildInputs = [ tarWrapper python nodejs ] 503 | ++ lib.optional (stdenv.isLinux) utillinux 504 | ++ lib.optional (stdenv.isDarwin) libtool 505 | ++ buildInputs; 506 | 507 | inherit dontStrip; # Stripping may fail a build for some package deployments 508 | inherit dontNpmInstall unpackPhase buildPhase; 509 | 510 | includeScript = includeDependencies { inherit dependencies; }; 511 | pinpointDependenciesScript = pinpointDependenciesOfPackage args; 512 | 513 | passAsFile = [ "includeScript" "pinpointDependenciesScript" ]; 514 | 515 | installPhase = '' 516 | source ${installPackage} 517 | 518 | mkdir -p $out/${packageName} 519 | cd $out/${packageName} 520 | 521 | source $includeScriptPath 522 | 523 | # Create fake package.json to make the npm commands work properly 524 | cp ${src}/package.json . 525 | chmod 644 package.json 526 | ${lib.optionalString bypassCache '' 527 | if [ -f ${src}/package-lock.json ] 528 | then 529 | cp ${src}/package-lock.json . 530 | chmod 644 package-lock.json 531 | fi 532 | ''} 533 | 534 | # Go to the parent folder to make sure that all packages are pinpointed 535 | cd .. 536 | ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} 537 | 538 | ${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }} 539 | 540 | # Expose the executables that were installed 541 | cd .. 542 | ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} 543 | 544 | mv ${packageName} lib 545 | ln -s $out/lib/node_modules/.bin $out/bin 546 | ''; 547 | } // extraArgs); 548 | 549 | # Builds a development shell 550 | buildNodeShell = 551 | { name 552 | , packageName 553 | , version ? null 554 | , src 555 | , dependencies ? [] 556 | , buildInputs ? [] 557 | , production ? true 558 | , npmFlags ? "" 559 | , dontNpmInstall ? false 560 | , bypassCache ? false 561 | , reconstructLock ? false 562 | , dontStrip ? true 563 | , unpackPhase ? "true" 564 | , buildPhase ? "true" 565 | , ... }@args: 566 | 567 | let 568 | nodeDependencies = buildNodeDependencies args; 569 | extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "unpackPhase" "buildPhase" ]; 570 | in 571 | stdenv.mkDerivation ({ 572 | name = "node-shell-${name}${if version == null then "" else "-${version}"}"; 573 | 574 | buildInputs = [ python nodejs ] ++ lib.optional (stdenv.isLinux) utillinux ++ buildInputs; 575 | buildCommand = '' 576 | mkdir -p $out/bin 577 | cat > $out/bin/shell <", 10 | "license": "MIT", 11 | "bin": { 12 | "nijs-build": "./bin/nijs-build.js", 13 | "nijs-execute": "./bin/nijs-execute.js" 14 | }, 15 | "main": "./lib/nijs", 16 | "dependencies": { 17 | "optparse": ">= 1.0.3", 18 | "slasp": "0.0.4" 19 | }, 20 | "devDependencies": { 21 | "jsdoc": "*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /release.nix: -------------------------------------------------------------------------------- 1 | { nixpkgs ? 2 | , systems ? [ "i686-linux" "x86_64-linux" "x86_64-darwin" ] 3 | , officialRelease ? false 4 | }: 5 | 6 | let 7 | pkgs = import nixpkgs {}; 8 | 9 | version = (builtins.fromJSON (builtins.readFile ./package.json)).version; 10 | 11 | jobset = import ./default.nix { 12 | inherit pkgs; 13 | system = builtins.currentSystem; 14 | }; 15 | 16 | jobs = rec { 17 | inherit (jobset) tarball; 18 | 19 | package = pkgs.lib.genAttrs systems (system: 20 | (import ./default.nix { 21 | pkgs = import nixpkgs { inherit system; }; 22 | inherit system; 23 | }).package.override { 24 | postInstall = '' 25 | mkdir -p $out/share/doc/nijs 26 | $out/lib/node_modules/nijs/node_modules/jsdoc/jsdoc.js -R README.md -r lib -d $out/share/doc/nijs/apidox 27 | mkdir -p $out/nix-support 28 | echo "doc api $out/share/doc/nijs/apidox" >> $out/nix-support/hydra-build-products 29 | ''; 30 | } 31 | ); 32 | 33 | tests = { 34 | proxytests = import ./tests/proxytests.nix { 35 | inherit pkgs; 36 | nijs = builtins.getAttr (builtins.currentSystem) (jobs.package); 37 | }; 38 | 39 | pkgs = 40 | let 41 | pkgsJsFile = "${./.}/tests/pkgs.js"; 42 | 43 | nijsImportPackage = import ./lib/importPackage.nix { 44 | inherit nixpkgs; 45 | system = builtins.currentSystem; 46 | nijs = builtins.getAttr (builtins.currentSystem) (jobs.package); 47 | }; 48 | in 49 | { 50 | hello = nijsImportPackage { inherit pkgsJsFile; attrName = "hello"; }; 51 | zlib = nijsImportPackage { inherit pkgsJsFile; attrName = "zlib"; }; 52 | file = nijsImportPackage { inherit pkgsJsFile; attrName = "file"; }; 53 | perl = nijsImportPackage { inherit pkgsJsFile; attrName = "perl"; }; 54 | openssl = nijsImportPackage { inherit pkgsJsFile; attrName = "openssl"; }; 55 | curl = nijsImportPackage { inherit pkgsJsFile; attrName = "curl"; }; 56 | wget = nijsImportPackage { inherit pkgsJsFile; attrName = "wget"; }; 57 | sumTest = nijsImportPackage { inherit pkgsJsFile; attrName = "sumTest"; }; 58 | stringWriteTest = nijsImportPackage { inherit pkgsJsFile; attrName = "stringWriteTest"; }; 59 | appendFilesTest = nijsImportPackage { inherit pkgsJsFile; attrName = "appendFilesTest"; }; 60 | createFileWithMessageTest = nijsImportPackage { inherit pkgsJsFile; attrName = "createFileWithMessageTest"; }; 61 | sayHello = nijsImportPackage { inherit pkgsJsFile; attrName = "sayHello"; }; 62 | addressPerson = nijsImportPackage { inherit pkgsJsFile; attrName = "addressPerson"; }; 63 | addressPersons = nijsImportPackage { inherit pkgsJsFile; attrName = "addressPersons"; }; 64 | addressPersonInformally = nijsImportPackage { inherit pkgsJsFile; attrName = "addressPersonInformally"; }; 65 | numbers = nijsImportPackage { inherit pkgsJsFile; attrName = "numbers"; }; 66 | sayHello2 = nijsImportPackage { inherit pkgsJsFile; attrName = "sayHello2"; }; 67 | objToXML = nijsImportPackage { inherit pkgsJsFile; attrName = "objToXML"; }; 68 | conditionals = nijsImportPackage { inherit pkgsJsFile; attrName = "conditionals"; }; 69 | bzip2 = nijsImportPackage { inherit pkgsJsFile; attrName = "bzip2"; }; 70 | utillinux = nijsImportPackage { inherit pkgsJsFile; attrName = "utillinux"; }; 71 | python = nijsImportPackage { inherit pkgsJsFile; attrName = "python"; }; 72 | nodejs = nijsImportPackage { inherit pkgsJsFile; attrName = "nodejs"; }; 73 | optparse = nijsImportPackage { inherit pkgsJsFile; attrName = "optparse"; }; 74 | slasp = nijsImportPackage { inherit pkgsJsFile; attrName = "slasp"; }; 75 | nijs = nijsImportPackage { inherit pkgsJsFile; attrName = "nijs"; }; 76 | underscoreTest = nijsImportPackage { inherit pkgsJsFile; attrName = "underscoreTest"; }; 77 | HelloModel = nijsImportPackage { inherit pkgsJsFile; attrName = "HelloModel"; }; 78 | }; 79 | 80 | pkgsAsync = 81 | let 82 | pkgsJsFile = "${./.}/tests/pkgs-async.js"; 83 | 84 | nijsImportPackageAsync = import ./lib/importPackageAsync.nix { 85 | inherit nixpkgs; 86 | system = builtins.currentSystem; 87 | nijs = builtins.getAttr (builtins.currentSystem) (jobs.package); 88 | }; 89 | in 90 | { 91 | test = nijsImportPackageAsync { inherit pkgsJsFile; attrName = "test"; }; 92 | hello = nijsImportPackageAsync { inherit pkgsJsFile; attrName = "hello"; }; 93 | zlib = nijsImportPackageAsync { inherit pkgsJsFile; attrName = "zlib"; }; 94 | file = nijsImportPackageAsync { inherit pkgsJsFile; attrName = "file"; }; 95 | createFileWithMessageTest = nijsImportPackageAsync { inherit pkgsJsFile; attrName = "createFileWithMessageTest"; }; 96 | }; 97 | 98 | execute = import ./tests/execute.nix { 99 | nijs = builtins.getAttr (builtins.currentSystem) package; 100 | inherit nixpkgs pkgs tarball; 101 | }; 102 | }; 103 | 104 | release = pkgs.releaseTools.aggregate { 105 | name = "nijs-${version}"; 106 | constituents = [ 107 | tarball 108 | ] 109 | ++ map (system: builtins.getAttr system package) systems 110 | ++ map (name: builtins.getAttr name tests.proxytests) (builtins.attrNames tests.proxytests) 111 | ++ map (name: builtins.getAttr name tests.pkgs) (builtins.attrNames tests.pkgs) 112 | ++ map (name: builtins.getAttr name tests.pkgsAsync) (builtins.attrNames tests.pkgsAsync) 113 | ++ [ tests.execute ]; 114 | 115 | meta.description = "Release-critical builds"; 116 | }; 117 | }; 118 | in 119 | jobs 120 | -------------------------------------------------------------------------------- /tests/custom-npm-pkgs/default.nix: -------------------------------------------------------------------------------- 1 | # This file has been generated by node2nix 1.11.1. Do not edit! 2 | 3 | {pkgs ? import { 4 | inherit system; 5 | }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-12_x"}: 6 | 7 | let 8 | nodeEnv = import ./node-env.nix { 9 | inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript; 10 | inherit pkgs nodejs; 11 | libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null; 12 | }; 13 | in 14 | import ./node-packages.nix { 15 | inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit; 16 | inherit nodeEnv; 17 | } 18 | -------------------------------------------------------------------------------- /tests/custom-npm-pkgs/node-packages.json: -------------------------------------------------------------------------------- 1 | [ 2 | "underscore" 3 | ] 4 | -------------------------------------------------------------------------------- /tests/custom-npm-pkgs/node-packages.nix: -------------------------------------------------------------------------------- 1 | # This file has been generated by node2nix 1.11.1. Do not edit! 2 | 3 | {nodeEnv, fetchurl, fetchgit, nix-gitignore, stdenv, lib, globalBuildInputs ? []}: 4 | 5 | let 6 | sources = {}; 7 | in 8 | { 9 | underscore = nodeEnv.buildNodePackage { 10 | name = "underscore"; 11 | packageName = "underscore"; 12 | version = "1.13.2"; 13 | src = fetchurl { 14 | url = "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz"; 15 | sha512 = "ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g=="; 16 | }; 17 | buildInputs = globalBuildInputs; 18 | meta = { 19 | description = "JavaScript's functional programming helper library."; 20 | homepage = "https://underscorejs.org"; 21 | license = "MIT"; 22 | }; 23 | production = true; 24 | bypassCache = true; 25 | reconstructLock = true; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /tests/execute.nix: -------------------------------------------------------------------------------- 1 | {nixpkgs, pkgs, tarball, nijs}: 2 | 3 | let 4 | documentRoot = pkgs.stdenv.mkDerivation { 5 | name = "documentroot"; 6 | 7 | srcHello = pkgs.fetchurl { 8 | url = mirror://gnu/hello/hello-2.12.tar.gz; 9 | sha256 = "1ayhp9v4m4rdhjmnl2bq3cibrbqqkgjbl3s7yk2nhlh8vj3ay16g"; 10 | }; 11 | 12 | srcZlib = pkgs.fetchurl { 13 | url = https://www.zlib.net/fossils/zlib-1.2.12.tar.gz; 14 | sha256 = "1n9na4fq4wagw1nzsfjr6wyly960jfa94460ncbf6p1fac44i14i"; 15 | }; 16 | 17 | srcFile = pkgs.fetchurl { 18 | url = ftp://ftp.astron.com/pub/file/file-5.41.tar.gz; 19 | sha256 = "0gv027jgdr0hdkw7m9ck0nwhq583f4aa7vnz4dzdbxv4ng3k5r8k"; 20 | }; 21 | 22 | buildCommand = '' 23 | mkdir -p $out/hello 24 | cp $srcHello $out/hello/hello-2.12.tar.gz 25 | mkdir -p $out/fossils 26 | cp $srcZlib $out/fossils/zlib-1.2.12.tar.gz 27 | mkdir -p $out/pub/file 28 | cp $srcFile $out/pub/file/file-5.41.tar.gz 29 | ''; 30 | }; 31 | in 32 | with import "${nixpkgs}/nixos/lib/testing-python.nix" { system = builtins.currentSystem; }; 33 | 34 | simpleTest { 35 | nodes = { 36 | machine = {pkgs, ...}: 37 | 38 | { 39 | networking.extraHosts = '' 40 | 127.0.0.2 ftpmirror.gnu.org www.zlib.net ftp.astron.com 41 | ''; 42 | 43 | services.httpd.enable = true; 44 | services.httpd.adminAddr = "admin@localhost"; 45 | services.httpd.virtualHosts.localhost.documentRoot = documentRoot; 46 | 47 | services.vsftpd.enable = true; 48 | services.vsftpd.anonymousUser = true; 49 | services.vsftpd.anonymousUserHome = "/home/ftp/"; 50 | 51 | environment.systemPackages = [ nijs pkgs.stdenv pkgs.gcc pkgs.gnumake pkgs.binutils ]; 52 | }; 53 | }; 54 | testScript = 55 | '' 56 | start_all() 57 | 58 | # Unpack the tarball to retrieve the testcases 59 | machine.succeed("tar xfvz ${tarball}/tarballs/*.tgz") 60 | 61 | # Build the 'test' package and check whether the output contains 62 | # 'Hello world' 63 | result = machine.succeed("cd package/tests && nijs-execute pkgs-async.js -A test") 64 | machine.succeed("[ \"\$(cat {} | grep 'Hello world')\" != \"\" ]".format(result[:-1])) 65 | 66 | # Build GNU Hello and see whether we can run it 67 | machine.wait_for_unit("httpd") 68 | result = machine.succeed("cd package/tests && nijs-execute pkgs-async.js -A hello >&2") 69 | machine.succeed("$HOME/.nijs/store/hello-*/bin/hello") 70 | 71 | # Build file and its dependencies (zlib) and see whether we can 72 | # run it 73 | machine.succeed("cp -r ${documentRoot}/pub /home/ftp") 74 | machine.wait_for_unit("vsftpd") 75 | machine.succeed("cd package/tests && nijs-execute pkgs-async.js -A file >&2") 76 | machine.succeed("$HOME/.nijs/store/file-*/bin/file --version") 77 | 78 | # Two of file's shared libraries (libmagic and libz) should refer to the NiJS store 79 | machine.succeed('[ "$(ldd $HOME/.nijs/store/file-*/bin/file | grep -c $HOME/.nijs/store)" = "2" ]') 80 | ''; 81 | } 82 | -------------------------------------------------------------------------------- /tests/pkgs-async.js: -------------------------------------------------------------------------------- 1 | var pkgs = { 2 | 3 | stdenv : function(callback) { 4 | return require('./pkgs-async/stdenv.js').pkg; 5 | }, 6 | 7 | test : function(callback) { 8 | return require('./pkgs-async/test.js').pkg({ 9 | stdenv : pkgs.stdenv 10 | }, callback); 11 | }, 12 | 13 | fetchurl : function(callback) { 14 | return require('./pkgs-async/fetchurl').pkg({ 15 | stdenv : pkgs.stdenv 16 | }, callback); 17 | }, 18 | 19 | hello : function(callback) { 20 | return require('./pkgs-async/hello.js').pkg({ 21 | stdenv : pkgs.stdenv, 22 | fetchurl : pkgs.fetchurl 23 | }, callback); 24 | }, 25 | 26 | zlib : function(callback) { 27 | return require('./pkgs-async/zlib.js').pkg({ 28 | stdenv : pkgs.stdenv, 29 | fetchurl : pkgs.fetchurl 30 | }, callback); 31 | }, 32 | 33 | file : function(callback) { 34 | return require('./pkgs-async/file.js').pkg({ 35 | stdenv : pkgs.stdenv, 36 | fetchurl : pkgs.fetchurl, 37 | zlib : pkgs.zlib 38 | }, callback); 39 | }, 40 | 41 | createFileWithMessageTest : function(callback) { 42 | return require('./pkgs-async/createFileWithMessageTest.js').pkg({ 43 | stdenv : pkgs.stdenv 44 | }, callback); 45 | } 46 | }; 47 | 48 | exports.pkgs = pkgs; 49 | -------------------------------------------------------------------------------- /tests/pkgs-async/createFileWithMessageTest.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args, callback) { 4 | args.stdenv().mkDerivation ({ 5 | name : "createFileWithMessageTest", 6 | buildCommand : new nijs.NixInlineJS({ 7 | requires : [ 8 | { "var" : "fs", "module" : "fs" }, 9 | { "var" : "path", "module" : "path" } 10 | ], 11 | code : function() { 12 | fs.mkdirSync(process.env['out']); 13 | var message = "Hello world written through inline JavaScript!"; 14 | fs.writeFileSync(path.join(process.env['out'], "message.txt"), message); 15 | } 16 | }) 17 | }, callback); 18 | }; 19 | -------------------------------------------------------------------------------- /tests/pkgs-async/fetchurl/builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | if [ "$(type -P curl)" = "" ] # Dirty way to lookup curl, but the derivation has a fixed output, so it's fine 4 | then 5 | curl="/run/current-system/sw/bin/curl" 6 | else 7 | curl="$(type -P curl)" 8 | fi 9 | 10 | for url in $mirrors 11 | do 12 | if $curl --location --max-redirs 20 --retry 3 --disable-epsv --cookie-jar cookies --insecure --fail "$url" --output "$out" 13 | then 14 | success=1 15 | break 16 | fi 17 | done 18 | 19 | if [ "$success" != "1" ] 20 | then 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /tests/pkgs-async/fetchurl/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | var nijs = require('nijs'); 4 | 5 | exports.pkg = function(args) { 6 | return function(funArgs, callback) { 7 | 8 | /* Determine the component's name */ 9 | var urlString; 10 | 11 | if(typeof funArgs.url == "string") 12 | urlString = funArgs.url; 13 | else if(funArgs.url instanceof nijs.NixURL) 14 | urlString = funArgs.url.value; 15 | else 16 | callback("The specified url is in an unknown format!"); 17 | 18 | var name; 19 | 20 | if(funArgs.name === undefined) 21 | name = path.basename(urlString); 22 | else 23 | name = funArgs.name; 24 | 25 | /* Check whether the right output hash is specified */ 26 | 27 | var outputHashAlgo; 28 | var outputHash; 29 | 30 | if(funArgs.md5 !== undefined && funArgs.md5 != "") { 31 | outputHashAlgo = "md5"; 32 | outputHash = funArgs.md5; 33 | } else if(funArgs.sha1 !== undefined && funArgs.sha1 != "") { 34 | outputHashAlgo = "sha1"; 35 | outputHash = funArgs.sha1; 36 | } else if(funArgs.sha256 !== undefined || funArgs.sha256 != "") { 37 | outputHashAlgo = "sha256"; 38 | outputHash = funArgs.sha256; 39 | } else { 40 | callback("No output hash specified! Specify either 'md5', 'sha1', or 'sha256'!"); 41 | } 42 | 43 | /* Pick the right list of mirrors, in case a mirror:// url has been specified */ 44 | 45 | if(urlString.substring(0, "mirror://".length) == "mirror://") { 46 | 47 | /* Open mirrors config file */ 48 | var mirrorsConfigFile = path.join(path.dirname(module.filename), "mirrors.json"); 49 | var mirrorsConfig = JSON.parse(fs.readFileSync(mirrorsConfigFile)); 50 | 51 | /* Determine the mirror identifier */ 52 | var urlPath = urlString.substring("mirror://".length - 1); 53 | var mirrorComponent = urlPath.match(/\/[a-zA-Z0-9_]+\//); 54 | var mirror = mirrorComponent.toString().substring(1, mirrorComponent.toString().length - 1); 55 | 56 | /* Determine the relative path to the file */ 57 | var filePath = urlPath.substring(mirrorComponent.toString().length); 58 | 59 | /* Append the file to each mirror */ 60 | 61 | mirrors = mirrorsConfig[mirror]; 62 | 63 | for(var i = 0; i < mirrors.length; i++) { 64 | mirrors[i] = mirrors[i] + filePath; 65 | } 66 | 67 | } else { 68 | mirrors = [ funArgs.url ]; 69 | } 70 | 71 | /* Create the derivation that specifies the build action */ 72 | 73 | args.stdenv().mkDerivation({ 74 | name : name, 75 | 76 | mirrors : mirrors, 77 | 78 | builder : new nijs.NixFile({ 79 | value : "./builder.sh", 80 | module : module 81 | }), 82 | 83 | outputHashAlgo : outputHashAlgo, 84 | outputHash : outputHash, 85 | 86 | PATH : process.env['PATH'], 87 | 88 | /* 89 | * We borrow these environment variables from the caller to allow easy proxy 90 | * configuration. This is impure, but a fixed-output derivation like fetchurl 91 | * is allowed to do so since its result is by definition pure. 92 | */ 93 | impureEnvVars : [ "http_proxy", "https_proxy", "ftp_proxy", "all_proxy", "no_proxy" ], 94 | 95 | /* 96 | * Doing the download on a remote machine just duplicates network 97 | * traffic, so don't do that */ 98 | preferLocalBuild : true, 99 | 100 | /* We use the host system's curl, which does not work in a chroot */ 101 | __noChroot : true 102 | }, callback); 103 | }; 104 | }; 105 | -------------------------------------------------------------------------------- /tests/pkgs-async/fetchurl/mirrors.json: -------------------------------------------------------------------------------- 1 | { 2 | "gnu" : [ 3 | "http://ftpmirror.gnu.org/", 4 | "http://ftp.nluug.nl/pub/gnu/", 5 | "http://mirrors.kernel.org/gnu/", 6 | "ftp://mirror.cict.fr/gnu/", 7 | "ftp://ftp.cs.tu-berlin.de/pub/gnu/", 8 | "ftp://ftp.chg.ru/pub/gnu/", 9 | "ftp://ftp.funet.fi/pub/mirrors/ftp.gnu.org/gnu/", 10 | "http://ftp.gnu.org/pub/gnu/" 11 | ], 12 | 13 | "sourceforge" : [ 14 | "http://prdownloads.sourceforge.net/", 15 | "http://heanet.dl.sourceforge.net/sourceforge/", 16 | "http://surfnet.dl.sourceforge.net/sourceforge/", 17 | "http://dfn.dl.sourceforge.net/sourceforge/", 18 | "http://mesh.dl.sourceforge.net/sourceforge/", 19 | "http://ovh.dl.sourceforge.net/sourceforge/", 20 | "http://osdn.dl.sourceforge.net/sourceforge/", 21 | "http://kent.dl.sourceforge.net/sourceforge/" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /tests/pkgs-async/file.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | var slasp = require('slasp'); 3 | 4 | exports.pkg = function(args, callback) { 5 | var src; 6 | 7 | slasp.sequence([ 8 | function(callback) { 9 | args.fetchurl()({ 10 | url : new nijs.NixURL("ftp://ftp.astron.com/pub/file/file-5.41.tar.gz"), 11 | sha256 : "0gv027jgdr0hdkw7m9ck0nwhq583f4aa7vnz4dzdbxv4ng3k5r8k" 12 | }, callback); 13 | }, 14 | 15 | function(callback, _src) { 16 | src = _src; 17 | args.zlib(callback); 18 | }, 19 | 20 | function(callback, zlib) { 21 | args.stdenv().mkDerivation ({ 22 | name : "file-5.41", 23 | src : src, 24 | buildInputs : [ zlib ], 25 | 26 | meta : { 27 | description : "A program that shows the type of files", 28 | homepage : new nijs.NixURL("http://darwinsys.com/file") 29 | } 30 | }, callback); 31 | } 32 | ], callback); 33 | }; 34 | -------------------------------------------------------------------------------- /tests/pkgs-async/hello.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | var slasp = require('slasp'); 3 | 4 | exports.pkg = function(args, callback) { 5 | slasp.sequence([ 6 | function(callback) { 7 | args.fetchurl()({ 8 | url : new nijs.NixURL("mirror://gnu/hello/hello-2.12.tar.gz"), 9 | sha256 : "1ayhp9v4m4rdhjmnl2bq3cibrbqqkgjbl3s7yk2nhlh8vj3ay16g" 10 | }, callback); 11 | }, 12 | 13 | function(callback, src) { 14 | args.stdenv().mkDerivation ({ 15 | name : "hello-2.12", 16 | src : src, 17 | 18 | doCheck : true, 19 | 20 | meta : { 21 | description : "A program that produces a familiar, friendly greeting", 22 | homepage : new nijs.NixURL("http://www.gnu.org/software/hello/manual"), 23 | license : "GPLv3+" 24 | } 25 | }, callback); 26 | } 27 | ], callback); 28 | }; 29 | -------------------------------------------------------------------------------- /tests/pkgs-async/stdenv.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = { 4 | mkDerivation : function(args, callback) { 5 | if(typeof NIJS_EXECUTE != "undefined" && NIJS_EXECUTE) 6 | nijs.evaluateDerivation(args, callback); 7 | else 8 | callback(null, new nijs.NixFunInvocation({ 9 | funExpr: new nijs.NixExpression("pkgs.stdenv.mkDerivation"), 10 | paramExpr: args 11 | })); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /tests/pkgs-async/test.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | var slasp = require('slasp'); 3 | 4 | exports.pkg = function(args, callback) { 5 | args.stdenv().mkDerivation ({ 6 | name : "test", 7 | buildCommand : 'echo "Hello world!" > $out' 8 | }, callback); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/pkgs-async/zlib.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | var slasp = require('slasp'); 3 | 4 | exports.pkg = function(args, callback) { 5 | slasp.sequence([ 6 | function(callback) { 7 | args.fetchurl()({ 8 | url : new nijs.NixURL("http://www.zlib.net/fossils/zlib-1.2.12.tar.gz"), 9 | sha256 : "1n9na4fq4wagw1nzsfjr6wyly960jfa94460ncbf6p1fac44i14i" 10 | }, callback); 11 | }, 12 | 13 | function(callback, src) { 14 | args.stdenv().mkDerivation({ 15 | name : "zlib-1.2.12", 16 | src : src, 17 | configureFlags : "--shared" 18 | }, callback); 19 | } 20 | ], callback); 21 | }; 22 | -------------------------------------------------------------------------------- /tests/pkgs.js: -------------------------------------------------------------------------------- 1 | var pkgs = { 2 | 3 | stdenv : function() { 4 | return require('./pkgs/stdenv.js').pkg; 5 | }, 6 | 7 | fetchurl : function() { 8 | return require('./pkgs/fetchurl').pkg({ 9 | stdenv : pkgs.stdenv 10 | }); 11 | }, 12 | 13 | hello : function() { 14 | return require('./pkgs/hello.js').pkg({ 15 | stdenv : pkgs.stdenv, 16 | fetchurl : pkgs.fetchurl 17 | }); 18 | }, 19 | 20 | zlib : function() { 21 | return require('./pkgs/zlib.js').pkg({ 22 | stdenv : pkgs.stdenv, 23 | fetchurl : pkgs.fetchurl 24 | }); 25 | }, 26 | 27 | file : function() { 28 | return require('./pkgs/file.js').pkg({ 29 | stdenv : pkgs.stdenv, 30 | fetchurl : pkgs.fetchurl, 31 | zlib : pkgs.zlib 32 | }); 33 | }, 34 | 35 | perl : function() { 36 | return require('./pkgs/perl.js').pkg; 37 | }, 38 | 39 | openssl : function() { 40 | return require('./pkgs/openssl.js').pkg({ 41 | stdenv : pkgs.stdenv, 42 | fetchurl : pkgs.fetchurl, 43 | perl : pkgs.perl, 44 | zlib : pkgs.zlib 45 | }); 46 | }, 47 | 48 | curl : function() { 49 | return require('./pkgs/curl.js').pkg({ 50 | stdenv : pkgs.stdenv, 51 | fetchurl : pkgs.fetchurl, 52 | openssl : pkgs.openssl, 53 | zlib : pkgs.zlib 54 | }); 55 | }, 56 | 57 | wget : function() { 58 | return require('./pkgs/wget.js').pkg({ 59 | stdenv : pkgs.stdenv, 60 | fetchurl : pkgs.fetchurl, 61 | openssl : pkgs.openssl 62 | }); 63 | }, 64 | 65 | sumTest : function() { 66 | return require('./pkgs/sumTest.js').pkg({ 67 | stdenv : pkgs.stdenv 68 | }) 69 | }, 70 | 71 | writeTextFile : function(args) { 72 | return require('./pkgs/writeTextFile.js').pkg(args); 73 | }, 74 | 75 | stringWriteTest : function () { 76 | return require('./pkgs/stringWriteTest.js').pkg({ 77 | writeTextFile : pkgs.writeTextFile 78 | }); 79 | }, 80 | 81 | appendFilesTest : function() { 82 | return require('./pkgs/appendFilesTest.js').pkg({ 83 | stdenv : pkgs.stdenv 84 | }); 85 | }, 86 | 87 | createFileWithMessageTest : function() { 88 | return require('./pkgs/createFileWithMessageTest.js').pkg({ 89 | stdenv : pkgs.stdenv 90 | }); 91 | }, 92 | 93 | sayHello : function() { 94 | return require('./pkgs/sayHello.js').pkg({ 95 | stdenv : pkgs.stdenv 96 | }); 97 | }, 98 | 99 | addressPerson : function() { 100 | return require('./pkgs/addressPerson.js').pkg({ 101 | stdenv : pkgs.stdenv 102 | }); 103 | }, 104 | 105 | addressPersons : function() { 106 | return require('./pkgs/addressPersons.js').pkg({ 107 | stdenv : pkgs.stdenv 108 | }); 109 | }, 110 | 111 | addressPersonInformally : function() { 112 | return require('./pkgs/addressPersonInformally.js').pkg({ 113 | stdenv : pkgs.stdenv 114 | }); 115 | }, 116 | 117 | numbers : function() { 118 | return require('./pkgs/numbers.js').pkg({ 119 | stdenv : pkgs.stdenv 120 | }); 121 | }, 122 | 123 | sayHello2 : function() { 124 | return require('./pkgs/sayHello2.js').pkg({ 125 | stdenv : pkgs.stdenv 126 | }); 127 | }, 128 | 129 | objToXML : function() { 130 | return require('./pkgs/objToXML.js').pkg({ 131 | writeTextFile : pkgs.writeTextFile 132 | }); 133 | }, 134 | 135 | conditionals: function() { 136 | return require('./pkgs/conditionals.js').pkg({ 137 | writeTextFile : pkgs.writeTextFile 138 | }); 139 | }, 140 | 141 | bzip2 : function() { 142 | return require('./pkgs/bzip2.js').pkg({ 143 | stdenv : pkgs.stdenv, 144 | fetchurl : pkgs.fetchurl 145 | }); 146 | }, 147 | 148 | utillinux : function() { 149 | return require('./pkgs/utillinux.js').pkg({ 150 | stdenv : pkgs.stdenv, 151 | fetchurl : pkgs.fetchurl, 152 | zlib : pkgs.zlib 153 | }); 154 | }, 155 | 156 | python : function() { 157 | return require('./pkgs/python').pkg({ 158 | stdenv : pkgs.stdenv, 159 | fetchurl : pkgs.fetchurl, 160 | zlib : pkgs.zlib, 161 | bzip2 : pkgs.bzip2, 162 | openssl : pkgs.openssl, 163 | }); 164 | }, 165 | 166 | nodejs : function() { 167 | return require('./pkgs/nodejs').pkg({ 168 | stdenv : pkgs.stdenv, 169 | fetchurl : pkgs.fetchurl, 170 | python : pkgs.python, 171 | zlib : pkgs.zlib, 172 | openssl : pkgs.openssl, 173 | utillinux : pkgs.utillinux 174 | }); 175 | }, 176 | 177 | buildNodePackage : function() { 178 | return require('./pkgs/nodejs/buildNodePackage.js').pkg({ 179 | stdenv : pkgs.stdenv, 180 | nodejs : pkgs.nodejs 181 | }); 182 | }, 183 | 184 | optparse : function() { 185 | return require('./pkgs/optparse.js').pkg({ 186 | buildNodePackage : pkgs.buildNodePackage, 187 | fetchurl : pkgs.fetchurl 188 | }); 189 | }, 190 | 191 | slasp : function() { 192 | return require('./pkgs/slasp.js').pkg({ 193 | buildNodePackage : pkgs.buildNodePackage, 194 | fetchurl : pkgs.fetchurl 195 | }); 196 | }, 197 | 198 | nijs : function() { 199 | return require('./pkgs/nijs.js').pkg({ 200 | buildNodePackage : pkgs.buildNodePackage, 201 | fetchurl : pkgs.fetchurl, 202 | optparse : pkgs.optparse, 203 | slasp : pkgs.slasp 204 | }); 205 | }, 206 | 207 | underscoreTest : function() { 208 | return require('./pkgs/underscoreTest.js').pkg; 209 | }, 210 | 211 | HelloModel : function() { 212 | return require('./pkgs/HelloModel.js').pkg({ 213 | stdenv : pkgs.stdenv, 214 | fetchurl : pkgs.fetchurl 215 | }); 216 | } 217 | }; 218 | 219 | exports.pkgs = pkgs; 220 | -------------------------------------------------------------------------------- /tests/pkgs/HelloModel.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | var inherit = require('nijs/lib/ast/util/inherit.js').inherit; 3 | var HelloSourceModel = require('./HelloModel/HelloSourceModel.js').HelloSourceModel; 4 | 5 | function HelloModel(args) { 6 | this.args = args; 7 | 8 | this.name = "hello-2.12"; 9 | this.source = new HelloSourceModel(args); 10 | this.meta = { 11 | description: "A program that produces a familiar, friendly greeting", 12 | homepage: "http://www.gnu.org/software/hello/manual", 13 | license: "GPLv3+" 14 | }; 15 | } 16 | 17 | /* HelloModel inherits from NixASTNode */ 18 | inherit(nijs.NixASTNode, HelloModel); 19 | 20 | /** 21 | * @see NixASTNode#toNixAST 22 | */ 23 | HelloModel.prototype.toNixAST = function() { 24 | var self = this; 25 | 26 | var metadataWrapper = { 27 | toNixAST: function() { 28 | return { 29 | description: self.meta.description, 30 | homepage: new nijs.NixURL(self.meta.homepage), 31 | license: self.meta.license 32 | }; 33 | } 34 | }; 35 | 36 | return this.args.stdenv().mkDerivation ({ 37 | name: this.name, 38 | src: this.source, 39 | doCheck: true, 40 | meta: new nijs.NixASTNode(metadataWrapper) 41 | }); 42 | }; 43 | 44 | exports.pkg = function(args) { 45 | return new HelloModel(args); 46 | }; 47 | -------------------------------------------------------------------------------- /tests/pkgs/HelloModel/HelloSourceModel.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | var inherit = require('nijs/lib/ast/util/inherit.js').inherit; 3 | 4 | function HelloSourceModel(args) { 5 | this.args = args; 6 | this.src = "mirror://gnu/hello/hello-2.12.tar.gz"; 7 | this.sha256 = "1ayhp9v4m4rdhjmnl2bq3cibrbqqkgjbl3s7yk2nhlh8vj3ay16g"; 8 | } 9 | 10 | /* HelloSourceModel inherits from NixASTNode */ 11 | inherit(nijs.NixASTNode, HelloSourceModel); 12 | 13 | /** 14 | * @see NixASTNode#toNixAST 15 | */ 16 | HelloSourceModel.prototype.toNixAST = function() { 17 | return this.args.fetchurl()({ 18 | url: new nijs.NixURL(this.src), 19 | sha256: this.sha256 20 | }); 21 | }; 22 | 23 | exports.HelloSourceModel = HelloSourceModel; 24 | -------------------------------------------------------------------------------- /tests/pkgs/addressPerson.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "addressPerson", 6 | message : new nijs.NixFunInvocation({ 7 | funExpr : new nijs.NixFunction({ 8 | argSpec: { 9 | "firstName": undefined, 10 | "lastName": undefined, 11 | "prefix": "Dear" 12 | }, 13 | body: "${prefix} ${firstName} ${lastName}" 14 | }), 15 | paramExpr : { 16 | "firstName": "Sander", 17 | "lastName": "van der Burg" 18 | } 19 | }), 20 | buildCommand : "echo $message > $out" 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /tests/pkgs/addressPersonInformally.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return new nijs.NixLet({ 5 | value: { 6 | person: { 7 | firstName: "Sander", 8 | lastName: "van der Burg" 9 | } 10 | }, 11 | body: args.stdenv().mkDerivation({ 12 | name: "addressPersonInformally", 13 | greeting: new nijs.NixAttrReference({ 14 | attrSetExpr: new nijs.NixExpression("person"), 15 | refExpr: new nijs.NixExpression("howToGreet"), 16 | orExpr: "Hi" 17 | }), 18 | firstName: new nijs.NixAttrReference({ 19 | attrSetExpr: new nijs.NixExpression("person"), 20 | refExpr: new nijs.NixExpression("firstName") 21 | }), 22 | buildCommand : "echo $greeting $firstName > $out" 23 | }) 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /tests/pkgs/addressPersons.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "addressPersons", 6 | message : new nijs.NixFunInvocation({ 7 | funExpr : new nijs.NixFunction({ 8 | argSpec : ["persons", "prefix"], 9 | body : new nijs.NixExpression('map (person: "${prefix} ${person}\n") persons') 10 | }), 11 | paramExpr : { 12 | "persons": [ "Sander", "Eelco" ], 13 | "prefix": "Dear" 14 | } 15 | }), 16 | buildCommand : "echo $message > $out" 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /tests/pkgs/append File B/text.txt: -------------------------------------------------------------------------------- 1 | world! 2 | -------------------------------------------------------------------------------- /tests/pkgs/appendFileA/text.txt: -------------------------------------------------------------------------------- 1 | Hello -------------------------------------------------------------------------------- /tests/pkgs/appendFilesTest.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation ({ 5 | name : "appendFiles", 6 | 7 | appendFileA : new nijs.NixFile ({ 8 | value : "./appendFileA/text.txt", 9 | module : module 10 | }), 11 | 12 | appendFileB : new nijs.NixFile ({ 13 | value : "./append File B/text.txt", 14 | module : module 15 | }), 16 | 17 | buildCommand : "cat $appendFileA $appendFileB > $out" 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /tests/pkgs/bzip2.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "bzip2-1.0.6", 6 | src : args.fetchurl()({ 7 | url : new nijs.NixURL("http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz"), 8 | sha256 : "1kfrc7f0ja9fdn6j1y6yir6li818npy6217hvr3wzmnmzhs8z152" 9 | }), 10 | 11 | makeFlags : "PREFIX=$(out)", 12 | 13 | preBuild : "make -f Makefile-libbz2_so", 14 | 15 | preInstall : "mkdir -p $out/lib\n" + 16 | "mv libbz2.so* $out/lib\n" + 17 | "(cd $out/lib && ln -s libbz2.so.1.0.? libbz2.so && ln -s libbz2.so.1.0.? libbz2.so.1);", 18 | 19 | postInstall : "rm $out/bin/bunzip2* $out/bin/bzcat*\n" + 20 | "ln -s bzip2 $out/bin/bunzip2\n" + 21 | "ln -s bzip2 $out/bin/bzcat", 22 | 23 | meta : { 24 | homepage : new nijs.NixURL("http://www.bzip2.org"), 25 | description : "bzip2 is a freely available, patent free, high-quality data compressor." 26 | } 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /tests/pkgs/conditionals.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return new nijs.NixAssert({ 5 | conditionExpr: true, 6 | body: new nijs.NixLet({ 7 | value: { 8 | test: true 9 | }, 10 | body: args.writeTextFile({ 11 | name : "conditionals", 12 | text : new nijs.NixIf({ 13 | ifExpr: new nijs.NixExpression("test"), 14 | thenExpr: "It is true!", 15 | elseExpr: "It is false!" 16 | }) 17 | }) 18 | }) 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /tests/pkgs/createFileWithMessageTest.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation ({ 5 | name : "createFileWithMessageTest", 6 | buildCommand : new nijs.NixInlineJS({ 7 | requires : [ 8 | { "var" : "fs", "module" : "fs" }, 9 | { "var" : "path", "module" : "path" } 10 | ], 11 | code : function() { 12 | fs.mkdirSync(process.env['out']); 13 | var message = "Hello world written through inline JavaScript!"; 14 | fs.writeFileSync(path.join(process.env['out'], "message.txt"), message); 15 | } 16 | }) 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /tests/pkgs/curl.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "curl-7.69.1", 6 | src : args.fetchurl()({ 7 | url : new nijs.NixURL("http://curl.haxx.se/download/curl-7.69.1.tar.bz2"), 8 | sha256 : "1s2ddjjif1wkp69vx25nzxklhimgqzaazfzliyl6mpvsa2yybx9g" 9 | }), 10 | 11 | propagatedBuildInputs : [ 12 | args.zlib(), 13 | args.openssl() 14 | ], 15 | 16 | preConfigure : "sed -e 's|/usr/bin|/no-such-path|g' -i.bak configure", 17 | 18 | meta : { 19 | homepage : new nijs.NixURL("http://curl.haxx.se"), 20 | description : "A command line tool for transferring files with URL syntax" 21 | } 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /tests/pkgs/fetchurl/builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | if [ "$(type -P curl)" = "" ] # Dirty way to lookup curl, but the derivation has a fixed output, so it's fine 4 | then 5 | curl="/run/current-system/sw/bin/curl" 6 | else 7 | curl="$(type -P curl)" 8 | fi 9 | 10 | for url in $mirrors 11 | do 12 | if $curl --location --max-redirs 20 --retry 3 --disable-epsv --cookie-jar cookies --insecure --fail "$url" --output "$out" 13 | then 14 | success=1 15 | break 16 | fi 17 | done 18 | 19 | if [ "$success" != "1" ] 20 | then 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /tests/pkgs/fetchurl/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | var nijs = require('nijs'); 4 | 5 | exports.pkg = function(args) { 6 | return function(funArgs) { 7 | 8 | /* Determine the component's name */ 9 | var urlString; 10 | 11 | if(typeof funArgs.url == "string") 12 | urlString = funArgs.url; 13 | else if(funArgs.url instanceof nijs.NixURL) 14 | urlString = funArgs.url.value; 15 | else 16 | throw "The specified url is in an unknown format!"; 17 | 18 | var name; 19 | 20 | if(funArgs.name === undefined) 21 | name = path.basename(urlString); 22 | else 23 | name = funArgs.name; 24 | 25 | /* Check whether the right output hash is specified */ 26 | 27 | var outputHashAlgo; 28 | var outputHash; 29 | 30 | if(funArgs.md5 !== undefined && funArgs.md5 != "") { 31 | outputHashAlgo = "md5"; 32 | outputHash = funArgs.md5; 33 | } else if(funArgs.sha1 !== undefined && funArgs.sha1 != "") { 34 | outputHashAlgo = "sha1"; 35 | outputHash = funArgs.sha1; 36 | } else if(funArgs.sha256 !== undefined || funArgs.sha256 != "") { 37 | outputHashAlgo = "sha256"; 38 | outputHash = funArgs.sha256; 39 | } else { 40 | throw "No output hash specified! Specify either 'md5', 'sha1', or 'sha256'!"; 41 | } 42 | 43 | /* Pick the right list of mirrors, in case a mirror:// url has been specified */ 44 | 45 | if(urlString.substring(0, "mirror://".length) == "mirror://") { 46 | 47 | /* Open mirrors config file */ 48 | var mirrorsConfigFile = path.join(path.dirname(module.filename), "mirrors.json"); 49 | var mirrorsConfig = JSON.parse(fs.readFileSync(mirrorsConfigFile)); 50 | 51 | /* Determine the mirror identifier */ 52 | var urlPath = urlString.substring("mirror://".length - 1); 53 | var mirrorComponent = urlPath.match(/\/[a-zA-Z0-9_]+\//); 54 | var mirror = mirrorComponent.toString().substring(1, mirrorComponent.toString().length - 1); 55 | 56 | /* Determine the relative path to the file */ 57 | var filePath = urlPath.substring(mirrorComponent.toString().length); 58 | 59 | /* Append the file to each mirror */ 60 | 61 | mirrors = mirrorsConfig[mirror]; 62 | 63 | for(var i = 0; i < mirrors.length; i++) { 64 | mirrors[i] = mirrors[i] + filePath; 65 | } 66 | 67 | } else { 68 | mirrors = [ funArgs.url ]; 69 | } 70 | 71 | /* Create the derivation that specifies the build action */ 72 | 73 | return args.stdenv().mkDerivation({ 74 | name : name, 75 | 76 | mirrors : mirrors, 77 | 78 | builder : new nijs.NixFile({ 79 | value : "./builder.sh", 80 | module : module 81 | }), 82 | 83 | outputHashAlgo : outputHashAlgo, 84 | outputHash : outputHash, 85 | 86 | PATH : process.env['PATH'], 87 | 88 | /* 89 | * We borrow these environment variables from the caller to allow easy proxy 90 | * configuration. This is impure, but a fixed-output derivation like fetchurl 91 | * is allowed to do so since its result is by definition pure. 92 | */ 93 | impureEnvVars : [ "http_proxy", "https_proxy", "ftp_proxy", "all_proxy", "no_proxy" ], 94 | 95 | /* 96 | * Doing the download on a remote machine just duplicates network 97 | * traffic, so don't do that */ 98 | preferLocalBuild : true, 99 | 100 | /* We use the host system's curl, which does not work in a chroot */ 101 | __noChroot : true 102 | }); 103 | }; 104 | }; 105 | -------------------------------------------------------------------------------- /tests/pkgs/fetchurl/mirrors.json: -------------------------------------------------------------------------------- 1 | { 2 | "gnu" : [ 3 | "http://ftpmirror.gnu.org/", 4 | "http://ftp.nluug.nl/pub/gnu/", 5 | "http://mirrors.kernel.org/gnu/", 6 | "ftp://mirror.cict.fr/gnu/", 7 | "ftp://ftp.cs.tu-berlin.de/pub/gnu/", 8 | "ftp://ftp.chg.ru/pub/gnu/", 9 | "ftp://ftp.funet.fi/pub/mirrors/ftp.gnu.org/gnu/", 10 | "http://ftp.gnu.org/pub/gnu/" 11 | ], 12 | 13 | "sourceforge" : [ 14 | "http://prdownloads.sourceforge.net/", 15 | "http://heanet.dl.sourceforge.net/sourceforge/", 16 | "http://surfnet.dl.sourceforge.net/sourceforge/", 17 | "http://dfn.dl.sourceforge.net/sourceforge/", 18 | "http://mesh.dl.sourceforge.net/sourceforge/", 19 | "http://ovh.dl.sourceforge.net/sourceforge/", 20 | "http://osdn.dl.sourceforge.net/sourceforge/", 21 | "http://kent.dl.sourceforge.net/sourceforge/" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /tests/pkgs/file.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation ({ 5 | name : "file-5.41", 6 | 7 | src : args.fetchurl()({ 8 | url : new nijs.NixURL("http://ftp.astron.com/pub/file/file-5.41.tar.gz"), 9 | sha256 : "0gv027jgdr0hdkw7m9ck0nwhq583f4aa7vnz4dzdbxv4ng3k5r8k" 10 | }), 11 | 12 | buildInputs : [ args.zlib() ], 13 | 14 | meta : { 15 | description : "A program that shows the type of files", 16 | homepage : new nijs.NixURL("http://darwinsys.com/file") 17 | } 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /tests/pkgs/hello.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation ({ 5 | name : "hello-2.12", 6 | 7 | src : args.fetchurl()({ 8 | url : new nijs.NixURL("mirror://gnu/hello/hello-2.12.tar.gz"), 9 | sha256 : "1ayhp9v4m4rdhjmnl2bq3cibrbqqkgjbl3s7yk2nhlh8vj3ay16g" 10 | }), 11 | 12 | doCheck : true, 13 | 14 | meta : { 15 | description : "A program that produces a familiar, friendly greeting", 16 | homepage : new nijs.NixURL("http://www.gnu.org/software/hello/manual"), 17 | license : "GPLv3+" 18 | } 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /tests/pkgs/nijs.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.buildNodePackage()({ 5 | name : "nijs-0.0.26", 6 | src : new nijs.NixFile({ 7 | value : "../..", 8 | module : module 9 | }), 10 | deps : [ 11 | args.optparse(), 12 | args.slasp() 13 | ], 14 | 15 | meta : { 16 | description : "An internal DSL for Nix in JavaScript" 17 | } 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /tests/pkgs/nodejs/build-node-package.sh: -------------------------------------------------------------------------------- 1 | source $stdenv/setup 2 | 3 | unpackPhase() { 4 | true 5 | } 6 | 7 | configurePhase() { 8 | runHook preConfigure 9 | mkdir -p node_modules 10 | 11 | for i in $deps 12 | do 13 | for j in $i/lib/node_modules/* 14 | do 15 | if [ -d $j ] 16 | then 17 | ln -sf $j node_modules 18 | fi 19 | done 20 | done 21 | 22 | export HOME=$(pwd) 23 | runHook postConfigure 24 | } 25 | 26 | buildPhase() { 27 | runHook preBuild 28 | npm --offline install $src 29 | runHook postBuild 30 | } 31 | 32 | installPhase() { 33 | runHook preInstall 34 | 35 | # Move the node_modules to the output folder 36 | mkdir -p $out/lib/node_modules 37 | mv node_modules/* $out/lib/node_modules 38 | 39 | # If we have executables move the .bin folder and create a symlink 40 | if [ -d node_modules/.bin ] 41 | then 42 | mv node_modules/.bin $out/lib/node_modules 43 | ln -sv $out/lib/node_modules/.bin $out/bin 44 | fi 45 | 46 | runHook postInstall 47 | } 48 | 49 | genericBuild 50 | -------------------------------------------------------------------------------- /tests/pkgs/nodejs/buildNodePackage.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return function(funArgs) { 5 | return args.stdenv().mkDerivation({ 6 | name : funArgs.name, 7 | src : funArgs.src, 8 | deps : funArgs.deps, 9 | 10 | propagatedNativeBuildInputs : [ 11 | args.nodejs() 12 | ], 13 | 14 | builder : new nijs.NixFile({ 15 | value : "build-node-package.sh", 16 | module : module 17 | }) 18 | 19 | }); 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /tests/pkgs/nodejs/index.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "node-12.22.12", 6 | src : args.fetchurl()({ 7 | url : new nijs.NixURL("https://nodejs.org/download/release/latest-v12.x/node-v12.22.12.tar.xz"), 8 | sha256 : "1whl0zi6fs9ay33bhcn2kh9xynran05iipahg1zzr6sv97wbfhmw" 9 | }), 10 | 11 | dontDisableStatic: true, 12 | 13 | preConfigure: 'sed -i -e "s|#!/usr/bin/env python|#! $(type -p python)|" configure', 14 | postInstall: 'sed -i -e "s|#!/usr/bin/env node|#! $out/bin/node|" $out/lib/node_modules/npm/bin/npm-cli.js', 15 | 16 | configureFlags : [ "--shared-openssl", "--shared-zlib" ], 17 | 18 | buildInputs : [ 19 | args.python(), 20 | args.openssl(), 21 | args.zlib(), 22 | args.utillinux() 23 | ], 24 | 25 | setupHook : new nijs.NixFile({ 26 | value : "setup-hook.sh", 27 | module : module 28 | }), 29 | 30 | meta : { 31 | homepage : new nijs.NixURL("http://nodejs.org"), 32 | description : "Platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications" 33 | } 34 | }); 35 | }; 36 | -------------------------------------------------------------------------------- /tests/pkgs/nodejs/setup-hook.sh: -------------------------------------------------------------------------------- 1 | addNodePath () { 2 | addToSearchPath NODE_PATH $1/lib/node_modules 3 | } 4 | 5 | addEnvHooks "$hostOffset" addNodePath 6 | -------------------------------------------------------------------------------- /tests/pkgs/numbers.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return new nijs.NixLet({ 5 | value: { 6 | generateNumbers : new nijs.NixFunction({ 7 | argSpec : ["min", "max"], 8 | body : new nijs.NixExpression("if min == max then [ min ] else [ min ] ++ (generateNumbers { min = builtins.add min 1; inherit max; })") 9 | }) 10 | }, 11 | body: args.stdenv().mkDerivation({ 12 | name : "numbers", 13 | numbers : new nijs.NixFunInvocation({ 14 | funExpr : new nijs.NixExpression("generateNumbers"), 15 | paramExpr : { min: 1, max: 10 } 16 | }), 17 | buildCommand : "echo $numbers > $out" 18 | }) 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /tests/pkgs/objToXML.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | var data = { 5 | "number": 1, 6 | "string": "Hello world", 7 | "URL": new nijs.NixURL("http://github.com"), 8 | "URL2": new nijs.NixURL("http://nixos.org/nix/manual/#chap-quick-start"), 9 | "null": null, 10 | "undefined": undefined, // This member should not be visible in the resulting XML 11 | "listOfStrings": [ "a", "b", "c", 1, 2, 3 ], 12 | "recursiveAttrSet": new nijs.NixRecursiveAttrSet({ 13 | "number": 2 14 | }), 15 | "keywords": { 16 | "assert": 0, 17 | "else": 1, 18 | "if": 2, 19 | "in": 3, 20 | "inherit": 4, 21 | "import": 5, 22 | "or": 6, 23 | "then": 7, 24 | "rec": 8, 25 | "with": 9 26 | }, 27 | "greeting": new nijs.NixInherit(), 28 | "hello": new nijs.NixInherit("greeting"), 29 | "world": new nijs.NixInherit("greeting"), 30 | "emptyObject": {}, 31 | "emptyRecursiveAttrSet": new nijs.NixRecursiveAttrSet({}), 32 | "emptyArray": [], 33 | "mergedObject": new nijs.NixMergeAttrs({ 34 | left: { 35 | "a": "a", 36 | "b": "b" 37 | }, 38 | right: { 39 | "a": "a2", 40 | "c": "c" 41 | } 42 | }) 43 | }; 44 | 45 | return new nijs.NixLet({ 46 | value: { 47 | greeting: { 48 | hello: "Hello ", 49 | world: "world!" 50 | }, 51 | dataXML: new nijs.NixFunInvocation({ 52 | funExpr: new nijs.NixExpression("builtins.toXML"), 53 | paramExpr: data 54 | }) 55 | }, 56 | body: args.writeTextFile({ 57 | name : "objToXML", 58 | text : new nijs.NixExpression("dataXML") 59 | }) 60 | }); 61 | }; 62 | -------------------------------------------------------------------------------- /tests/pkgs/openssl.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation ({ 5 | name : "openssl-1.1.1n", 6 | 7 | src : args.fetchurl()({ 8 | url : new nijs.NixURL("https://www.openssl.org/source/openssl-1.1.1n.tar.gz"), 9 | sha256 : "0ymif8rlc5cf5qp5bh2pxlrgq6xryh7g4sqfvrdjg9gnli8ypp20" 10 | }), 11 | 12 | buildInputs : [ args.perl() ], 13 | propagatedBuildInputs : [ args.zlib() ], 14 | 15 | preConfigure : "sed -i 's|/usr/bin/env|$(type -p env)|g' ./config", 16 | configureScript : "./config", 17 | configureFlags : [ "shared", "--libdir=lib" ], 18 | makeFlags : "MANDIR=$(out)/share/man" 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /tests/pkgs/optparse.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.buildNodePackage()({ 5 | name : "optparse-1.0.5", 6 | src : args.fetchurl()({ 7 | url : new nijs.NixURL("http://registry.npmjs.org/optparse/-/optparse-1.0.5.tgz"), 8 | sha1 : "75e75a96506611eb1c65ba89018ff08a981e2c16" 9 | }), 10 | 11 | meta : { 12 | description : "Command-line option parser library for NodeJS programs" 13 | } 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /tests/pkgs/perl.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = new nijs.NixExpression("pkgs.perl"); 4 | -------------------------------------------------------------------------------- /tests/pkgs/python/builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | source $stdenv/setup 4 | 5 | for i in $inputs 6 | do 7 | export C_INCLUDE_PATH=$i/include${C_INCLUDE_PATH:+:}$C_INCLUDE_PATH 8 | export LIBRARY_PATH=$i/lib${LIBRARY_PATH:+:}$LIBRARY_PATH 9 | done 10 | 11 | genericBuild 12 | -------------------------------------------------------------------------------- /tests/pkgs/python/deterministic-build.patch: -------------------------------------------------------------------------------- 1 | diff -ur orig/Lib/py_compile.py new/Lib/py_compile.py 2 | --- orig/Lib/py_compile.py 3 | +++ new/Lib/py_compile.py 4 | @@ -122,7 +122,10 @@ 5 | cfile = file + (__debug__ and 'c' or 'o') 6 | with open(cfile, 'wb') as fc: 7 | fc.write('\0\0\0\0') 8 | - wr_long(fc, timestamp) 9 | + if "DETERMINISTIC_BUILD" in os.environ: 10 | + fc.write('\0\0\0\0') 11 | + else: 12 | + wr_long(fc, timestamp) 13 | marshal.dump(codeobject, fc) 14 | fc.flush() 15 | fc.seek(0, 0) 16 | diff -ur orig/Python/import.c new/Python/import.c 17 | --- orig/Python/import.c 18 | +++ new/Python/import.c 19 | @@ -939,10 +939,12 @@ 20 | return; 21 | } 22 | /* Now write the true mtime (as a 32-bit field) */ 23 | - fseek(fp, 4L, 0); 24 | - assert(mtime <= 0xFFFFFFFF); 25 | - PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); 26 | - fflush(fp); 27 | + if (Py_GETENV("DETERMINISTIC_BUILD") == NULL) { 28 | + fseek(fp, 4L, 0); 29 | + assert(mtime <= 0xFFFFFFFF); 30 | + PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); 31 | + fflush(fp); 32 | + } 33 | fclose(fp); 34 | if (Py_VerboseFlag) 35 | PySys_WriteStderr("# wrote %s\n", cpathname); 36 | 37 | -------------------------------------------------------------------------------- /tests/pkgs/python/index.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | var inputs = [ 5 | args.zlib(), 6 | args.bzip2(), 7 | args.openssl() 8 | ]; 9 | 10 | return args.stdenv().mkDerivation({ 11 | name : "python-2.7.18", 12 | src : args.fetchurl()({ 13 | url : new nijs.NixURL("http://www.python.org/ftp/python/2.7.18/Python-2.7.18.tar.xz"), 14 | sha256 : "0hzgxl94hnflis0d6m4szjx0b52gah7wpmcg5g00q7am6xwhwb5n" 15 | }), 16 | 17 | patches : [ 18 | new nijs.NixFile({ 19 | value : "search-path.patch", 20 | module : module 21 | }), 22 | 23 | new nijs.NixFile({ 24 | value : "nix-store-mtime.patch", 25 | module : module 26 | }), 27 | 28 | new nijs.NixFile({ 29 | value : "deterministic-build.patch", 30 | module : module 31 | }) 32 | ], 33 | 34 | buildInputs : inputs, 35 | inputs : inputs, 36 | 37 | builder : new nijs.NixFile({ 38 | value : "builder.sh", 39 | module : module 40 | }), 41 | 42 | configureFlags : "--enable-shared", 43 | 44 | setupHook : new nijs.NixFile({ 45 | value : "setup-hook.sh", 46 | module : module 47 | }), 48 | 49 | meta : { 50 | homepage : new nijs.NixURL("http://python.org"), 51 | description : "Python is a programming language that lets you work quickly and integrate systems more effectively." 52 | } 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /tests/pkgs/python/nix-store-mtime.patch: -------------------------------------------------------------------------------- 1 | diff -ru -x '*~' Python-2.7.1-orig/Python/import.c Python-2.7.1/Python/import.c 2 | --- Python-2.7.1-orig/Python/import.c 2010-05-20 20:37:55.000000000 +0200 3 | +++ Python-2.7.1/Python/import.c 2011-01-04 15:55:11.000000000 +0100 4 | @@ -751,7 +751,7 @@ 5 | return NULL; 6 | } 7 | pyc_mtime = PyMarshal_ReadLongFromFile(fp); 8 | - if (pyc_mtime != mtime) { 9 | + if (pyc_mtime != mtime && mtime != 1) { 10 | if (Py_VerboseFlag) 11 | PySys_WriteStderr("# %s has bad mtime\n", cpathname); 12 | fclose(fp); 13 | -------------------------------------------------------------------------------- /tests/pkgs/python/search-path.patch: -------------------------------------------------------------------------------- 1 | diff -rc Python-2.4.4-orig/setup.py Python-2.4.4/setup.py 2 | *** Python-2.4.4-orig/setup.py 2006-10-08 19:41:25.000000000 +0200 3 | --- Python-2.4.4/setup.py 2007-05-27 16:04:54.000000000 +0200 4 | *************** 5 | *** 279,288 **** 6 | # Check for AtheOS which has libraries in non-standard locations 7 | if platform == 'atheos': 8 | lib_dirs += ['/system/libs', '/atheos/autolnk/lib'] 9 | - lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep) 10 | inc_dirs += ['/system/include', '/atheos/autolnk/include'] 11 | - inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep) 12 | 13 | # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb) 14 | if platform in ['osf1', 'unixware7', 'openunix8']: 15 | lib_dirs += ['/usr/ccs/lib'] 16 | --- 279,289 ---- 17 | # Check for AtheOS which has libraries in non-standard locations 18 | if platform == 'atheos': 19 | lib_dirs += ['/system/libs', '/atheos/autolnk/lib'] 20 | inc_dirs += ['/system/include', '/atheos/autolnk/include'] 21 | 22 | + lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep) 23 | + inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep) 24 | + 25 | # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb) 26 | if platform in ['osf1', 'unixware7', 'openunix8']: 27 | lib_dirs += ['/usr/ccs/lib'] 28 | -------------------------------------------------------------------------------- /tests/pkgs/python/setup-hook.sh: -------------------------------------------------------------------------------- 1 | addPythonPath() { 2 | addToSearchPathWithCustomDelimiter : PYTHONPATH $1/lib/python2.7/site-packages 3 | } 4 | 5 | toPythonPath() { 6 | local paths="$1" 7 | local result= 8 | for i in $paths; do 9 | p="$i/lib/python2.7/site-packages" 10 | result="${result}${result:+:}$p" 11 | done 12 | echo $result 13 | } 14 | 15 | addEnvHooks "$hostOffset" addPythonPath 16 | -------------------------------------------------------------------------------- /tests/pkgs/sayHello.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "sayHello", 6 | message : new nijs.NixFunInvocation({ 7 | funExpr : new nijs.NixFunction({ 8 | argSpec : "name", 9 | body : "Hello ${name}!" 10 | }), 11 | paramExpr : "Sander" 12 | }), 13 | buildCommand : "echo $message > $out" 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /tests/pkgs/sayHello2.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return new nijs.NixWith({ 5 | withExpr: { 6 | firstName: "Sander", 7 | lastName: "van der Burg" 8 | }, 9 | body: args.stdenv().mkDerivation({ 10 | name : "sayHello2", 11 | buildCommand : "echo ${firstName} ${lastName} > $out" 12 | }) 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /tests/pkgs/slasp.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.buildNodePackage()({ 5 | name : "slasp-0.0.4", 6 | src : args.fetchurl()({ 7 | url : new nijs.NixURL("http://registry.npmjs.org/slasp/-/slasp-0.0.4.tgz"), 8 | sha1 : "9adc26ee729a0f95095851a5489f87a5258d57a9" 9 | }), 10 | 11 | meta : { 12 | description : "SugarLess Asynchronous Structured Programming" 13 | } 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /tests/pkgs/stdenv.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = { 4 | mkDerivation : function(args) { 5 | return new nijs.NixFunInvocation({ 6 | funExpr: new nijs.NixExpression("pkgs.stdenv.mkDerivation"), 7 | paramExpr: args 8 | }); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /tests/pkgs/stringWriteTest.js: -------------------------------------------------------------------------------- 1 | exports.pkg = function(args) { 2 | return args.writeTextFile ({ 3 | name : "stringWriteTest", 4 | text : "I'd like to say: \"Hello World!\"" 5 | }); 6 | } 7 | -------------------------------------------------------------------------------- /tests/pkgs/sumTest.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation(new nijs.NixRecursiveAttrSet ({ // Allow attributes to refer to each other 5 | name : "sumtest", 6 | 7 | meta : { // Prevent builder to stringify the function 8 | sumFun : function(a, b) { 9 | return a + b; 10 | } 11 | }, 12 | 13 | buildCommand : 'echo ${toString (meta.sumFun 1 2)} > $out' 14 | })); 15 | }; 16 | -------------------------------------------------------------------------------- /tests/pkgs/underscoreTest.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | var proxytests = new nijs.NixFunInvocation({ 4 | funExpr: new nijs.NixImport( 5 | new nijs.NixFile({ 6 | value: "../proxytests.nix", 7 | module: module 8 | }) 9 | ), 10 | paramExpr: { 11 | pkgs: new nijs.NixInherit(), 12 | nijs: new nijs.NixInherit() 13 | } 14 | }); 15 | 16 | exports.pkg = new nijs.NixAttrReference({ 17 | attrSetExpr: proxytests, 18 | refExpr: new nijs.NixExpression("underscoreTest") 19 | }); 20 | -------------------------------------------------------------------------------- /tests/pkgs/utillinux.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "util-linux-2.37.4", 6 | src : args.fetchurl()({ 7 | url : new nijs.NixURL("https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.37/util-linux-2.37.4.tar.xz"), 8 | sha256 : "10svcnsqmrsd660bzcm7k6dm8sa7hkknhr3bag1nccwimlb6jkk3" 9 | }), 10 | 11 | configureFlags : [ 12 | "--without-ncurses", 13 | "--disable-use-tty-group", 14 | "--enable-fs-paths-default=/var/setuid-wrappers:/var/run/current-system/sw/sbin:/sbin", 15 | "--disable-makeinstall-setuid", 16 | "--disable-makeinstall-chown" 17 | ], 18 | 19 | buildInputs : [ 20 | args.zlib() 21 | ], 22 | 23 | meta : { 24 | description : "A set of system utilities for Linux." 25 | } 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /tests/pkgs/wget.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "wget-1.21", 6 | 7 | src : args.fetchurl()({ 8 | url : new nijs.NixURL("mirror://gnu/wget/wget-1.21.tar.gz"), 9 | sha256 : "09cknh5dbfa0kgw4jksi0xd224cwq50qsccwf34kd661s2dimg5k" 10 | }), 11 | 12 | configureFlags : "--with-ssl=openssl --with-openssl=yes", 13 | openssl: args.openssl(), 14 | OPENSSL_CFLAGS : "-I$openssl/include" , 15 | OPENSSL_LIBS : "-L$openssl/lib -lssl", 16 | 17 | buildInputs : [ args.openssl() ], 18 | 19 | meta : { 20 | description : "GNU Wget, a tool for retrieving files using HTTP, HTTPS, and FTP", 21 | license : "GPLv3+", 22 | homepage : new nijs.NixURL("http://www.gnu.org/software/wget") 23 | } 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /tests/pkgs/writeTextFile.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return new nijs.NixFunInvocation({ 5 | funExpr: new nijs.NixExpression("pkgs.writeTextFile"), 6 | paramExpr: args 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /tests/pkgs/zlib.js: -------------------------------------------------------------------------------- 1 | var nijs = require('nijs'); 2 | 3 | exports.pkg = function(args) { 4 | return args.stdenv().mkDerivation({ 5 | name : "zlib-1.2.12", 6 | src : args.fetchurl()({ 7 | url : new nijs.NixURL("https://www.zlib.net/fossils/zlib-1.2.12.tar.gz"), 8 | sha256 : "1n9na4fq4wagw1nzsfjr6wyly960jfa94460ncbf6p1fac44i14i" 9 | }), 10 | configureFlags : "--shared" 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /tests/proxytests.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} 2 | , system ? builtins.currentSystem 3 | , nijs ? builtins.getAttr (builtins.currentSystem) ((import ../release.nix {}).package) 4 | }: 5 | 6 | let 7 | nijsFunProxy = import ../lib/funProxy.nix { 8 | inherit (pkgs) stdenv lib nodejs; 9 | inherit nijs; 10 | }; 11 | 12 | nijsInlineProxy = import ../lib/inlineProxy.nix { 13 | inherit (pkgs) stdenv lib writeTextFile nodejs; 14 | inherit nijs; 15 | }; 16 | 17 | customNpmPkgs = import ./custom-npm-pkgs { 18 | inherit pkgs system; 19 | }; 20 | in 21 | rec { 22 | sum = import ./proxytests/sum.nix { 23 | inherit (pkgs) stdenv; 24 | inherit nijsFunProxy; 25 | }; 26 | 27 | appendTwoStrings = import ./proxytests/appendTwoStrings.nix { 28 | inherit (pkgs) stdenv; 29 | inherit nijsFunProxy; 30 | }; 31 | 32 | printObjectAndReturnBye = import ./proxytests/printObjectAndReturnBye.nix { 33 | inherit (pkgs) stdenv; 34 | inherit nijsFunProxy; 35 | }; 36 | 37 | returnEscapedString = import ./proxytests/returnEscapedString.nix { 38 | inherit (pkgs) stdenv; 39 | inherit nijsFunProxy; 40 | }; 41 | 42 | returnAttrSetStrings = import ./proxytests/returnAttrSetStrings.nix { 43 | inherit (pkgs) stdenv; 44 | inherit nijsFunProxy; 45 | }; 46 | 47 | underscoreTest = import ./proxytests/underscoreTest.nix { 48 | inherit (pkgs) stdenv; 49 | inherit (customNpmPkgs) underscore; 50 | inherit nijsFunProxy; 51 | }; 52 | 53 | timerTest = import ./proxytests/timerTest.nix { 54 | inherit (pkgs) stdenv; 55 | inherit nijsFunProxy; 56 | }; 57 | 58 | createFileWithMessage = import ./proxytests/createFileWithMessage.nix { 59 | inherit (pkgs) stdenv; 60 | inherit nijsInlineProxy; 61 | }; 62 | 63 | createFileWithUnderscore = import ./proxytests/createFileWithUnderscore.nix { 64 | inherit (pkgs) stdenv; 65 | inherit (customNpmPkgs) underscore; 66 | inherit nijsInlineProxy; 67 | }; 68 | 69 | indirectionWget = import ./proxytests/indirectionWget.nix { 70 | inherit (pkgs) stdenv; 71 | inherit pkgs; 72 | inherit nijsFunProxy; 73 | }; 74 | 75 | indirectCat = import ./proxytests/indirectCat.nix { 76 | inherit (pkgs) stdenv; 77 | inherit nijsFunProxy; 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /tests/proxytests/appendTwoStrings.nix: -------------------------------------------------------------------------------- 1 | {stdenv, nijsFunProxy}: 2 | 3 | let 4 | appendTwoStrings = a: b: nijsFunProxy { 5 | name = "appendTwoStrings"; 6 | function = '' 7 | function appendTwoStrings(a, b) { 8 | return a + " " + b; 9 | } 10 | ''; 11 | args = [ a b ]; 12 | }; 13 | in 14 | stdenv.mkDerivation { 15 | name = "appendTwoStrings"; 16 | 17 | buildCommand = '' 18 | echo ${appendTwoStrings "Hello" "world"} > $out 19 | ''; 20 | } 21 | -------------------------------------------------------------------------------- /tests/proxytests/createFileWithMessage.nix: -------------------------------------------------------------------------------- 1 | {stdenv, nijsInlineProxy}: 2 | 3 | stdenv.mkDerivation { 4 | name = "createFileWithMessage"; 5 | buildCommand = nijsInlineProxy { 6 | name = "createFileWithMessage-buildCommand"; 7 | requires = [ 8 | { var = "fs"; module = "fs"; } 9 | { var = "path"; module = "path"; } 10 | ]; 11 | code = '' 12 | fs.mkdirSync(process.env['out']); 13 | var message = "Hello world written through inline JavaScript!"; 14 | fs.writeFileSync(path.join(process.env['out'], "message.txt"), message); 15 | ''; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /tests/proxytests/createFileWithUnderscore.nix: -------------------------------------------------------------------------------- 1 | {stdenv, underscore, nijsInlineProxy}: 2 | 3 | stdenv.mkDerivation { 4 | name = "createFileWithUnderscore"; 5 | buildCommand = nijsInlineProxy { 6 | name = "createFileWithUnderscore-buildCommand"; 7 | modules = [ underscore ]; 8 | requires = [ 9 | { var = "fs"; module = "fs"; } 10 | { var = "_"; module = "underscore"; } 11 | ]; 12 | code = '' 13 | var words = [ "This", "is", "very", "cool" ]; 14 | var message = _.sortBy(words, function(word) { 15 | return word.toLowerCase().charAt(0); 16 | }); 17 | 18 | fs.writeFileSync(process.env['out'], message.toString()); 19 | ''; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /tests/proxytests/indirectCat.nix: -------------------------------------------------------------------------------- 1 | {stdenv, nijsFunProxy}: 2 | 3 | let 4 | passMessageFile = messageFile: nijsFunProxy { 5 | name = "sum"; 6 | 7 | requires = [ 8 | { var = "fs"; module = "fs"; } 9 | ]; 10 | 11 | function = '' 12 | function passMessageFile(messageFile) { 13 | var message = fs.readFileSync(messageFile.paramExpr); 14 | return message.toString(); 15 | } 16 | ''; 17 | args = [ messageFile ]; 18 | }; 19 | in 20 | stdenv.mkDerivation { 21 | name = "indirectCat"; 22 | buildCommand = '' 23 | echo ${passMessageFile ./message.txt} > $out 24 | ''; 25 | } 26 | -------------------------------------------------------------------------------- /tests/proxytests/indirectionWget.nix: -------------------------------------------------------------------------------- 1 | {stdenv, pkgs, nijsFunProxy}: 2 | 3 | let 4 | indirectionWgetFun = nijsFunProxy { 5 | name = "indirectionWgetFun"; 6 | function = '' 7 | function indirectionWget() { 8 | return new nijs.NixExpression("{pkgs}: pkgs.wget"); 9 | } 10 | ''; 11 | args = []; 12 | }; 13 | 14 | indirectionWget = indirectionWgetFun { inherit pkgs; }; 15 | in 16 | stdenv.mkDerivation { 17 | name = "indirectionWget"; 18 | 19 | buildCommand = '' 20 | mkdir -p $out/bin 21 | ln -s ${indirectionWget}/bin/wget $out/bin/wget 22 | ''; 23 | } 24 | -------------------------------------------------------------------------------- /tests/proxytests/message.txt: -------------------------------------------------------------------------------- 1 | The message -------------------------------------------------------------------------------- /tests/proxytests/printObjectAndReturnBye.nix: -------------------------------------------------------------------------------- 1 | {stdenv, nijsFunProxy}: 2 | 3 | let 4 | printObjectAndReturnBye = args: nijsFunProxy { 5 | name = "printObjectAndReturnBye"; 6 | function = '' 7 | function printObjectAndReturnBye(args) { 8 | for(var attrName in args) { 9 | var attrValue = args[attrName]; 10 | process.stderr.write(attrName + " = " + attrValue + "\n"); 11 | } 12 | 13 | return args.attrset.b; 14 | } 15 | ''; 16 | args = [ args ]; 17 | }; 18 | in 19 | stdenv.mkDerivation { 20 | name = "printObjectAndReturnBye"; 21 | 22 | buildCommand = '' 23 | echo ${printObjectAndReturnBye { 24 | str = "Hello world"; 25 | number = 12345; 26 | list = [ 1 2 "abc" ]; 27 | attrset = { 28 | a = 1; 29 | b = "Bye world"; 30 | }; 31 | } } > $out 32 | ''; 33 | } 34 | -------------------------------------------------------------------------------- /tests/proxytests/returnAttrSetStrings.nix: -------------------------------------------------------------------------------- 1 | {stdenv, nijsFunProxy}: 2 | 3 | let 4 | returnAttrSetStrings = nijsFunProxy { 5 | name = "returnAttrSetStrings"; 6 | function = '' 7 | function returnAttrSetStrings() { 8 | return { 9 | first: "Hello", 10 | ",": ", ", 11 | "second/third/fourth": "how are you?" 12 | }; 13 | } 14 | ''; 15 | args = []; 16 | }; 17 | in 18 | stdenv.mkDerivation { 19 | name = "returnAttrSetStrings"; 20 | 21 | buildCommand = '' 22 | cat > $out < $out < $out 19 | ''; 20 | } 21 | -------------------------------------------------------------------------------- /tests/proxytests/timerTest.nix: -------------------------------------------------------------------------------- 1 | {stdenv, nijsFunProxy}: 2 | 3 | let 4 | timerTest = message: nijsFunProxy { 5 | name = "timerTest"; 6 | function = '' 7 | function timerTest(message) { 8 | setTimeout(function() { 9 | nijsCallbacks.callback(null, message); 10 | }, 3000); 11 | } 12 | ''; 13 | args = [ message ]; 14 | async = true; 15 | }; 16 | in 17 | stdenv.mkDerivation { 18 | name = "timerTest"; 19 | 20 | buildCommand = '' 21 | echo ${timerTest "Hello world! The timer test works!"} > $out 22 | ''; 23 | } 24 | -------------------------------------------------------------------------------- /tests/proxytests/underscoreTest.nix: -------------------------------------------------------------------------------- 1 | {stdenv, underscore, nijsFunProxy}: 2 | 3 | let 4 | underscoreTestFun = numbers: nijsFunProxy { 5 | name = "underscoreTest"; 6 | function = '' 7 | function underscoreTestFun(numbers) { 8 | var words = [ "one", "two", "three", "four", "five" ]; 9 | var result = []; 10 | 11 | _.each(numbers, function(elem) { 12 | result.push(words[elem - 1]); 13 | }); 14 | 15 | return result; 16 | } 17 | ''; 18 | args = [ numbers ]; 19 | modules = [ underscore ]; 20 | requires = [ 21 | { var = "_"; module = "underscore"; } 22 | ]; 23 | }; 24 | in 25 | stdenv.mkDerivation { 26 | name = "underscoreTest"; 27 | 28 | buildCommand = '' 29 | echo ${toString (underscoreTestFun [ 5 4 3 2 1 ])} > $out 30 | ''; 31 | } 32 | --------------------------------------------------------------------------------