Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lnk

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lnk - npm Package Compare versions

Comparing version 0.4.4 to 1.0.0

license

286

index.js
'use strict';
var path = require('path');
var fs = require('fs');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var assign = require('object-assign');
var forEach = require('each-async');
var series = require('array-series');
var pathIsAbsolute = require('path-is-absolute');
const path = require('path');
const arrify = require('arrify');
const rimraf = require('rimraf');
const mkdirp = require('mkdirp');
const pathIsAbsolute = require('path-is-absolute');
const pify = require('pify');
var link = require('./link');
const link = require('./link');
var defaults = {
cwd: undefined,
type: 'default', // 'hard', 'symbolic', 'dir', 'junction' or 'default'
parents: false,
force: false,
log: function noop() {},
var fsStatP = pify(fs.stat);
const rimrafP = pify(rimraf);
const mkdirpP = pify(mkdirp);
const defaults = {
cwd: undefined,
type: 'default', // 'hard', 'symbolic', 'dir', 'junction' or 'default'
parents: false,
force: false,
log: () => {}
};
function preprocessTarget(target, opts) {
// NB symlinks: do not use path.resolve here
if (!pathIsAbsolute(target) && opts.cwd) {
target = path.join(opts.cwd, target);
}
return target;
}
const preprocessTarget = (target, opts) => {
// NB symlinks: do not use path.resolve here
if (opts.cwd && !pathIsAbsolute(target)) {
target = path.join(opts.cwd, target);
}
return target;
};
function generateLinkPath(target, directory, opts) {
var basename = path.basename(target);
var dirname = path.dirname(target);
const generateLinkPath = (target, directory, opts) => {
const basename = path.basename(target);
const dirname = path.dirname(target);
if (opts.cwd) {
directory = path.resolve(opts.cwd, directory);
}
if (opts.cwd) {
directory = path.resolve(opts.cwd, directory);
}
if (opts.parents) {
return path.join(directory, dirname, basename);
} else {
return path.join(directory, basename);
}
}
if (opts.parents) {
return path.join(directory, dirname, basename);
}
function assertSaveOverwrite(target, directory, cb) {
fs.stat(target, function targetStatCb(targetErr, targetStat) {
if (targetErr) {
if (targetErr.code === 'ENOENT' || targetErr.code === 'ELOOP') {
// target and directory cannot be same file
return cb();
}
return cb(targetErr);
}
fs.stat(directory, function directoryStatCb(dirErr, linkStat) {
if (dirErr) {
if (dirErr.code === 'ENOENT' || dirErr.code === 'ELOOP') {
return cb();
}
return cb(dirErr);
}
if (targetStat.ino === linkStat.ino &&
targetStat.dev === linkStat.dev) {
cb(new Error('`' + target + '` and `' + directory + '` are the same'));
} else {
cb();
}
});
});
}
return path.join(directory, basename);
};
function assertSaveOverwriteSync(target, directory) {
var targetStat;
var linkStat;
try {
targetStat = fs.statSync(target);
} catch (err) {
if (err.code === 'ENOENT' || err.code === 'ELOOP') {
// target and directory cannot be same file
return;
}
throw err;
}
try {
linkStat = fs.statSync(directory);
} catch (err) {
if (err.code === 'ENOENT' || err.code === 'ELOOP') {
return;
}
throw err;
}
if (targetStat.ino === linkStat.ino &&
targetStat.dev === linkStat.dev) {
throw new Error('`' + target + '` and `' + directory + '` are the same');
}
}
const assertSaveOverwrite = (target, linkPath) => Promise
.all([fsStatP(target), fsStatP(linkPath)])
.then(stats => {
const targetStat = stats[0];
const linkStat = stats[1];
function assertArgument(arg, argName) {
if (!arg) {
throw new Error(argName + ' required');
}
}
if (targetStat.ino === linkStat.ino && targetStat.dev === linkStat.dev) {
throw new Error(`${target} and ${linkPath} are the same`);
}
})
.catch(err => {
if (err.code === 'ENOENT' || err.code === 'ELOOP') {
// target and linkPath cannot be same file
return;
}
module.exports = function lnk(targets, directory, opts, cb) {
var linkFn;
if (typeof opts === 'function') {
cb = opts;
opts = {};
}
throw err;
});
assertArgument(targets, 'targets');
assertArgument(directory, 'directory');
assertArgument(cb, 'cb');
const assertSaveOverwriteSync = (target, linkPath) => {
try {
const targetStat = fs.statSync(target);
const linkStat = fs.statSync(linkPath);
targets = Array.isArray(targets) ? targets : [targets];
opts = assign({}, defaults, opts);
linkFn = link.get(opts.type);
if (targetStat.ino === linkStat.ino && targetStat.dev === linkStat.dev) {
throw new Error(`${target} and ${linkPath} are the same`);
}
} catch (err) {
if (err.code === 'ENOENT' || err.code === 'ELOOP') {
// target and linkPath cannot be same file
return;
}
function logLnk(level, linkPath, targetPath, done) {
opts.log(level, 'lnk', '%j => %j', linkPath, targetPath);
done();
}
throw err;
}
};
function linkTarget(target, i, done) {
var targetPath = preprocessTarget(target, opts);
var linkPath = generateLinkPath(target, directory, opts);
const assertArgument = (arg, argName) => {
if (!arg) {
throw new Error(argName + ' required');
}
};
series([
mkdirp.bind(mkdirp, path.dirname(linkPath)),
logLnk.bind(null, 'verbose', linkPath, targetPath),
function(next) {
linkFn(targetPath, linkPath, function(err) {
if (err && err.code === 'EEXIST' && opts.force) {
opts.log('silly', 'lnk', 'try to rm -rf %s', linkPath);
series([
assertSaveOverwrite.bind(null, targetPath, linkPath),
rimraf.bind(rimraf, linkPath),
logLnk.bind(null, 'silly', linkPath, targetPath),
linkFn.bind(linkFn, targetPath, linkPath),
], next);
} else {
next(err);
}
});
},
], done);
}
const lnk = (targets, directory, opts) => {
opts = Object.assign({}, defaults, opts);
logLnk('silly', targets, directory, function() {});
forEach(targets, linkTarget, cb);
const linkTarget = target => {
const linkFn = link.get(opts.type);
const targetPath = preprocessTarget(target, opts);
const linkPath = generateLinkPath(target, directory, opts);
return mkdirpP(path.dirname(linkPath))
.then(() => opts.log('verbose', 'lnk', '%j => %j', linkPath, targetPath))
.then(() => linkFn(targetPath, linkPath)
.catch(err => {
if (err.code !== 'EEXIST' || !opts.force) {
throw err;
}
return Promise.resolve()
.then(() => opts.log('silly', 'lnk', 'try to rm -rf %s', linkPath))
.then(() => assertSaveOverwrite(targetPath, linkPath))
.then(() => rimrafP(linkPath))
.then(() => opts.log('silly', 'lnk', '%j => %j', linkPath, targetPath))
.then(() => linkFn(targetPath, linkPath));
}));
};
return Promise.resolve()
.then(() => assertArgument(targets, 'targets'))
.then(() => assertArgument(directory, 'directory'))
.then(() => opts.log('silly', 'lnk', '%j => %j', targets, directory))
.then(() => Promise.all(arrify(targets).map(linkTarget)));
};
module.exports.sync = function lnkSync(targets, directory, opts) {
var linkFn;
const lnkSync = (targets, directory, opts) => {
opts = Object.assign({}, defaults, opts);
assertArgument(targets, 'targets');
assertArgument(directory, 'directory');
const linkTarget = target => {
const linkFn = link.getSync(opts.type);
const targetPath = preprocessTarget(target, opts);
const linkPath = generateLinkPath(target, directory, opts);
targets = Array.isArray(targets) ? targets : [targets];
opts = assign({}, defaults, opts);
linkFn = link.getSync(opts.type);
mkdirp.sync(path.dirname(linkPath));
function linkTarget(target) {
var targetPath = preprocessTarget(target, opts);
var linkPath = generateLinkPath(target, directory, opts);
try {
opts.log('verbose', 'lnk', '%j => %j', linkPath, targetPath);
linkFn(targetPath, linkPath);
} catch (err) {
if (err.code !== 'EEXIST' || !opts.force) {
throw err;
}
mkdirp.sync(path.dirname(linkPath));
try {
opts.log('verbose', 'lnk', '%j => %j', linkPath, targetPath);
linkFn(targetPath, linkPath);
} catch (err) {
if (err.code === 'EEXIST' && opts.force) {
opts.log('silly', 'lnk', 'try to rm -rf %s', linkPath);
assertSaveOverwriteSync(targetPath, linkPath);
rimraf.sync(linkPath);
opts.log('silly', 'lnk', '%j => %j', linkPath, targetPath);
linkFn(targetPath, linkPath);
} else {
throw err;
}
}
}
opts.log('silly', 'lnk', 'try to rm -rf %s', linkPath);
assertSaveOverwriteSync(targetPath, linkPath);
rimraf.sync(linkPath);
opts.log('silly', 'lnk', '%j => %j', linkPath, targetPath);
linkFn(targetPath, linkPath);
}
};
opts.log('silly', 'lnk', '%j => %j', targets, directory);
targets.forEach(linkTarget);
assertArgument(targets, 'targets');
assertArgument(directory, 'directory');
opts.log('silly', 'lnk', '%j => %j', targets, directory);
arrify(targets).forEach(linkTarget);
};
module.exports = lnk;
module.exports.sync = lnkSync;
module.exports.getTypes = () => link.getTypes();
'use strict';
var isWin = process.platform === 'win32';
var fs = require('fs');
var pathLib = require('path');
const pathLib = require('path');
function relative(from, to) {
return pathLib.relative(pathLib.dirname(from), pathLib.resolve(to));
}
const pify = require('pify');
exports.hard = function(target, path, cb) {
fs.link(target, path, cb);
};
const relative = (from, to) => pathLib.relative(pathLib.dirname(from), pathLib.resolve(to));
exports.hardSync = function(target, path) {
return fs.linkSync(target, path);
};
exports.hard = pify(fs.link);
exports.symbolic = function(target, path, cb) {
target = relative(path, target);
fs.symlink(target, path, cb);
};
exports.hardSync = fs.linkSync;
exports.symbolicSync = function(target, path) {
target = relative(path, target);
return fs.symlinkSync(target, path);
};
exports.symbolic = pify((target, path, cb) => {
target = relative(path, target);
fs.symlink(target, path, cb);
});
exports.directory = function(target, path, cb) {
target = relative(path, target);
fs.symlink(target, path, 'dir', cb);
};
exports.symbolicSync = (target, path) => {
target = relative(path, target);
exports.directorySync = function(target, path) {
target = relative(path, target);
return fs.symlinkSync(target, path, 'dir');
return fs.symlinkSync(target, path);
};
exports.junction = function(target, path, cb) {
// junction paths are always absolute
if (!isWin) {
target = relative(path, target);
}
fs.symlink(target, path, 'junction', cb);
exports.directory = pify((target, path, cb) => {
target = relative(path, target);
fs.symlink(target, path, 'dir', cb);
});
exports.directorySync = (target, path) => {
target = relative(path, target);
return fs.symlinkSync(target, path, 'dir');
};
exports.junctionSync = function(target, path) {
// junction paths are always absolute
if (!isWin) {
target = relative(path, target);
}
return fs.symlinkSync(target, path, 'junction');
exports.junction = pify((target, path, cb) => {
target = relative(path, target);
fs.symlink(target, path, 'junction', cb);
});
exports.junctionSync = (target, path) => {
target = relative(path, target);
return fs.symlinkSync(target, path, 'junction');
};
exports.default = function(target, path, cb) {
exports.hard(target, path, function(err) {
if (!err || err.code !== 'EPERM') {
return cb(err);
}
exports.junction(target, path, cb);
});
exports.default = (target, path) => {
return exports.hard(target, path).catch(err => {
if (err.code === 'EPERM') {
return exports.junction(target, path);
}
throw err;
});
};
exports.defaultSync = function(target, path) {
try {
return exports.hardSync(target, path);
} catch (err) {
if (err.code === 'EPERM') {
return exports.junctionSync(target, path);
}
throw err;
}
exports.defaultSync = (target, path) => {
try {
return exports.hardSync(target, path);
} catch (err) {
if (err.code === 'EPERM') {
return exports.junctionSync(target, path);
}
throw err;
}
};
Object.defineProperty(exports, 'get', {
value: function(type) {
var linkFn = exports[type];
value: type => {
var linkFn = exports[type];
if (linkFn) {
return linkFn.bind(exports);
}
if (linkFn) {
return linkFn.bind(exports);
}
throw new Error('unknown link type: `' + type + '`');
},
throw new Error('unknown link type: `' + type + '`');
}
});
Object.defineProperty(exports, 'getSync', {
value: function(type) {
return exports.get(type + 'Sync');
},
value: type => exports.get(type + 'Sync')
});
Object.defineProperty(exports, 'getTypes', {
value: function() {
var suffix = 'Sync';
var types = [];
var name;
value: () => {
const suffix = 'Sync';
const types = [];
for (name in exports) {
if (typeof exports[name] === 'function' &&
name.slice(-suffix.length) !== suffix) {
for (let name in exports) {
if (typeof exports[name] === 'function' && name.slice(-suffix.length) !== suffix) {
types.push(name);
}
}
types.push(name);
}
}
return types;
},
return types;
}
});
{
"name": "lnk",
"version": "0.4.4",
"description": "Create links between files",
"version": "1.0.0",
"description": "Create links between files cross-platform",
"license": "MIT",
"repository": "schnittstabil/lnk",
"keywords": [
"link",
"cross-platform",
"windows",
"symlink",

@@ -20,69 +24,42 @@ "linkSync",

"ln",
"mklink",
"cli"
"mklink"
],
"license": "MIT",
"homepage": "https://github.com/schnittstabil/lnk",
"author": {
"name": "Michael Mayer",
"email": "michael@schnittstabil.de"
"email": "michael@schnittstabil.de",
"url": "schnittstabil.de"
},
"repository": {
"type": "git",
"url": "https://github.com/schnittstabil/lnk.git"
"engines": {
"node": ">=4"
},
"bugs": {
"url": "https://github.com/schnittstabil/lnk/issues"
"dependencies": {
"arrify": "^1.0.1",
"mkdirp": "^0.5.0",
"path-is-absolute": "^1.0.0",
"pify": "^2.3",
"rimraf": "^2.5.4"
},
"devDependencies": {
"ava": "^0.16",
"coveralls": "^2.11",
"execa": "^0.4.0",
"nyc": "^8.3.0",
"rewire": "^2.3",
"uuid": "^2.0",
"xo": "^0.16.0"
},
"main": "index.js",
"bin": {
"lnk": "./cli.js"
"lnk": "./index.js"
},
"config": {
"ghooks": {
"pre-commit": "npm run -s lint",
"pre-push": "npm run pre-push"
}
},
"files": [
"cli.js",
"index.js",
"link.js"
],
"scripts": {
"test": "mocha",
"travis": "npm run pre-push && npm run upload-coveralls",
"pre-push": "npm run cover && istanbul check-coverage && npm run lint",
"cover": "npm run clean-cover && istanbul cover node_modules/mocha/bin/_mocha -- -R spec",
"upload-coveralls": "cat coverage/lcov.info | coveralls",
"lint": "npm -s run lint-js && npm -s run jscs && npm -s run lint-ec",
"lint-js": "globstar -n -- eslint \"*.js\" \"test/**/*.js\"",
"jscs": "jscs .",
"lint-ec": "globstar -n -- editorconfig-tools check \"*.js\" \"test/**/*.js\" \"*.json\" \"*.md\" \".*.yml\"",
"watch-tasks": "npm -s run test && npm -s run lint",
"watch": "gazer-color -p \"*.*\" -p \"test/**/*\" -- npm -s run watch-tasks",
"watch-lint": "gazer-color -p \"*.*\" -p \"test/**/*\" -- npm -s run lint",
"clean-temp": "rimraf temp",
"clean-cover": "rimraf coverage"
},
"devDependencies": {
"coveralls": "^2.11.2",
"del": "^1.1.1",
"eslint": "^0.17.1",
"editorconfig-tools": "^0.1.1",
"gazer-color": "0.0.3",
"ghooks": "^0.3.0",
"globstar": "^1.0.0",
"istanbul": "^0.3.6",
"jscs": "^1.11.3",
"mocha": "^2.1.0",
"mocha-lcov-reporter": "0.0.2",
"rewire": "^2.3.1",
"uuid": "^2.0.1"
},
"dependencies": {
"array-series": "^0.1.5",
"each-async": "^1.1.1",
"mkdirp": "^0.5.0",
"npmlog": "^1.1.0",
"object-assign": "^2.0.0",
"path-is-absolute": "^1.0.0",
"rimraf": "^2.2.8",
"yargs": "^3.4.5"
"test": "xo && nyc ava",
"clean": "rimraf .nyc_output/ coverage/",
"coverage-html": "nyc ava && nyc report --reporter=html"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc