diff --git a/bin/index.js b/bin/index.js index 0c15239..3b9c0b2 100755 --- a/bin/index.js +++ b/bin/index.js @@ -4,6 +4,7 @@ const { hideBin } = require('yargs/helpers') const { install, installFromDesc } = require('../src/install') const { init } = require('../src/init') +const { installFromPackageJson } = require('../src/installFromPackagejson') yargs(hideBin(process.argv)) .command( @@ -56,5 +57,23 @@ yargs(hideBin(process.argv)) (argv) => { installFromDesc(argv.description_file, argv.destination_folder) } - ) +). + command( + 'installFromPackageJson [packageJson] [destination_folder]', + 'Install dependencies from package.json file containing an "rdependencies" entry.', + (yargs) => { + yargs. + positional('packageJson', { + type: 'string', + describe: 'Path to the package.json file.', + default: "package.json", + }) + .positional('destination_folder', { + type: 'string', + default: "./webr_packages", + describe: 'Where to install the packages', + }); + }, (argv) => { + installFromPackageJson(argv.packageJson, argv.destination_folder) + }) .parse(); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4fc638d..4d31c35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "webrcli", - "version": "1.0.0", + "version": "0.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "webrcli", - "version": "1.0.0", + "version": "0.0.5", "license": "MIT", "dependencies": { "axios": "^1.6.2", @@ -2425,9 +2425,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -4704,9 +4704,9 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", diff --git a/package.json b/package.json index 47bb58f..5ebef8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webrcli", - "version": "0.0.4", + "version": "0.0.5", "description": "cli tools for building node project with webr inside", "main": "index.js", "bin": { diff --git a/src/init.js b/src/init.js index c7e5075..4f876e6 100644 --- a/src/init.js +++ b/src/init.js @@ -24,13 +24,19 @@ const init = async (destination_folder) => { process.chdir(destination_folder); // installing npm dependencies + log("⏳ launching npm init, installing webr & spidyr----"); execSync(`npm init -y`); execSync(`npm install webr spidyr`); + // append to package.json + let packageJson = JSON.parse(fs.readFileSync("package.json")); + packageJson.scripts["postinstall"] = "webrcli installFromPackageJson"; + fs.writeFileSync("package.json", JSON.stringify(packageJson, null, 2)); + process.chdir(previousDirectory); // copying template - log("👉 Copying template ----"); + log("💀 Copying project skeleton ----"); fs.cpSync( path.join(__dirname, "..", "template"), path.join(destination_folder), @@ -44,9 +50,13 @@ const init = async (destination_folder) => { webr_packages ) + process.chdir(destination_folder); + log("👉 Installing {pkgload} ----"); await installIt("pkgload", webr_packages) + process.chdir(previousDirectory); + return; } diff --git a/src/install.js b/src/install.js index d5d618b..9a7a1e1 100644 --- a/src/install.js +++ b/src/install.js @@ -3,6 +3,7 @@ const fs = require("fs"); const { installOnePackage } = require('./install-utils'); const { create_mount_folder_init_webr } = require('./config-utils.js'); +const { append_package_json } = require('./packagejsonmanip'); const installIt = async function ( package_to_install, @@ -44,6 +45,8 @@ const installIt = async function ( ) } + append_package_json(package_to_install) + await webR.close(); return true diff --git a/src/installFromPackagejson.js b/src/installFromPackagejson.js new file mode 100644 index 0000000..4a9acdb --- /dev/null +++ b/src/installFromPackagejson.js @@ -0,0 +1,28 @@ +const { installIt } = require('./install'); +const { parsePackageJson } = require('./packagejsonmanip'); + +function installFromPackageJson( + package_json = "package.json", + destination_folder = "webr_packages" +) { + // Read the package.json file + const package_json_read = parsePackageJson(package_json); + const dependencies = package_json_read.rdependencies; + + if (dependencies) { + // Install the dependencies + for (let dependency of dependencies) { + installIt( + dependency, + destination_folder + ); + } + } else { + console.log("❗️ No rdependencies found in the package.json file"); + } + +} + +module.exports = { + installFromPackageJson: installFromPackageJson +} \ No newline at end of file diff --git a/src/packagejsonmanip.js b/src/packagejsonmanip.js new file mode 100644 index 0000000..a6c9ecb --- /dev/null +++ b/src/packagejsonmanip.js @@ -0,0 +1,58 @@ +const fs = require('fs'); + +function parsePackageJson(filePath) { + try { + const fileContent = fs.readFileSync(filePath, 'utf8'); + const packageJson = JSON.parse(fileContent); + return packageJson; + } catch (error) { + console.error('Error parsing' + filePath, error); + return null; + } +} + +function writePackageJson(filePath, packageJson) { + try { + const fileContent = JSON.stringify(packageJson, null, 2); + fs.writeFileSync(filePath, fileContent, 'utf8'); + } catch (error) { + console.error('Error writing package.json:', error); + } +} + +function addDependencies( + dependencies, + packageJson = "package.json" +) { + const pk = parsePackageJson(packageJson) + if (!pk.rdependencies) { + pk.rdependencies = [] + } + pk.rdependencies.push(dependencies) + + writePackageJson(packageJson, pk) +} + +const append_package_json = function (package_to_add) { + const package_json_path = process.cwd() + "/package.json"; + if (fs.existsSync(package_json_path)) { + const package_json = JSON.parse(fs.readFileSync(package_json_path)); + + if (!package_json.rdependencies) { + package_json.rdependencies = []; + } + + package_json.rdependencies.push(package_to_add); + package_json.rdependencies = [...new Set(package_json.rdependencies)] + fs.writeFileSync(package_json_path, JSON.stringify(package_json, null, 2)); + } else { + console.log("❗️ No package.json file found"); + } +} + +module.exports = { + parsePackageJson, + writePackageJson, + addDependencies, + append_package_json +}; \ No newline at end of file diff --git a/tests/init.test.js b/tests/init.test.js index c946dfc..1e04669 100644 --- a/tests/init.test.js +++ b/tests/init.test.js @@ -7,6 +7,7 @@ const fs = require('fs'); test('init works', async () => { // set a temp dir let temp_dir = path.join(os.tmpdir(), 'coucou') + process.cwd = jest.fn().mockReturnValue(temp_dir); if ( fs.existsSync(temp_dir) diff --git a/tests/install-utils.test.js b/tests/install-utils.test.js index d4ba211..7aa6a58 100644 --- a/tests/install-utils.test.js +++ b/tests/install-utils.test.js @@ -9,7 +9,7 @@ test('installOnePackage works', async () => { let pkgname = 'sudoku'; let url = 'https://cran.r-project.org/src/contrib/sudoku_2.8.tar.gz'; let destination_folder = path.join(os.tmpdir(), 'sudoku'); - + process.cwd = jest.fn().mockReturnValue(destination_folder); if ( fs.existsSync(destination_folder) ) { diff --git a/tests/install.test.js b/tests/install.test.js index 093d31c..e6bb59e 100644 --- a/tests/install.test.js +++ b/tests/install.test.js @@ -8,7 +8,7 @@ const { timeLog } = require('console'); test('installIt works', async () => { let temp_dir = path.join(os.tmpdir(), 'install'); - + process.cwd = jest.fn().mockReturnValue(temp_dir); if ( fs.existsSync(temp_dir) ) { diff --git a/tests/packagejsonmanip.test.js b/tests/packagejsonmanip.test.js new file mode 100644 index 0000000..3e748c8 --- /dev/null +++ b/tests/packagejsonmanip.test.js @@ -0,0 +1,75 @@ +const fs = require('fs'); +const packageJsonManip = require('../src/packagejsonmanip'); +const path = require('path'); +const os = require('os'); + +describe('packagejsonmanip', () => { + describe('parsePackageJson', () => { + it('should parse the package.json file and return an object', () => { + let filePath = path.join(os.tmpdir(), 'parsePackageJson.json'); + let packageJson = { + "name": 'my-package', + "version": '1.0.0', + "dependencies": { + "lodash": '^4.17.21', + "axios": '^0.21.1' + } + }; + fs.writeFileSync(filePath, JSON.stringify(packageJson), 'utf8'); + + let result = packageJsonManip.parsePackageJson(filePath); + + expect(result).toEqual(packageJson); + + fs.unlinkSync(filePath); + }); + }); + + describe('writePackageJson', () => { + it('should write the package.json file with the provided content', () => { + const packageJson = { + "name": 'my-package', + "version": '1.0.0', + "dependencies": { + "lodash": '^4.17.21', + "axios": '^0.21.1' + } + }; + // create a temp json file + let temp_file = path.join(os.tmpdir(), 'writePackageJson.json'); + packageJsonManip.writePackageJson(temp_file, packageJson); + + // expect the file to exist + const result = packageJsonManip.parsePackageJson(temp_file); + expect(result).toEqual(packageJson); + + fs.unlinkSync(temp_file); + }); + }); + + describe('addDependencies', () => { + it('should add the provided dependencies to the package.json file', () => { + const packageJson = { + "name": 'my-package', + "version": '1.0.0', + "dependencies": { + "lodash": '^4.17.21', + "axios": '^0.21.1' + } + }; + // create a temp json file + let temp_file = path.join(os.tmpdir(), 'package.json'); + packageJsonManip.writePackageJson(temp_file, packageJson); + + // add a new dependency + packageJsonManip.addDependencies('golem', temp_file); + + // expect the new dependency to be added + const result = packageJsonManip.parsePackageJson(temp_file); + + expect(result.rdependencies).toContain('golem'); + + fs.unlinkSync(temp_file); + }); + }); +}); \ No newline at end of file