Skip to content
This repository has been archived by the owner on Oct 25, 2023. It is now read-only.

Commit

Permalink
switch to linking package
Browse files Browse the repository at this point in the history
  • Loading branch information
imurchie committed Aug 26, 2019
1 parent 5676cdb commit 176b9c5
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 54 deletions.
23 changes: 13 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
os: linux
dist: xenial
language: node_js
os:
Expand All @@ -22,19 +21,23 @@ env:
- _FORCE_LOGS=1
install:
# on node 12 opencv4nodejs and mjpeg-consumer cannot be installed
# also handle possible travis caching
- if [[ `node --version` != v12* ]]; then
printf "while [ true ]; do\nsleep 30\necho 'Building OpenCV'\ndone" > ping.sh;
bash ping.sh &
echo $! > ping.pid;
npm install -g opencv4nodejs > /dev/null 2>&1;
kill `cat ping.pid`;
if [[ $(npm ls --depth 1 -g opencv4nodejs) =~ "── opencv4nodejs@" ]]; then
printf "while [ true ]; do\nsleep 30\necho 'Building OpenCV'\ndone" > ping.sh;
bash ping.sh &
echo $! > ping.pid;
npm install -g opencv4nodejs > /dev/null 2>&1;
kill `cat ping.pid`;
fi

npm install --no-save mjpeg-consumer;
if [[ $(npm ls --depth 1 -g mjpeg-consumer) =~ "── mjpeg-consumer@" ]]; then
npm install -g mjpeg-consumer;
fi
fi
- npm install
script:
- npm ls -g opencv4nodejs -j
- ls -la "C:\ProgramData\nvs\node\10.15.2\x64\node_modules\opencv4nodejs"
- _FORCE_LOGS=1 npm run e2e-test
- npm run test
- npm run e2e-test
after_success:
- npm run coverage
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as process from './lib/process';
import * as zip from './lib/zip';
import * as imageUtil from './lib/image-util';
import * as mjpeg from './lib/mjpeg';
import * as node from './lib/node';


const { fs } = fsIndex;
Expand All @@ -18,9 +19,9 @@ const { mkdirp } = mkdirpIndex;

export {
tempDir, system, util, fs, cancellableDelay, plist, mkdirp, logger, process,
zip, imageUtil, net, mjpeg
zip, imageUtil, net, mjpeg, node,
};
export default {
tempDir, system, util, fs, cancellableDelay, plist, mkdirp, logger, process,
zip, imageUtil, net, mjpeg
zip, imageUtil, net, mjpeg, node,
};
38 changes: 2 additions & 36 deletions lib/image-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import { Buffer } from 'buffer';
import { PNG } from 'pngjs';
import B from 'bluebird';
import { hasValue } from './util';
import { exec } from 'teen_process';
import path from 'path';
import log from './logger';
import { isWindows } from './system';
import { requirePackage } from './node';


const { MIME_JPEG, MIME_PNG, MIME_BMP } = Jimp;
Expand Down Expand Up @@ -92,38 +90,6 @@ async function getJimpImage (data) {
});
}

/**
* Utility function to extend node functionality, allowing us to require
* modules that are installed globally
*
* @param {string} packageName - the name of the package to be required
* @returns {object} - the package object
*/
async function requirePackage (packageName) {
// see if we can get it locally
try {
log.debug(`Loading local package '${packageName}'`);
return require(packageName);
} catch (err) {
log.debug(`Unable to load local package '${packageName}': ${err.message}`);
}

// find the npm global root
const cmd = isWindows() ? 'npm.cmd' : 'npm';
const {stdout} = await exec(cmd, ['root', '-g'], {timeout: 20000});
const globalNPMRoot = stdout.trim();

// get the global package root
const packageDir = path.join(globalNPMRoot, packageName);
log.debug(`Loading global package '${packageName}' from '${packageDir}'`);

try {
return require(packageDir);
} catch (err) {
throw new Error(`Unable to find global package '${packageName}' at '${packageDir}': ${err.message}`);
}
}

/**
* @throws {Error} If opencv4nodejs module is not installed or cannot be loaded
*/
Expand All @@ -136,7 +102,7 @@ async function initOpenCV () {
try {
cv = await requirePackage('opencv4nodejs');
} catch (err) {
log.debug(`Unable to load 'opencv4nodejs': ${err.message}`);
log.warn(`Unable to load 'opencv4nodejs': ${err.message}`);
}

if (!cv) {
Expand Down
9 changes: 5 additions & 4 deletions lib/mjpeg.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import B from 'bluebird';
import { getJimpImage, MIME_PNG } from './image-util';
import mJpegServer from 'mjpeg-server';
import { Writable } from 'stream';
import { requirePackage } from './node';


// lazy load this, as it might not be available
Expand All @@ -14,10 +15,10 @@ let MJpegConsumer = null;
/**
* @throws {Error} If `mjpeg-consumer` module is not installed or cannot be loaded
*/
function initMJpegConsumer () {
async function initMJpegConsumer () {
if (!MJpegConsumer) {
try {
MJpegConsumer = require('mjpeg-consumer');
MJpegConsumer = await requirePackage('mjpeg-consumer');
} catch (ign) {}
}
if (!MJpegConsumer) {
Expand All @@ -44,8 +45,6 @@ class MJpegStream extends Writable {
constructor (mJpegUrl, errorHandler = _.noop, options = {}) {
super(options);

initMJpegConsumer();

this.errorHandler = errorHandler;
this.url = mJpegUrl;
this.clear();
Expand Down Expand Up @@ -107,6 +106,8 @@ class MJpegStream extends Writable {
// ensure we're not started already
this.stop();

await initMJpegConsumer();

this.consumer = new MJpegConsumer();

// use the deferred pattern so we can wait for the start of the stream
Expand Down
54 changes: 54 additions & 0 deletions lib/node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { isWindows } from './system';
import log from './logger';
import { exec } from 'teen_process';


/**
* Internal utility to link global package to local context
*
* @returns {string} - name of the package to link
* @throws {Error} If the command fails
*/
async function linkGlobalPackage (packageName) {
try {
log.debug(`Linking package '${packageName}'`);
const cmd = isWindows() ? 'npm.cmd' : 'npm';
await exec(cmd, ['link', packageName], {timeout: 20000});
} catch (err) {
const msg = `Unable to load package '${packageName}', linking failed: ${err.message}`;
log.debug(msg);
if (err.stderr) {
// log the stderr if there, but do not add to thrown error as it is
// _very_ verbose
log.debug(err.stderr);
}
throw new Error(msg);
}
}

/**
* Utility function to extend node functionality, allowing us to require
* modules that are installed globally. If the package cannot be required,
* this will attempt to link the package and then re-require it
*
* @param {string} packageName - the name of the package to be required
* @returns {object} - the package object
* @throws {Error} If the package is not found locally or globally
*/
async function requirePackage (packageName) {
try {
log.debug(`Loading local package '${packageName}'`);
return require(packageName);
} catch (err) {
log.debug(`Failed to load package '${packageName}': ${err.message}`);
await linkGlobalPackage(packageName);
}
try {
log.debug(`Retrying load of local package '${packageName}'`);
return require(packageName);
} catch (err) {
log.errorAndThrow(`Unable to load package '${packageName}': ${err.message}`);
}
}

export { requirePackage };
5 changes: 5 additions & 0 deletions test/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"func-names": 0
}
}
4 changes: 2 additions & 2 deletions test/mjpeg-e2e-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ const MJPEG_SERVER_URL = `http://localhost:${MJPEG_SERVER_PORT}`;
describe('MJpeg Stream (e2e)', function () {
let mJpegServer, stream;

before(function () {
before(async function () {
// TODO: remove when buffertools can handle v12
if (process.version.startsWith('v12')) {
return this.skip();
}

mJpegServer = initMJpegServer(MJPEG_SERVER_PORT);
mJpegServer = await initMJpegServer(MJPEG_SERVER_PORT);
});

after(function () {
Expand Down
21 changes: 21 additions & 0 deletions test/node-e2e-specs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { node } from '..';


chai.should();
chai.use(chaiAsPromised);

describe('node utilities', function () {
describe('requirePackage', function () {
it('should be able to require a local package', async function () {
await node.requirePackage('chai').should.not.be.rejected;
});
it('should be able to require a global package', async function () {
await node.requirePackage('npm').should.not.be.rejected;
});
it('should fail to find uninstalled package', async function () {
await node.requirePackage('appium-foo-driver').should.eventually.be.rejectedWith(/Unable to load package/);
});
});
});

0 comments on commit 176b9c5

Please sign in to comment.