diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..e9bd8f8 --- /dev/null +++ b/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + "es2015" + ], + "plugins": [ + "transform-async-to-generator", + "source-map-support" + ], + "sourceMaps": "inline" +} diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..5820778 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist +benchmark diff --git a/.eslintrc.js b/.eslintrc similarity index 70% rename from .eslintrc.js rename to .eslintrc index ce279f0..9fe82c7 100644 --- a/.eslintrc.js +++ b/.eslintrc @@ -1,13 +1,21 @@ -module.exports = { +{ "env": { "es6": true, "node": true }, "extends": "eslint:recommended", "parserOptions": { - "sourceType": "module" + "sourceType": "module", + "ecmaVersion": 2017 }, "rules": { + "prefer-destructuring": ["error", { + "array": true, + "object": true + }, { + "enforceForRenamedProperties": false + } + ], "indent": [ "error", 4 @@ -33,4 +41,4 @@ module.exports = { "as-needed" ] } -}; +} diff --git a/.travis.yml b/.travis.yml index e8ef988..593d567 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,12 @@ os: - linux - osx osx_image: xcode8 -script: 'npm test' -cache: - directories: - - node_modules +install: + - npm install + - npm run lint + - npm run build +script: + - npm run test-build +# cache: +# directories: +# - node_modules diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4dbdc26 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:4-alpine +RUN apk --no-cache add perl + +ADD package.json /app/package.json +RUN cd /app && npm install + +ADD . /app +WORKDIR /app +RUN npm install + +# ENV NODE_ENV production +CMD ["npm", "run", "build"] diff --git a/README.md b/README.md index bc11a61..9cbf7dd 100644 --- a/README.md +++ b/README.md @@ -718,6 +718,17 @@ context.globalExiftoolConstructor = exiftool.ExiftoolProcess Otherwise, the context will use a stable version which it installs independently. +## Building + +The project is written with ES2017 (`async/await`) and built to be compatible +with lower Node.js versions using `Babel`. `npm run build` will build source +and test files. `npm run test-build` will run transpiled tests against +transpiled sources, whereas `npm t` will run raw tests against raw source files. + +The preset used for transpiling is `es2015`, but without +`transform-es2015-classes`, and with `transform-async-to-generator` and +`source-map-support`. + ## Metadata Metadata is awesome and although it can increase the file size, it preserves diff --git a/appveyor.yml b/appveyor.yml index 6699917..6f1f0d5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,6 +8,9 @@ install: - ps: Install-Product node $env:nodejs_version # install modules - npm install + - npm run lint + # transpile + - npm run build # Post-install test scripts. test_script: @@ -15,7 +18,7 @@ test_script: - node --version - npm --version # run tests - - npm test + - npm run test-build # Don't actually build. build: off diff --git a/dist/src/begin-ready.js b/dist/src/begin-ready.js new file mode 100644 index 0000000..eb408dc --- /dev/null +++ b/dist/src/begin-ready.js @@ -0,0 +1,91 @@ +'use strict'; + +require('source-map-support/register'); + +var _require = require('stream'), + Transform = _require.Transform, + Writable = _require.Writable; + +var restream = require('restream'); + +var BEGIN_READY_RE = /{begin(\d+)}([\s\S]*){ready\1}/g; + +/** + * A transform stream which will mutate data from regex stream into an object + * with commandNumber and data. + * @return {Transfrom} A transform stream into which exiftool process stdout and + * stderr can be piped. It will push objects in form of { cn: commandNumber, d: data } + */ +function createBeginReadyMatchTransformStream() { + var ts = new Transform({ objectMode: true }); + // expecting data from RegexTransformStream with BEGIN_READY_RE + ts._transform = function (match, enc, next) { + var data = { + cn: match[1], + d: match[2].trim() + }; + next(null, data); + }; + return ts; +} + +/** + * A write stream which will maintain a map of commands which are waiting + * to be resolved, where keys are the corresponding resolve promise. The + * stream will expect input from BeginReady Transform Stream. + * @return {Writable} A write stream extended with `addToResolveMap` method. + * @see createBeginReadyTransformStream + */ +function createResolverWriteStream() { + var ws = new Writable({ + objectMode: true + }); + ws._resolveMap = {}; + ws.addToResolveMap = function (commandNumber, resolve) { + if (typeof commandNumber !== 'string') { + throw new Error('commandNumber argument must be a string'); + } + if (typeof resolve !== 'function') { + throw new Error('resolve argument must be a function'); + } + if (this._resolveMap[commandNumber]) { + throw new Error('Command with the same number is already expected'); + } + this._resolveMap[commandNumber] = resolve; + }; + ws._write = function (obj, enc, next) { + var commandNumber = obj.cn; + var data = obj.d; + var resolve = this._resolveMap[commandNumber]; + if (resolve) { + resolve(data); + delete this._resolveMap[commandNumber]; + next(); + } else { + next(new Error('Command with index ' + commandNumber + ' not found')); + } + }; + return ws; +} + +/** + * Setup a pipe from process std stream into resolve write stream + * through regex transform and begin-ready transform streams. + * @param {Readable} rs Readable stream (from exiftool process) + * @return {Writable} A Resolve transform stream. + */ +function setupResolveWriteStreamPipe(rs) { + var rts = restream(BEGIN_READY_RE); + var brmts = createBeginReadyMatchTransformStream(); + var rws = createResolverWriteStream(); + + return rs.pipe(rts).pipe(brmts).pipe(rws); +} + +module.exports = { + createBeginReadyMatchTransformStream: createBeginReadyMatchTransformStream, + createResolverWriteStream: createResolverWriteStream, + BEGIN_READY_RE: BEGIN_READY_RE, + setupResolveWriteStreamPipe: setupResolveWriteStreamPipe +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iZWdpbi1yZWFkeS5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiVHJhbnNmb3JtIiwiV3JpdGFibGUiLCJyZXN0cmVhbSIsIkJFR0lOX1JFQURZX1JFIiwiY3JlYXRlQmVnaW5SZWFkeU1hdGNoVHJhbnNmb3JtU3RyZWFtIiwidHMiLCJvYmplY3RNb2RlIiwiX3RyYW5zZm9ybSIsIm1hdGNoIiwiZW5jIiwibmV4dCIsImRhdGEiLCJjbiIsImQiLCJ0cmltIiwiY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbSIsIndzIiwiX3Jlc29sdmVNYXAiLCJhZGRUb1Jlc29sdmVNYXAiLCJjb21tYW5kTnVtYmVyIiwicmVzb2x2ZSIsIkVycm9yIiwiX3dyaXRlIiwib2JqIiwic2V0dXBSZXNvbHZlV3JpdGVTdHJlYW1QaXBlIiwicnMiLCJydHMiLCJicm10cyIsInJ3cyIsInBpcGUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOzs7O2VBQWlDQSxRQUFRLFFBQVIsQztJQUF6QkMsUyxZQUFBQSxTO0lBQVdDLFEsWUFBQUEsUTs7QUFDbkIsSUFBTUMsV0FBV0gsUUFBUSxVQUFSLENBQWpCOztBQUVBLElBQU1JLGlCQUFpQixpQ0FBdkI7O0FBR0E7Ozs7OztBQU1BLFNBQVNDLG9DQUFULEdBQWdEO0FBQzVDLFFBQU1DLEtBQUssSUFBSUwsU0FBSixDQUFjLEVBQUVNLFlBQVksSUFBZCxFQUFkLENBQVg7QUFDQTtBQUNBRCxPQUFHRSxVQUFILEdBQWdCLFVBQUNDLEtBQUQsRUFBUUMsR0FBUixFQUFhQyxJQUFiLEVBQXNCO0FBQ2xDLFlBQU1DLE9BQU87QUFDVEMsZ0JBQUlKLE1BQU0sQ0FBTixDQURLO0FBRVRLLGVBQUdMLE1BQU0sQ0FBTixFQUFTTSxJQUFUO0FBRk0sU0FBYjtBQUlBSixhQUFLLElBQUwsRUFBV0MsSUFBWDtBQUNILEtBTkQ7QUFPQSxXQUFPTixFQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7QUFPQSxTQUFTVSx5QkFBVCxHQUFxQztBQUNqQyxRQUFNQyxLQUFLLElBQUlmLFFBQUosQ0FBYTtBQUNwQkssb0JBQVk7QUFEUSxLQUFiLENBQVg7QUFHQVUsT0FBR0MsV0FBSCxHQUFpQixFQUFqQjtBQUNBRCxPQUFHRSxlQUFILEdBQXFCLFVBQVNDLGFBQVQsRUFBd0JDLE9BQXhCLEVBQWlDO0FBQ2xELFlBQUksT0FBT0QsYUFBUCxLQUF5QixRQUE3QixFQUF1QztBQUNuQyxrQkFBTSxJQUFJRSxLQUFKLENBQVUseUNBQVYsQ0FBTjtBQUNIO0FBQ0QsWUFBSSxPQUFPRCxPQUFQLEtBQW1CLFVBQXZCLEVBQW1DO0FBQy9CLGtCQUFNLElBQUlDLEtBQUosQ0FBVSxxQ0FBVixDQUFOO0FBQ0g7QUFDRCxZQUFJLEtBQUtKLFdBQUwsQ0FBaUJFLGFBQWpCLENBQUosRUFBcUM7QUFDakMsa0JBQU0sSUFBSUUsS0FBSixDQUFVLGtEQUFWLENBQU47QUFDSDtBQUNELGFBQUtKLFdBQUwsQ0FBaUJFLGFBQWpCLElBQWtDQyxPQUFsQztBQUNILEtBWEQ7QUFZQUosT0FBR00sTUFBSCxHQUFZLFVBQVVDLEdBQVYsRUFBZWQsR0FBZixFQUFvQkMsSUFBcEIsRUFBMEI7QUFDbEMsWUFBTVMsZ0JBQWdCSSxJQUFJWCxFQUExQjtBQUNBLFlBQU1ELE9BQU9ZLElBQUlWLENBQWpCO0FBQ0EsWUFBTU8sVUFBVSxLQUFLSCxXQUFMLENBQWlCRSxhQUFqQixDQUFoQjtBQUNBLFlBQUlDLE9BQUosRUFBYTtBQUNUQSxvQkFBUVQsSUFBUjtBQUNBLG1CQUFPLEtBQUtNLFdBQUwsQ0FBaUJFLGFBQWpCLENBQVA7QUFDQVQ7QUFDSCxTQUpELE1BSU87QUFDSEEsaUJBQUssSUFBSVcsS0FBSix5QkFBZ0NGLGFBQWhDLGdCQUFMO0FBQ0g7QUFDSixLQVhEO0FBWUEsV0FBT0gsRUFBUDtBQUNIOztBQUVEOzs7Ozs7QUFNQSxTQUFTUSwyQkFBVCxDQUFxQ0MsRUFBckMsRUFBeUM7QUFDckMsUUFBTUMsTUFBTXhCLFNBQVNDLGNBQVQsQ0FBWjtBQUNBLFFBQU13QixRQUFRdkIsc0NBQWQ7QUFDQSxRQUFNd0IsTUFBTWIsMkJBQVo7O0FBRUEsV0FBT1UsR0FBR0ksSUFBSCxDQUFRSCxHQUFSLEVBQWFHLElBQWIsQ0FBa0JGLEtBQWxCLEVBQXlCRSxJQUF6QixDQUE4QkQsR0FBOUIsQ0FBUDtBQUNIOztBQUVERSxPQUFPQyxPQUFQLEdBQWlCO0FBQ2IzQiw4RUFEYTtBQUViVyx3REFGYTtBQUdiWixrQ0FIYTtBQUlicUI7QUFKYSxDQUFqQiIsImZpbGUiOiJiZWdpbi1yZWFkeS5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHsgVHJhbnNmb3JtLCBXcml0YWJsZSB9ICA9IHJlcXVpcmUoJ3N0cmVhbScpXG5jb25zdCByZXN0cmVhbSA9IHJlcXVpcmUoJ3Jlc3RyZWFtJylcblxuY29uc3QgQkVHSU5fUkVBRFlfUkUgPSAve2JlZ2luKFxcZCspfShbXFxzXFxTXSope3JlYWR5XFwxfS9nXG5cblxuLyoqXG4gKiBBIHRyYW5zZm9ybSBzdHJlYW0gd2hpY2ggd2lsbCBtdXRhdGUgZGF0YSBmcm9tIHJlZ2V4IHN0cmVhbSBpbnRvIGFuIG9iamVjdFxuICogd2l0aCBjb21tYW5kTnVtYmVyIGFuZCBkYXRhLlxuICogQHJldHVybiB7VHJhbnNmcm9tfSBBIHRyYW5zZm9ybSBzdHJlYW0gaW50byB3aGljaCBleGlmdG9vbCBwcm9jZXNzIHN0ZG91dCBhbmRcbiAqIHN0ZGVyciBjYW4gYmUgcGlwZWQuIEl0IHdpbGwgcHVzaCBvYmplY3RzIGluIGZvcm0gb2YgeyBjbjogY29tbWFuZE51bWJlciwgZDogZGF0YSB9XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJlZ2luUmVhZHlNYXRjaFRyYW5zZm9ybVN0cmVhbSgpIHtcbiAgICBjb25zdCB0cyA9IG5ldyBUcmFuc2Zvcm0oeyBvYmplY3RNb2RlOiB0cnVlIH0pXG4gICAgLy8gZXhwZWN0aW5nIGRhdGEgZnJvbSBSZWdleFRyYW5zZm9ybVN0cmVhbSB3aXRoIEJFR0lOX1JFQURZX1JFXG4gICAgdHMuX3RyYW5zZm9ybSA9IChtYXRjaCwgZW5jLCBuZXh0KSA9PiB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgICBjbjogbWF0Y2hbMV0sXG4gICAgICAgICAgICBkOiBtYXRjaFsyXS50cmltKCksXG4gICAgICAgIH1cbiAgICAgICAgbmV4dChudWxsLCBkYXRhKVxuICAgIH1cbiAgICByZXR1cm4gdHNcbn1cblxuLyoqXG4gKiBBIHdyaXRlIHN0cmVhbSB3aGljaCB3aWxsIG1haW50YWluIGEgbWFwIG9mIGNvbW1hbmRzIHdoaWNoIGFyZSB3YWl0aW5nXG4gKiB0byBiZSByZXNvbHZlZCwgd2hlcmUga2V5cyBhcmUgdGhlIGNvcnJlc3BvbmRpbmcgcmVzb2x2ZSBwcm9taXNlLiBUaGVcbiAqIHN0cmVhbSB3aWxsIGV4cGVjdCBpbnB1dCBmcm9tIEJlZ2luUmVhZHkgVHJhbnNmb3JtIFN0cmVhbS5cbiAqIEByZXR1cm4ge1dyaXRhYmxlfSBBIHdyaXRlIHN0cmVhbSBleHRlbmRlZCB3aXRoIGBhZGRUb1Jlc29sdmVNYXBgIG1ldGhvZC5cbiAqIEBzZWUgY3JlYXRlQmVnaW5SZWFkeVRyYW5zZm9ybVN0cmVhbVxuICovXG5mdW5jdGlvbiBjcmVhdGVSZXNvbHZlcldyaXRlU3RyZWFtKCkge1xuICAgIGNvbnN0IHdzID0gbmV3IFdyaXRhYmxlKHtcbiAgICAgICAgb2JqZWN0TW9kZTogdHJ1ZSxcbiAgICB9KVxuICAgIHdzLl9yZXNvbHZlTWFwID0ge31cbiAgICB3cy5hZGRUb1Jlc29sdmVNYXAgPSBmdW5jdGlvbihjb21tYW5kTnVtYmVyLCByZXNvbHZlKSB7XG4gICAgICAgIGlmICh0eXBlb2YgY29tbWFuZE51bWJlciAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY29tbWFuZE51bWJlciBhcmd1bWVudCBtdXN0IGJlIGEgc3RyaW5nJylcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHJlc29sdmUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncmVzb2x2ZSBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9yZXNvbHZlTWFwW2NvbW1hbmROdW1iZXJdKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbW1hbmQgd2l0aCB0aGUgc2FtZSBudW1iZXIgaXMgYWxyZWFkeSBleHBlY3RlZCcpXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVzb2x2ZU1hcFtjb21tYW5kTnVtYmVyXSA9IHJlc29sdmVcbiAgICB9XG4gICAgd3MuX3dyaXRlID0gZnVuY3Rpb24gKG9iaiwgZW5jLCBuZXh0KSB7XG4gICAgICAgIGNvbnN0IGNvbW1hbmROdW1iZXIgPSBvYmouY25cbiAgICAgICAgY29uc3QgZGF0YSA9IG9iai5kXG4gICAgICAgIGNvbnN0IHJlc29sdmUgPSB0aGlzLl9yZXNvbHZlTWFwW2NvbW1hbmROdW1iZXJdXG4gICAgICAgIGlmIChyZXNvbHZlKSB7XG4gICAgICAgICAgICByZXNvbHZlKGRhdGEpXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fcmVzb2x2ZU1hcFtjb21tYW5kTnVtYmVyXVxuICAgICAgICAgICAgbmV4dCgpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXh0KG5ldyBFcnJvcihgQ29tbWFuZCB3aXRoIGluZGV4ICR7Y29tbWFuZE51bWJlcn0gbm90IGZvdW5kYCkpXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHdzXG59XG5cbi8qKlxuICogU2V0dXAgYSBwaXBlIGZyb20gcHJvY2VzcyBzdGQgc3RyZWFtIGludG8gcmVzb2x2ZSB3cml0ZSBzdHJlYW1cbiAqIHRocm91Z2ggcmVnZXggdHJhbnNmb3JtIGFuZCBiZWdpbi1yZWFkeSB0cmFuc2Zvcm0gc3RyZWFtcy5cbiAqIEBwYXJhbSB7UmVhZGFibGV9IHJzIFJlYWRhYmxlIHN0cmVhbSAoZnJvbSBleGlmdG9vbCBwcm9jZXNzKVxuICogQHJldHVybiB7V3JpdGFibGV9IEEgUmVzb2x2ZSB0cmFuc2Zvcm0gc3RyZWFtLlxuICovXG5mdW5jdGlvbiBzZXR1cFJlc29sdmVXcml0ZVN0cmVhbVBpcGUocnMpIHtcbiAgICBjb25zdCBydHMgPSByZXN0cmVhbShCRUdJTl9SRUFEWV9SRSlcbiAgICBjb25zdCBicm10cyA9IGNyZWF0ZUJlZ2luUmVhZHlNYXRjaFRyYW5zZm9ybVN0cmVhbSgpXG4gICAgY29uc3QgcndzID0gY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbSgpXG5cbiAgICByZXR1cm4gcnMucGlwZShydHMpLnBpcGUoYnJtdHMpLnBpcGUocndzKVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjcmVhdGVCZWdpblJlYWR5TWF0Y2hUcmFuc2Zvcm1TdHJlYW0sXG4gICAgY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbSxcbiAgICBCRUdJTl9SRUFEWV9SRSxcbiAgICBzZXR1cFJlc29sdmVXcml0ZVN0cmVhbVBpcGUsXG59XG4iXX0= \ No newline at end of file diff --git a/dist/src/execute-with-rs.js b/dist/src/execute-with-rs.js new file mode 100644 index 0000000..a64e0c9 --- /dev/null +++ b/dist/src/execute-with-rs.js @@ -0,0 +1,43 @@ +'use strict'; + +require('source-map-support/register'); + +var wrote = require('wrote'); + +var _require = require('stream'), + Readable = _require.Readable; + +/** + * Create temp file for rs, execute exiftool command, then erase file + * @param {Readable} rs a read stream + * @param {string[]} args Arguments + * @param {function} executeCommand function which is responsible for executing the command + */ + + +function executeWithRs(rs, args, executeCommand) { + if (!(rs instanceof Readable)) { + return Promise.reject(new Error('Please pass a readable stream')); + } + if (typeof executeCommand !== 'function') { + return Promise.reject(new Error('executeCommand must be a function')); + } + var ws = void 0; + return wrote() // temp file will be created + .then(function (res) { + ws = res; + rs.pipe(ws); + return executeCommand(ws.path, args); + }).then(function (res) { + return wrote.erase(ws).then(function () { + return res; + }); + }, function (err) { + return wrote.erase(ws).then(function () { + throw err; + }); + }); +} + +module.exports = executeWithRs; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leGVjdXRlLXdpdGgtcnMuanMiXSwibmFtZXMiOlsid3JvdGUiLCJyZXF1aXJlIiwiUmVhZGFibGUiLCJleGVjdXRlV2l0aFJzIiwicnMiLCJhcmdzIiwiZXhlY3V0ZUNvbW1hbmQiLCJQcm9taXNlIiwicmVqZWN0IiwiRXJyb3IiLCJ3cyIsInRoZW4iLCJyZXMiLCJwaXBlIiwicGF0aCIsImVyYXNlIiwiZXJyIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQU1BLFFBQVFDLFFBQVEsT0FBUixDQUFkOztlQUNxQkEsUUFBUSxRQUFSLEM7SUFBYkMsUSxZQUFBQSxROztBQUVSOzs7Ozs7OztBQU1BLFNBQVNDLGFBQVQsQ0FBdUJDLEVBQXZCLEVBQTJCQyxJQUEzQixFQUFpQ0MsY0FBakMsRUFBaUQ7QUFDN0MsUUFBSSxFQUFFRixjQUFjRixRQUFoQixDQUFKLEVBQStCO0FBQzNCLGVBQU9LLFFBQVFDLE1BQVIsQ0FBZSxJQUFJQyxLQUFKLENBQVUsK0JBQVYsQ0FBZixDQUFQO0FBQ0g7QUFDRCxRQUFJLE9BQU9ILGNBQVAsS0FBMEIsVUFBOUIsRUFBMEM7QUFDdEMsZUFBT0MsUUFBUUMsTUFBUixDQUFlLElBQUlDLEtBQUosQ0FBVSxtQ0FBVixDQUFmLENBQVA7QUFDSDtBQUNELFFBQUlDLFdBQUo7QUFDQSxXQUFPVixRQUFRO0FBQVIsS0FDRlcsSUFERSxDQUNHLFVBQUNDLEdBQUQsRUFBUztBQUNYRixhQUFLRSxHQUFMO0FBQ0FSLFdBQUdTLElBQUgsQ0FBUUgsRUFBUjtBQUNBLGVBQU9KLGVBQWVJLEdBQUdJLElBQWxCLEVBQXdCVCxJQUF4QixDQUFQO0FBQ0gsS0FMRSxFQU1GTSxJQU5FLENBTUcsVUFBQ0MsR0FBRCxFQUFTO0FBQ1gsZUFBT1osTUFBTWUsS0FBTixDQUFZTCxFQUFaLEVBQ0ZDLElBREUsQ0FDRyxZQUFNO0FBQ1IsbUJBQU9DLEdBQVA7QUFDSCxTQUhFLENBQVA7QUFJSCxLQVhFLEVBV0EsVUFBQ0ksR0FBRCxFQUFTO0FBQ1IsZUFBT2hCLE1BQU1lLEtBQU4sQ0FBWUwsRUFBWixFQUNGQyxJQURFLENBQ0csWUFBTTtBQUNSLGtCQUFNSyxHQUFOO0FBQ0gsU0FIRSxDQUFQO0FBSUgsS0FoQkUsQ0FBUDtBQWlCSDs7QUFFREMsT0FBT0MsT0FBUCxHQUFpQmYsYUFBakIiLCJmaWxlIjoiZXhlY3V0ZS13aXRoLXJzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3Qgd3JvdGUgPSByZXF1aXJlKCd3cm90ZScpXG5jb25zdCB7IFJlYWRhYmxlIH0gPSByZXF1aXJlKCdzdHJlYW0nKVxuXG4vKipcbiAqIENyZWF0ZSB0ZW1wIGZpbGUgZm9yIHJzLCBleGVjdXRlIGV4aWZ0b29sIGNvbW1hbmQsIHRoZW4gZXJhc2UgZmlsZVxuICogQHBhcmFtIHtSZWFkYWJsZX0gcnMgYSByZWFkIHN0cmVhbVxuICogQHBhcmFtIHtzdHJpbmdbXX0gYXJncyBBcmd1bWVudHNcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGV4ZWN1dGVDb21tYW5kIGZ1bmN0aW9uIHdoaWNoIGlzIHJlc3BvbnNpYmxlIGZvciBleGVjdXRpbmcgdGhlIGNvbW1hbmRcbiAqL1xuZnVuY3Rpb24gZXhlY3V0ZVdpdGhScyhycywgYXJncywgZXhlY3V0ZUNvbW1hbmQpIHtcbiAgICBpZiAoIShycyBpbnN0YW5jZW9mIFJlYWRhYmxlKSkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdQbGVhc2UgcGFzcyBhIHJlYWRhYmxlIHN0cmVhbScpKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIGV4ZWN1dGVDb21tYW5kICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ2V4ZWN1dGVDb21tYW5kIG11c3QgYmUgYSBmdW5jdGlvbicpKVxuICAgIH1cbiAgICBsZXQgd3NcbiAgICByZXR1cm4gd3JvdGUoKSAvLyB0ZW1wIGZpbGUgd2lsbCBiZSBjcmVhdGVkXG4gICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgIHdzID0gcmVzXG4gICAgICAgICAgICBycy5waXBlKHdzKVxuICAgICAgICAgICAgcmV0dXJuIGV4ZWN1dGVDb21tYW5kKHdzLnBhdGgsIGFyZ3MpXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB3cm90ZS5lcmFzZSh3cylcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gd3JvdGUuZXJhc2Uod3MpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnJcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9KVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGV4ZWN1dGVXaXRoUnNcbiJdfQ== \ No newline at end of file diff --git a/dist/src/index.js b/dist/src/index.js new file mode 100644 index 0000000..b8f1e73 --- /dev/null +++ b/dist/src/index.js @@ -0,0 +1,318 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +require('source-map-support/register'); + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var EventEmitter = require('events'); +var lib = require('./lib'); +var beginReady = require('./begin-ready'); +var executeWithRs = require('./execute-with-rs'); + +var EXIFTOOL_PATH = 'exiftool'; + +var events = { + OPEN: 'exiftool_opened', + EXIT: 'exiftool_exit' +}; + +var ExiftoolProcess = function (_EventEmitter) { + _inherits(ExiftoolProcess, _EventEmitter); + + /** + * Create an instance of ExiftoolProcess class. + * @param {string} [bin="exiftool"] path to executable + */ + function ExiftoolProcess(bin) { + _classCallCheck(this, ExiftoolProcess); + + var _this = _possibleConstructorReturn(this, (ExiftoolProcess.__proto__ || Object.getPrototypeOf(ExiftoolProcess)).call(this)); + + _this._bin = lib.isString(bin) ? bin : EXIFTOOL_PATH; + _this._process = undefined; + _this._open = false; + return _this; + } + + /** + * Close the exiftool process by passing -stay_open false. + * @returns {Promise} a promise to stop the process. + */ + + + _createClass(ExiftoolProcess, [{ + key: 'close', + value: function close() { + if (!this._open) { + return Promise.reject(new Error('Exiftool process is not open')); + } + return lib.close(this._process); + } + }, { + key: '_assignEncoding', + value: function _assignEncoding(encoding) { + var _encoding = void 0; + if (encoding === null) { + _encoding = undefined; + } else if (lib.isString(encoding)) { + _encoding = encoding; + } else { + _encoding = 'utf8'; + } + this._encoding = _encoding; + } + /** + * Spawn exiftool process with -stay_open True -@ - arguments. + * Options can be passed as the first argument instead of encoding. + * @param {string} [encoding="utf8"] Encoding with which to read from and + * write to streams. pass null to not use encoding, utf8 otherwise + * @param {object} [options] options to pass to the spawn method + * @returns {Promise.} A promise to spawn exiftool in stay_open + * mode, resolved with pid. + */ + + }, { + key: 'open', + value: function () { + var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(encoding, options) { + var _encoding, _options, exiftoolProcess; + + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _encoding = encoding; + _options = options; + // if encoding is not a string and options are not given, treat it as options + + if (options === undefined && typeof encoding !== 'string') { + _encoding = undefined; + _options = encoding; + } + this._assignEncoding(_encoding); + + if (!this._open) { + _context.next = 6; + break; + } + + throw new Error('Exiftool process is already open'); + + case 6: + _context.next = 8; + return lib.spawn(this._bin, _options); + + case 8: + exiftoolProcess = _context.sent; + + //console.log(`Started exiftool process %s`, process.pid); + this.emit(events.OPEN, exiftoolProcess.pid); + this._process = exiftoolProcess; + + this._process.on('exit', this._exitListener.bind(this)); + + if (lib.isReadable(this._process.stdout)) { + _context.next = 15; + break; + } + + lib.killProcess(this._process); + throw new Error('Process was not spawned with a readable stdout, check stdio options.'); + + case 15: + if (lib.isWritable(this._process.stdin)) { + _context.next = 18; + break; + } + + lib.killProcess(this._process); + throw new Error('Process was not spawned with a writable stdin, check stdio options.'); + + case 18: + + // if process was spawned, stderr is readable (see lib/spawn) + + this._process.stdout.setEncoding(this._encoding); + this._process.stderr.setEncoding(this._encoding); + + // resolve-write streams + this._stdoutResolveWs = beginReady.setupResolveWriteStreamPipe(this._process.stdout); + this._stderrResolveWs = beginReady.setupResolveWriteStreamPipe(this._process.stderr); + + // handle errors so that Node does not crash + this._stdoutResolveWs.on('error', console.error); // eslint-disable-line no-console + this._stderrResolveWs.on('error', console.error); // eslint-disable-line no-console + + // debug + // exiftoolProcess.stdout.pipe(process.stdout) + // exiftoolProcess.stderr.pipe(process.stderr) + + this._open = true; + + return _context.abrupt('return', exiftoolProcess.pid); + + case 26: + case 'end': + return _context.stop(); + } + } + }, _callee, this); + })); + + function open(_x, _x2) { + return _ref.apply(this, arguments); + } + + return open; + }() + }, { + key: '_exitListener', + value: function _exitListener() { + // console.log('exiftool process exit') + this.emit(events.EXIT); + this._open = false; // try to re-spawn? + } + + /** + * Checks if process is opens. + * @returns {boolean} true if open and false otherwise. + */ + + }, { + key: '_executeCommand', + value: function () { + var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(command, args, argsNoSplit, debug) { + var proc; + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + if (this._open) { + _context2.next = 2; + break; + } + + throw new Error('exiftool is not open'); + + case 2: + if (!(this._process.signalCode === 'SIGTERM')) { + _context2.next = 4; + break; + } + + throw new Error('Could not connect to the exiftool process'); + + case 4: + proc = debug === true ? process : this._process; + return _context2.abrupt('return', lib.executeCommand(proc, this._stdoutResolveWs, this._stderrResolveWs, command, args, argsNoSplit, this._encoding)); + + case 6: + case 'end': + return _context2.stop(); + } + } + }, _callee2, this); + })); + + function _executeCommand(_x3, _x4, _x5, _x6) { + return _ref2.apply(this, arguments); + } + + return _executeCommand; + }() + + /** + * Read metadata of a file or directory. + * @param {string|Readable} file path to the file or directory, or a + * readable stream + * @param {string[]} args any additional arguments, e.g., ['Orientation#'] + * to report Orientation only, or ['-FileSize'] to exclude FileSize + * @returns {Promise.<{data: object[]|null, error: string|null}>} a promise + * resolved with parsed stdout and stderr. + */ + + }, { + key: 'readMetadata', + value: function readMetadata(file, args) { + if (lib.isReadable(file)) { + return executeWithRs(file, args, this._executeCommand.bind(this)); + } + return this._executeCommand(file, args); + } + + /** + * Write metadata to a file or directory. + * @param {string} file path to the file or directory + * @param {object} data data to write, with keys as tags + * @param {string[]} args additional arguments, e.g., ['overwrite_original'] + * @param {boolean} debug whether to print to stdout + * @returns {Promise.<{{data, error}}>} A promise to write metadata, + * resolved with data from stdout and stderr. + */ + + }, { + key: 'writeMetadata', + value: function () { + var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(file, data, args, debug) { + var writeArgs; + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + if (lib.isString(file)) { + _context3.next = 2; + break; + } + + throw new Error('File must be a string'); + + case 2: + if (lib.checkDataObject(data)) { + _context3.next = 4; + break; + } + + throw new Error('Data argument is not an object'); + + case 4: + writeArgs = lib.mapDataToTagArray(data); + return _context3.abrupt('return', this._executeCommand(file, args, writeArgs, debug)); + + case 6: + case 'end': + return _context3.stop(); + } + } + }, _callee3, this); + })); + + function writeMetadata(_x7, _x8, _x9, _x10) { + return _ref3.apply(this, arguments); + } + + return writeMetadata; + }() + }, { + key: 'isOpen', + get: function get() { + return this._open; + } + }]); + + return ExiftoolProcess; +}(EventEmitter); + +module.exports = { + ExiftoolProcess: ExiftoolProcess, + EXIFTOOL_PATH: EXIFTOOL_PATH, + events: events +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6WyJFdmVudEVtaXR0ZXIiLCJyZXF1aXJlIiwibGliIiwiYmVnaW5SZWFkeSIsImV4ZWN1dGVXaXRoUnMiLCJFWElGVE9PTF9QQVRIIiwiZXZlbnRzIiwiT1BFTiIsIkVYSVQiLCJFeGlmdG9vbFByb2Nlc3MiLCJiaW4iLCJfYmluIiwiaXNTdHJpbmciLCJfcHJvY2VzcyIsInVuZGVmaW5lZCIsIl9vcGVuIiwiUHJvbWlzZSIsInJlamVjdCIsIkVycm9yIiwiY2xvc2UiLCJlbmNvZGluZyIsIl9lbmNvZGluZyIsIm9wdGlvbnMiLCJfb3B0aW9ucyIsIl9hc3NpZ25FbmNvZGluZyIsInNwYXduIiwiZXhpZnRvb2xQcm9jZXNzIiwiZW1pdCIsInBpZCIsIm9uIiwiX2V4aXRMaXN0ZW5lciIsImJpbmQiLCJpc1JlYWRhYmxlIiwic3Rkb3V0Iiwia2lsbFByb2Nlc3MiLCJpc1dyaXRhYmxlIiwic3RkaW4iLCJzZXRFbmNvZGluZyIsInN0ZGVyciIsIl9zdGRvdXRSZXNvbHZlV3MiLCJzZXR1cFJlc29sdmVXcml0ZVN0cmVhbVBpcGUiLCJfc3RkZXJyUmVzb2x2ZVdzIiwiY29uc29sZSIsImVycm9yIiwiY29tbWFuZCIsImFyZ3MiLCJhcmdzTm9TcGxpdCIsImRlYnVnIiwic2lnbmFsQ29kZSIsInByb2MiLCJwcm9jZXNzIiwiZXhlY3V0ZUNvbW1hbmQiLCJmaWxlIiwiX2V4ZWN1dGVDb21tYW5kIiwiZGF0YSIsImNoZWNrRGF0YU9iamVjdCIsIndyaXRlQXJncyIsIm1hcERhdGFUb1RhZ0FycmF5IiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQSxJQUFNQSxlQUFlQyxRQUFRLFFBQVIsQ0FBckI7QUFDQSxJQUFNQyxNQUFNRCxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQU1FLGFBQWFGLFFBQVEsZUFBUixDQUFuQjtBQUNBLElBQU1HLGdCQUFnQkgsUUFBUSxtQkFBUixD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SSxFQUFNVCxJLEVBQU1FLEs7Ozs7OztvQ0FDN0I3QyxJQUFJVSxRQUFKLENBQWF3QyxJQUFiLEM7Ozs7O3NDQUNLLElBQUlsQyxLQUFKLENBQVUsdUJBQVYsQzs7O29DQUVMaEIsSUFBSXFELGVBQUosQ0FBb0JELElBQXBCLEM7Ozs7O3NDQUNLLElBQUlwQyxLQUFKLENBQVUsZ0NBQVYsQzs7O0FBR0pzQyx5QyxHQUFZdEQsSUFBSXVELGlCQUFKLENBQXNCSCxJQUF0QixDO2tFQUNYLEtBQUtELGVBQUwsQ0FBcUJELElBQXJCLEVBQTJCUCxJQUEzQixFQUFpQ1csU0FBakMsRUFBNENULEtBQTVDLEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs0QkFwREU7QUFDVCxtQkFBTyxLQUFLaEMsS0FBWjtBQUNIOzs7O0VBeEd5QmYsWTs7QUE4SjlCMEQsT0FBT0MsT0FBUCxHQUFpQjtBQUNibEQsb0NBRGE7QUFFYkosZ0NBRmE7QUFHYkM7QUFIYSxDQUFqQiIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ2V2ZW50cycpXG5jb25zdCBsaWIgPSByZXF1aXJlKCcuL2xpYicpXG5jb25zdCBiZWdpblJlYWR5ID0gcmVxdWlyZSgnLi9iZWdpbi1yZWFkeScpXG5jb25zdCBleGVjdXRlV2l0aFJzID0gcmVxdWlyZSgnLi9leGVjdXRlLXdpdGgtcnMnKVxuXG5jb25zdCBFWElGVE9PTF9QQVRIID0gJ2V4aWZ0b29sJ1xuXG5jb25zdCBldmVudHMgPSB7XG4gICAgT1BFTjogJ2V4aWZ0b29sX29wZW5lZCcsXG4gICAgRVhJVDogJ2V4aWZ0b29sX2V4aXQnLFxufVxuXG5jbGFzcyBFeGlmdG9vbFByb2Nlc3MgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhbiBpbnN0YW5jZSBvZiBFeGlmdG9vbFByb2Nlc3MgY2xhc3MuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtiaW49XCJleGlmdG9vbFwiXSBwYXRoIHRvIGV4ZWN1dGFibGVcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihiaW4pIHtcbiAgICAgICAgc3VwZXIoKVxuICAgICAgICB0aGlzLl9iaW4gPSBsaWIuaXNTdHJpbmcoYmluKSA/IGJpbiA6IEVYSUZUT09MX1BBVEhcbiAgICAgICAgdGhpcy5fcHJvY2VzcyA9IHVuZGVmaW5lZFxuICAgICAgICB0aGlzLl9vcGVuID0gZmFsc2VcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbG9zZSB0aGUgZXhpZnRvb2wgcHJvY2VzcyBieSBwYXNzaW5nIC1zdGF5X29wZW4gZmFsc2UuXG4gICAgICogQHJldHVybnMge1Byb21pc2V9IGEgcHJvbWlzZSB0byBzdG9wIHRoZSBwcm9jZXNzLlxuICAgICAqL1xuICAgIGNsb3NlKCkge1xuICAgICAgICBpZiAoIXRoaXMuX29wZW4pIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ0V4aWZ0b29sIHByb2Nlc3MgaXMgbm90IG9wZW4nKSlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGliLmNsb3NlKHRoaXMuX3Byb2Nlc3MpXG4gICAgfVxuXG4gICAgX2Fzc2lnbkVuY29kaW5nKGVuY29kaW5nKSB7XG4gICAgICAgIGxldCBfZW5jb2RpbmdcbiAgICAgICAgaWYgKGVuY29kaW5nID09PSBudWxsKSB7XG4gICAgICAgICAgICBfZW5jb2RpbmcgPSB1bmRlZmluZWRcbiAgICAgICAgfSBlbHNlIGlmIChsaWIuaXNTdHJpbmcoZW5jb2RpbmcpKSB7XG4gICAgICAgICAgICBfZW5jb2RpbmcgPSBlbmNvZGluZ1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgX2VuY29kaW5nID0gJ3V0ZjgnXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fZW5jb2RpbmcgPSBfZW5jb2RpbmdcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3Bhd24gZXhpZnRvb2wgcHJvY2VzcyB3aXRoIC1zdGF5X29wZW4gVHJ1ZSAtQCAtIGFyZ3VtZW50cy5cbiAgICAgKiBPcHRpb25zIGNhbiBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IGluc3RlYWQgb2YgZW5jb2RpbmcuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtlbmNvZGluZz1cInV0ZjhcIl0gRW5jb2Rpbmcgd2l0aCB3aGljaCB0byByZWFkIGZyb20gYW5kXG4gICAgICogd3JpdGUgdG8gc3RyZWFtcy4gcGFzcyBudWxsIHRvIG5vdCB1c2UgZW5jb2RpbmcsIHV0Zjggb3RoZXJ3aXNlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXSBvcHRpb25zIHRvIHBhc3MgdG8gdGhlIHNwYXduIG1ldGhvZFxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlLjxudW1iZXI+fSBBIHByb21pc2UgdG8gc3Bhd24gZXhpZnRvb2wgaW4gc3RheV9vcGVuXG4gICAgICogbW9kZSwgcmVzb2x2ZWQgd2l0aCBwaWQuXG4gICAgICovXG4gICAgYXN5bmMgb3BlbihlbmNvZGluZywgb3B0aW9ucykge1xuICAgICAgICBsZXQgX2VuY29kaW5nID0gZW5jb2RpbmdcbiAgICAgICAgbGV0IF9vcHRpb25zID0gb3B0aW9uc1xuICAgICAgICAvLyBpZiBlbmNvZGluZyBpcyBub3QgYSBzdHJpbmcgYW5kIG9wdGlvbnMgYXJlIG5vdCBnaXZlbiwgdHJlYXQgaXQgYXMgb3B0aW9uc1xuICAgICAgICBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIF9lbmNvZGluZyA9IHVuZGVmaW5lZFxuICAgICAgICAgICAgX29wdGlvbnMgPSBlbmNvZGluZ1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2Fzc2lnbkVuY29kaW5nKF9lbmNvZGluZylcbiAgICAgICAgaWYgKHRoaXMuX29wZW4pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRXhpZnRvb2wgcHJvY2VzcyBpcyBhbHJlYWR5IG9wZW4nKVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGV4aWZ0b29sUHJvY2VzcyA9IGF3YWl0IGxpYi5zcGF3bih0aGlzLl9iaW4sIF9vcHRpb25zKVxuICAgICAgICAvL2NvbnNvbGUubG9nKGBTdGFydGVkIGV4aWZ0b29sIHByb2Nlc3MgJXNgLCBwcm9jZXNzLnBpZCk7XG4gICAgICAgIHRoaXMuZW1pdChldmVudHMuT1BFTiwgZXhpZnRvb2xQcm9jZXNzLnBpZClcbiAgICAgICAgdGhpcy5fcHJvY2VzcyA9IGV4aWZ0b29sUHJvY2Vzc1xuXG4gICAgICAgIHRoaXMuX3Byb2Nlc3Mub24oJ2V4aXQnLCB0aGlzLl9leGl0TGlzdGVuZXIuYmluZCh0aGlzKSlcbiAgICAgICAgaWYgKCFsaWIuaXNSZWFkYWJsZSh0aGlzLl9wcm9jZXNzLnN0ZG91dCkpIHtcbiAgICAgICAgICAgIGxpYi5raWxsUHJvY2Vzcyh0aGlzLl9wcm9jZXNzKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQcm9jZXNzIHdhcyBub3Qgc3Bhd25lZCB3aXRoIGEgcmVhZGFibGUgc3Rkb3V0LCBjaGVjayBzdGRpbyBvcHRpb25zLicpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFsaWIuaXNXcml0YWJsZSh0aGlzLl9wcm9jZXNzLnN0ZGluKSkge1xuICAgICAgICAgICAgbGliLmtpbGxQcm9jZXNzKHRoaXMuX3Byb2Nlc3MpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Byb2Nlc3Mgd2FzIG5vdCBzcGF3bmVkIHdpdGggYSB3cml0YWJsZSBzdGRpbiwgY2hlY2sgc3RkaW8gb3B0aW9ucy4nKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgcHJvY2VzcyB3YXMgc3Bhd25lZCwgc3RkZXJyIGlzIHJlYWRhYmxlIChzZWUgbGliL3NwYXduKVxuXG4gICAgICAgIHRoaXMuX3Byb2Nlc3Muc3Rkb3V0LnNldEVuY29kaW5nKHRoaXMuX2VuY29kaW5nKVxuICAgICAgICB0aGlzLl9wcm9jZXNzLnN0ZGVyci5zZXRFbmNvZGluZyh0aGlzLl9lbmNvZGluZylcblxuICAgICAgICAvLyByZXNvbHZlLXdyaXRlIHN0cmVhbXNcbiAgICAgICAgdGhpcy5fc3Rkb3V0UmVzb2x2ZVdzID0gYmVnaW5SZWFkeS5zZXR1cFJlc29sdmVXcml0ZVN0cmVhbVBpcGUodGhpcy5fcHJvY2Vzcy5zdGRvdXQpXG4gICAgICAgIHRoaXMuX3N0ZGVyclJlc29sdmVXcyA9IGJlZ2luUmVhZHkuc2V0dXBSZXNvbHZlV3JpdGVTdHJlYW1QaXBlKHRoaXMuX3Byb2Nlc3Muc3RkZXJyKVxuXG4gICAgICAgIC8vIGhhbmRsZSBlcnJvcnMgc28gdGhhdCBOb2RlIGRvZXMgbm90IGNyYXNoXG4gICAgICAgIHRoaXMuX3N0ZG91dFJlc29sdmVXcy5vbignZXJyb3InLCBjb25zb2xlLmVycm9yKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgdGhpcy5fc3RkZXJyUmVzb2x2ZVdzLm9uKCdlcnJvcicsIGNvbnNvbGUuZXJyb3IpIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZVxuXG4gICAgICAgIC8vIGRlYnVnXG4gICAgICAgIC8vIGV4aWZ0b29sUHJvY2Vzcy5zdGRvdXQucGlwZShwcm9jZXNzLnN0ZG91dClcbiAgICAgICAgLy8gZXhpZnRvb2xQcm9jZXNzLnN0ZGVyci5waXBlKHByb2Nlc3Muc3RkZXJyKVxuXG4gICAgICAgIHRoaXMuX29wZW4gPSB0cnVlXG5cbiAgICAgICAgcmV0dXJuIGV4aWZ0b29sUHJvY2Vzcy5waWRcbiAgICB9XG5cbiAgICBfZXhpdExpc3RlbmVyKCkge1xuICAgICAgICAvLyBjb25zb2xlLmxvZygnZXhpZnRvb2wgcHJvY2VzcyBleGl0JylcbiAgICAgICAgdGhpcy5lbWl0KGV2ZW50cy5FWElUKVxuICAgICAgICB0aGlzLl9vcGVuID0gZmFsc2UgLy8gdHJ5IHRvIHJlLXNwYXduP1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBwcm9jZXNzIGlzIG9wZW5zLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIG9wZW4gYW5kIGZhbHNlIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBnZXQgaXNPcGVuKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3BlblxuICAgIH1cblxuICAgIGFzeW5jIF9leGVjdXRlQ29tbWFuZChjb21tYW5kLCBhcmdzLCBhcmdzTm9TcGxpdCwgZGVidWcpIHtcbiAgICAgICAgLy90ZXN0IHRoaXMhXG4gICAgICAgIGlmICghdGhpcy5fb3Blbikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdleGlmdG9vbCBpcyBub3Qgb3BlbicpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3Byb2Nlc3Muc2lnbmFsQ29kZSA9PT0gJ1NJR1RFUk0nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBjb25uZWN0IHRvIHRoZSBleGlmdG9vbCBwcm9jZXNzJylcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHByb2MgPSBkZWJ1ZyA9PT0gdHJ1ZSA/IHByb2Nlc3MgOiB0aGlzLl9wcm9jZXNzXG4gICAgICAgIHJldHVybiBsaWIuZXhlY3V0ZUNvbW1hbmQocHJvYywgdGhpcy5fc3Rkb3V0UmVzb2x2ZVdzLFxuICAgICAgICAgICAgdGhpcy5fc3RkZXJyUmVzb2x2ZVdzLCBjb21tYW5kLCBhcmdzLCBhcmdzTm9TcGxpdCwgdGhpcy5fZW5jb2RpbmcpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZCBtZXRhZGF0YSBvZiBhIGZpbGUgb3IgZGlyZWN0b3J5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfFJlYWRhYmxlfSBmaWxlIHBhdGggdG8gdGhlIGZpbGUgb3IgZGlyZWN0b3J5LCBvciBhXG4gICAgICogcmVhZGFibGUgc3RyZWFtXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gYXJncyBhbnkgYWRkaXRpb25hbCBhcmd1bWVudHMsIGUuZy4sIFsnT3JpZW50YXRpb24jJ11cbiAgICAgKiB0byByZXBvcnQgT3JpZW50YXRpb24gb25seSwgb3IgWyctRmlsZVNpemUnXSB0byBleGNsdWRlIEZpbGVTaXplXG4gICAgICogQHJldHVybnMge1Byb21pc2UuPHtkYXRhOiBvYmplY3RbXXxudWxsLCBlcnJvcjogc3RyaW5nfG51bGx9Pn0gYSBwcm9taXNlXG4gICAgICogcmVzb2x2ZWQgd2l0aCBwYXJzZWQgc3Rkb3V0IGFuZCBzdGRlcnIuXG4gICAgICovXG4gICAgcmVhZE1ldGFkYXRhKGZpbGUsIGFyZ3MpIHtcbiAgICAgICAgaWYgKGxpYi5pc1JlYWRhYmxlKGZpbGUpKSB7XG4gICAgICAgICAgICByZXR1cm4gZXhlY3V0ZVdpdGhScyhmaWxlLCBhcmdzLCB0aGlzLl9leGVjdXRlQ29tbWFuZC5iaW5kKHRoaXMpKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9leGVjdXRlQ29tbWFuZChmaWxlLCBhcmdzKVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlIG1ldGFkYXRhIHRvIGEgZmlsZSBvciBkaXJlY3RvcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGUgcGF0aCB0byB0aGUgZmlsZSBvciBkaXJlY3RvcnlcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gZGF0YSBkYXRhIHRvIHdyaXRlLCB3aXRoIGtleXMgYXMgdGFnc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IGFyZ3MgYWRkaXRpb25hbCBhcmd1bWVudHMsIGUuZy4sIFsnb3ZlcndyaXRlX29yaWdpbmFsJ11cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGRlYnVnIHdoZXRoZXIgdG8gcHJpbnQgdG8gc3Rkb3V0XG4gICAgICogQHJldHVybnMge1Byb21pc2UuPHt7ZGF0YSwgZXJyb3J9fT59IEEgcHJvbWlzZSB0byB3cml0ZSBtZXRhZGF0YSxcbiAgICAgKiByZXNvbHZlZCB3aXRoIGRhdGEgZnJvbSBzdGRvdXQgYW5kIHN0ZGVyci5cbiAgICAgKi9cbiAgICBhc3luYyB3cml0ZU1ldGFkYXRhKGZpbGUsIGRhdGEsIGFyZ3MsIGRlYnVnKSB7XG4gICAgICAgIGlmICghbGliLmlzU3RyaW5nKGZpbGUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpbGUgbXVzdCBiZSBhIHN0cmluZycpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFsaWIuY2hlY2tEYXRhT2JqZWN0KGRhdGEpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RhdGEgYXJndW1lbnQgaXMgbm90IGFuIG9iamVjdCcpXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB3cml0ZUFyZ3MgPSBsaWIubWFwRGF0YVRvVGFnQXJyYXkoZGF0YSlcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V4ZWN1dGVDb21tYW5kKGZpbGUsIGFyZ3MsIHdyaXRlQXJncywgZGVidWcpXG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBFeGlmdG9vbFByb2Nlc3MsXG4gICAgRVhJRlRPT0xfUEFUSCxcbiAgICBldmVudHMsXG59XG4iXX0= \ No newline at end of file diff --git a/dist/src/lib.js b/dist/src/lib.js new file mode 100644 index 0000000..ffcd066 --- /dev/null +++ b/dist/src/lib.js @@ -0,0 +1,226 @@ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +require('source-map-support/register'); + +var cp = require('child_process'); + +var _require = require('os'), + EOL = _require.EOL; + +var isStream = require('is-stream'); +var erotic = require('erotic'); + +function writeStdIn(proc, data, encoding) { + // console.log('write stdin', data) + proc.stdin.write(data, encoding); + proc.stdin.write(EOL, encoding); +} + +function close(proc) { + var er = erotic(); + var errHandler = void 0; + return new Promise(function (resolve, reject) { + errHandler = function errHandler(_ref) { + var message = _ref.message; + + var err = er(message); + reject(err); + }; + proc.once('close', resolve); + proc.stdin.once('error', errHandler); + writeStdIn(proc, '-stay_open'); + writeStdIn(proc, 'false'); + }).then(function () { + proc.stdin.removeListener('error', errHandler); + }); +} + +function isString(s) { + return (typeof s === 'undefined' ? 'undefined' : _typeof(s)).toLowerCase() === 'string'; +} + +function isObject(o) { + return (typeof o === 'undefined' ? 'undefined' : _typeof(o)).toLowerCase() === 'object' && o !== null; +} + +/** + * Get arguments. Split by new line to write to exiftool + */ +function getArgs(args, noSplit) { + if (!(Array.isArray(args) && args.length)) { + return []; + } + return args.filter(isString).map(function (arg) { + return '-' + arg; + }).reduce(function (acc, arg) { + return [].concat(acc, noSplit ? [arg] : arg.split(/\s+/)); + }, []); +} + +/** + * Write command data to the exiftool's stdin. + * @param {ChildProcess} process - exiftool process executed with -stay_open True -@ - + * @param {string} command - which command to execute + * @param {string} commandNumber - text which will be echoed before and after results + * @param {string[]} args - any additional arguments + * @param {string[]} noSplitArgs - arguments which should not be broken up like args + * @param {string} encoding - which encoding to write in. default no encoding + */ +function execute(proc, command, commandNumber, args, noSplitArgs, encoding) { + var extendedArgs = getArgs(args); + var extendedArgsNoSplit = getArgs(noSplitArgs, true); + + command = command !== undefined ? command : ''; + + var allArgs = [].concat(extendedArgsNoSplit, extendedArgs, ['-json', '-s'], [command, '-echo1', '{begin' + commandNumber + '}', '-echo2', '{begin' + commandNumber + '}', '-echo4', '{ready' + commandNumber + '}', '-execute' + commandNumber]); + if (process.env.DEBUG) { + // eslint-disable-next-line no-console + console.log(JSON.stringify(allArgs, null, 2)); + } + allArgs.forEach(function (arg) { + return writeStdIn(proc, arg, encoding); + }); +} + +var currentCommand = 0; +function genCommandNumber() { + return String(++currentCommand); +} + +function executeCommand(proc, stdoutRws, stderrRws, command, args, noSplitArgs, encoding) { + var commandNumber = genCommandNumber(); + + if (proc === process) { + // debugging + execute(proc, command, commandNumber, args, noSplitArgs, encoding); + return Promise.resolve({ data: 'debug', error: null }); + } + + var dataFinishHandler = void 0; + var errFinishHandler = void 0; + var dataErr = void 0; + var errErr = void 0; + + var dataPromise = new Promise(function (resolve, reject) { + dataFinishHandler = function dataFinishHandler() { + reject(new Error('stdout stream finished before operation was complete')); + }; + stdoutRws.once('finish', dataFinishHandler); + stdoutRws.addToResolveMap(commandNumber, resolve); + }).catch(function (error) { + dataErr = error; + }); + var errPromise = new Promise(function (resolve, reject) { + errFinishHandler = function errFinishHandler() { + reject(new Error('stderr stream finished before operation was complete')); + }; + stderrRws.once('finish', errFinishHandler); + stderrRws.addToResolveMap(commandNumber, resolve); + }).catch(function (error) { + errErr = error; + }); + + execute(proc, command, commandNumber, args, noSplitArgs, encoding); + + return Promise.all([dataPromise, errPromise]).then(function (res) { + stderrRws.removeListener('finish', errFinishHandler); + stdoutRws.removeListener('finish', dataFinishHandler); + if (dataErr && !errErr) { + throw dataErr; + } else if (errErr && !dataErr) { + throw errErr; + } else if (dataErr && errErr) { + throw new Error('stdout and stderr finished before operation was complete'); + } + return { + data: res[0] ? JSON.parse(res[0]) : null, + error: res[1] || null + }; + }); +} + +function isReadable(stream) { + return isStream.readable(stream); +} +function isWritable(stream) { + return isStream.writable(stream); +} + +/** + * Spawn exiftool. + * @param {string} bin Path to the binary + * @param {object} [options] options to pass to child_process.spawn method + * @returns {Promise.} A promise resolved with the process pointer, or rejected on error. + */ +function spawn(bin, options) { + var echoString = Date.now().toString(); + var proc = cp.spawn(bin, ['-echo2', echoString, '-stay_open', 'True', '-@', '-'], options); + if (!isReadable(proc.stderr)) { + killProcess(proc); + return Promise.reject(new Error('Process was not spawned with a readable stderr, check stdio options.')); + } + + return new Promise(function (resolve, reject) { + var echoHandler = function echoHandler(data) { + var d = data.toString().trim(); + // listening for echo2 in stderr (echo and echo1 won't work) + if (d === echoString) { + resolve(proc); + } else { + reject(new Error('Unexpected string on start: ' + d)); + } + }; + proc.stderr.once('data', echoHandler); + proc.once('error', reject); + }); +} + +function checkDataObject(data) { + return data === Object(data) && !Array.isArray(data); +} + +function mapDataToTagArray(data, array) { + var res = Array.isArray(array) ? array : []; + Object.keys(data).forEach(function (tag) { + var value = data[tag]; + if (Array.isArray(value)) { + value.forEach(function (v) { + var arg = tag + '=' + v; + res.push(arg); + }); + } else { + res.push(tag + '=' + value); + } + }); + return res; +} + +/** + * Use process.kill on POSIX or terminate process with taskkill on Windows. + * @param {ChildProcess} proc Process to terminate + */ +function killProcess(proc) { + if (process.platform === 'win32') { + cp.exec('taskkill /t /F /PID ' + proc.pid); + } else { + proc.kill(); + } +} + +module.exports = { + spawn: spawn, + close: close, + executeCommand: executeCommand, + checkDataObject: checkDataObject, + mapDataToTagArray: mapDataToTagArray, + getArgs: getArgs, + execute: execute, + isString: isString, + isObject: isObject, + isReadable: isReadable, + isWritable: isWritable, + killProcess: killProcess +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIuanMiXSwibmFtZXMiOlsiY3AiLCJyZXF1aXJlIiwiRU9MIiwiaXNTdHJlYW0iLCJlcm90aWMiLCJ3cml0ZVN0ZEluIiwicHJvYyIsImRhdGEiLCJlbmNvZGluZyIsInN0ZGluIiwid3JpdGUiLCJjbG9zZSIsImVyIiwiZXJySGFuZGxlciIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwibWVzc2FnZSIsImVyciIsIm9uY2UiLCJ0aGVuIiwicmVtb3ZlTGlzdGVuZXIiLCJpc1N0cmluZyIsInMiLCJ0b0xvd2VyQ2FzZSIsImlzT2JqZWN0IiwibyIsImdldEFyZ3MiLCJhcmdzIiwibm9TcGxpdCIsIkFycmF5IiwiaXNBcnJheSIsImxlbmd0aCIsImZpbHRlciIsIm1hcCIsImFyZyIsInJlZHVjZSIsImFjYyIsImNvbmNhdCIsInNwbGl0IiwiZXhlY3V0ZSIsImNvbW1hbmQiLCJjb21tYW5kTnVtYmVyIiwibm9TcGxpdEFyZ3MiLCJleHRlbmRlZEFyZ3MiLCJleHRlbmRlZEFyZ3NOb1NwbGl0IiwidW5kZWZpbmVkIiwiYWxsQXJncyIsInByb2Nlc3MiLCJlbnYiLCJERUJVRyIsImNvbnNvbGUiLCJsb2ciLCJKU09OIiwic3RyaW5naWZ5IiwiZm9yRWFjaCIsImN1cnJlbnRDb21tYW5kIiwiZ2VuQ29tbWFuZE51bWJlciIsIlN0cmluZyIsImV4ZWN1dGVDb21tYW5kIiwic3Rkb3V0UndzIiwic3RkZXJyUndzIiwiZXJyb3IiLCJkYXRhRmluaXNoSGFuZGxlciIsImVyckZpbmlzaEhhbmRsZXIiLCJkYXRhRXJyIiwiZXJyRXJyIiwiZGF0YVByb21pc2UiLCJFcnJvciIsImFkZFRvUmVzb2x2ZU1hcCIsImNhdGNoIiwiZXJyUHJvbWlzZSIsImFsbCIsInJlcyIsInBhcnNlIiwiaXNSZWFkYWJsZSIsInN0cmVhbSIsInJlYWRhYmxlIiwiaXNXcml0YWJsZSIsIndyaXRhYmxlIiwic3Bhd24iLCJiaW4iLCJvcHRpb25zIiwiZWNob1N0cmluZyIsIkRhdGUiLCJub3ciLCJ0b1N0cmluZyIsInN0ZGVyciIsImtpbGxQcm9jZXNzIiwiZWNob0hhbmRsZXIiLCJkIiwidHJpbSIsImNoZWNrRGF0YU9iamVjdCIsIk9iamVjdCIsIm1hcERhdGFUb1RhZ0FycmF5IiwiYXJyYXkiLCJrZXlzIiwidmFsdWUiLCJ0YWciLCJ2IiwicHVzaCIsInBsYXRmb3JtIiwiZXhlYyIsInBpZCIsImtpbGwiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFNQSxLQUFLQyxRQUFRLGVBQVIsQ0FBWDs7ZUFDZ0JBLFFBQVEsSUFBUixDO0lBQVJDLEcsWUFBQUEsRzs7QUFDUixJQUFNQyxXQUFXRixRQUFRLFdBQVIsQ0FBakI7QUFDQSxJQUFNRyxTQUFTSCxRQUFRLFFBQVIsQ0FBZjs7QUFFQSxTQUFTSSxVQUFULENBQW9CQyxJQUFwQixFQUEwQkMsSUFBMUIsRUFBZ0NDLFFBQWhDLEVBQTBDO0FBQ3RDO0FBQ0FGLFNBQUtHLEtBQUwsQ0FBV0MsS0FBWCxDQUFpQkgsSUFBakIsRUFBdUJDLFFBQXZCO0FBQ0FGLFNBQUtHLEtBQUwsQ0FBV0MsS0FBWCxDQUFpQlIsR0FBakIsRUFBc0JNLFFBQXRCO0FBQ0g7O0FBRUQsU0FBU0csS0FBVCxDQUFlTCxJQUFmLEVBQXFCO0FBQ2pCLFFBQU1NLEtBQUtSLFFBQVg7QUFDQSxRQUFJUyxtQkFBSjtBQUNBLFdBQU8sSUFBSUMsT0FBSixDQUFZLFVBQUNDLE9BQUQsRUFBVUMsTUFBVixFQUFxQjtBQUNwQ0gscUJBQWEsMEJBQWlCO0FBQUEsZ0JBQWRJLE9BQWMsUUFBZEEsT0FBYzs7QUFDMUIsZ0JBQU1DLE1BQU1OLEdBQUdLLE9BQUgsQ0FBWjtBQUNBRCxtQkFBT0UsR0FBUDtBQUNILFNBSEQ7QUFJQVosYUFBS2EsSUFBTCxDQUFVLE9BQVYsRUFBbUJKLE9BQW5CO0FBQ0FULGFBQUtHLEtBQUwsQ0FBV1UsSUFBWCxDQUFnQixPQUFoQixFQUF5Qk4sVUFBekI7QUFDQVIsbUJBQVdDLElBQVgs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QkMsQ0FBdEI7QUFDQTFCLG9CQUFJMkIsSUFBSixDQUFTakUsR0FBVDtBQUNILGFBSEQ7QUFJSCxTQUxELE1BS087QUFDSHNDLGdCQUFJMkIsSUFBSixDQUFZRixHQUFaLFNBQW1CRCxLQUFuQjtBQUNIO0FBQ0osS0FaTDtBQWFBLFdBQU94QixHQUFQO0FBQ0g7O0FBRUQ7Ozs7QUFJQSxTQUFTZSxXQUFULENBQXFCbEYsSUFBckIsRUFBMkI7QUFDdkIsUUFBSTBDLFFBQVFxRCxRQUFSLEtBQXFCLE9BQXpCLEVBQWtDO0FBQzlCckcsV0FBR3NHLElBQUgsMEJBQStCaEcsS0FBS2lHLEdBQXBDO0FBQ0gsS0FGRCxNQUVPO0FBQ0hqRyxhQUFLa0csSUFBTDtBQUNIO0FBQ0o7O0FBRURDLE9BQU9DLE9BQVAsR0FBaUI7QUFDYjFCLGdCQURhO0FBRWJyRSxnQkFGYTtBQUdiZ0Qsa0NBSGE7QUFJYmlDLG9DQUphO0FBS2JFLHdDQUxhO0FBTWJuRSxvQkFOYTtBQU9iYSxvQkFQYTtBQVFibEIsc0JBUmE7QUFTYkcsc0JBVGE7QUFVYmtELDBCQVZhO0FBV2JHLDBCQVhhO0FBWWJVO0FBWmEsQ0FBakIiLCJmaWxlIjoibGliLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgY3AgPSByZXF1aXJlKCdjaGlsZF9wcm9jZXNzJylcbmNvbnN0IHsgRU9MIH0gPSByZXF1aXJlKCdvcycpXG5jb25zdCBpc1N0cmVhbSA9IHJlcXVpcmUoJ2lzLXN0cmVhbScpXG5jb25zdCBlcm90aWMgPSByZXF1aXJlKCdlcm90aWMnKVxuXG5mdW5jdGlvbiB3cml0ZVN0ZEluKHByb2MsIGRhdGEsIGVuY29kaW5nKSB7XG4gICAgLy8gY29uc29sZS5sb2coJ3dyaXRlIHN0ZGluJywgZGF0YSlcbiAgICBwcm9jLnN0ZGluLndyaXRlKGRhdGEsIGVuY29kaW5nKVxuICAgIHByb2Muc3RkaW4ud3JpdGUoRU9MLCBlbmNvZGluZylcbn1cblxuZnVuY3Rpb24gY2xvc2UocHJvYykge1xuICAgIGNvbnN0IGVyID0gZXJvdGljKClcbiAgICBsZXQgZXJySGFuZGxlclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGVyckhhbmRsZXIgPSAoeyBtZXNzYWdlIH0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVyciA9IGVyKG1lc3NhZ2UpXG4gICAgICAgICAgICByZWplY3QoZXJyKVxuICAgICAgICB9XG4gICAgICAgIHByb2Mub25jZSgnY2xvc2UnLCByZXNvbHZlKVxuICAgICAgICBwcm9jLnN0ZGluLm9uY2UoJ2Vycm9yJywgZXJySGFuZGxlcilcbiAgICAgICAgd3JpdGVTdGRJbihwcm9jLCAnLXN0YXlfb3BlbicpXG4gICAgICAgIHdyaXRlU3RkSW4ocHJvYywgJ2ZhbHNlJylcbiAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgcHJvYy5zdGRpbi5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCBlcnJIYW5kbGVyKVxuICAgIH0pXG59XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKHMpIHtcbiAgICByZXR1cm4gKHR5cGVvZiBzKS50b0xvd2VyQ2FzZSgpID09PSAnc3RyaW5nJ1xufVxuXG5mdW5jdGlvbiBpc09iamVjdChvKSB7XG4gICAgcmV0dXJuICh0eXBlb2YgbykudG9Mb3dlckNhc2UoKSA9PT0gJ29iamVjdCcgJiYgbyAhPT0gbnVsbFxufVxuXG4vKipcbiAqIEdldCBhcmd1bWVudHMuIFNwbGl0IGJ5IG5ldyBsaW5lIHRvIHdyaXRlIHRvIGV4aWZ0b29sXG4gKi9cbmZ1bmN0aW9uIGdldEFyZ3MoYXJncywgbm9TcGxpdCkge1xuICAgIGlmKCEoQXJyYXkuaXNBcnJheShhcmdzKSAmJiBhcmdzLmxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIFtdXG4gICAgfVxuICAgIHJldHVybiBhcmdzXG4gICAgICAgIC5maWx0ZXIoaXNTdHJpbmcpXG4gICAgICAgIC5tYXAoYXJnID0+IGAtJHthcmd9YClcbiAgICAgICAgLnJlZHVjZSgoYWNjLCBhcmcpID0+XG4gICAgICAgICAgICBbXS5jb25jYXQoYWNjLCBub1NwbGl0ID8gW2FyZ10gOiBhcmcuc3BsaXQoL1xccysvKSlcbiAgICAgICAgICAgICwgW10pXG59XG5cbi8qKlxuICogV3JpdGUgY29tbWFuZCBkYXRhIHRvIHRoZSBleGlmdG9vbCdzIHN0ZGluLlxuICogQHBhcmFtIHtDaGlsZFByb2Nlc3N9IHByb2Nlc3MgLSBleGlmdG9vbCBwcm9jZXNzIGV4ZWN1dGVkIHdpdGggLXN0YXlfb3BlbiBUcnVlIC1AIC1cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb21tYW5kIC0gd2hpY2ggY29tbWFuZCB0byBleGVjdXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gY29tbWFuZE51bWJlciAtIHRleHQgd2hpY2ggd2lsbCBiZSBlY2hvZWQgYmVmb3JlIGFuZCBhZnRlciByZXN1bHRzXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzIC0gYW55IGFkZGl0aW9uYWwgYXJndW1lbnRzXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBub1NwbGl0QXJncyAtIGFyZ3VtZW50cyB3aGljaCBzaG91bGQgbm90IGJlIGJyb2tlbiB1cCBsaWtlIGFyZ3NcbiAqIEBwYXJhbSB7c3RyaW5nfSBlbmNvZGluZyAtIHdoaWNoIGVuY29kaW5nIHRvIHdyaXRlIGluLiBkZWZhdWx0IG5vIGVuY29kaW5nXG4gKi9cbmZ1bmN0aW9uIGV4ZWN1dGUocHJvYywgY29tbWFuZCwgY29tbWFuZE51bWJlciwgYXJncywgbm9TcGxpdEFyZ3MsIGVuY29kaW5nKSB7XG4gICAgY29uc3QgZXh0ZW5kZWRBcmdzID0gZ2V0QXJncyhhcmdzKVxuICAgIGNvbnN0IGV4dGVuZGVkQXJnc05vU3BsaXQgPSBnZXRBcmdzKG5vU3BsaXRBcmdzLCB0cnVlKVxuXG4gICAgY29tbWFuZCA9IGNvbW1hbmQgIT09IHVuZGVmaW5lZCA/IGNvbW1hbmQgOiAnJ1xuXG4gICAgY29uc3QgYWxsQXJncyA9IFtdLmNvbmNhdChcbiAgICAgICAgZXh0ZW5kZWRBcmdzTm9TcGxpdCxcbiAgICAgICAgZXh0ZW5kZWRBcmdzLFxuICAgICAgICBbJy1qc29uJywgJy1zJ10sXG4gICAgICAgIFtcbiAgICAgICAgICAgIGNvbW1hbmQsXG4gICAgICAgICAgICAnLWVjaG8xJyxcbiAgICAgICAgICAgIGB7YmVnaW4ke2NvbW1hbmROdW1iZXJ9fWAsXG4gICAgICAgICAgICAnLWVjaG8yJyxcbiAgICAgICAgICAgIGB7YmVnaW4ke2NvbW1hbmROdW1iZXJ9fWAsXG4gICAgICAgICAgICAnLWVjaG80JyxcbiAgICAgICAgICAgIGB7cmVhZHkke2NvbW1hbmROdW1iZXJ9fWAsXG4gICAgICAgICAgICBgLWV4ZWN1dGUke2NvbW1hbmROdW1iZXJ9YCxcbiAgICAgICAgXVxuICAgIClcbiAgICBpZiAocHJvY2Vzcy5lbnYuREVCVUcpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoYWxsQXJncywgbnVsbCwgMikpXG4gICAgfVxuICAgIGFsbEFyZ3MuZm9yRWFjaChhcmcgPT4gd3JpdGVTdGRJbihwcm9jLCBhcmcsIGVuY29kaW5nKSlcbn1cblxubGV0IGN1cnJlbnRDb21tYW5kID0gMFxuZnVuY3Rpb24gZ2VuQ29tbWFuZE51bWJlcigpIHtcbiAgICByZXR1cm4gU3RyaW5nKCsrY3VycmVudENvbW1hbmQpXG59XG5cbmZ1bmN0aW9uIGV4ZWN1dGVDb21tYW5kKHByb2MsIHN0ZG91dFJ3cywgc3RkZXJyUndzLCBjb21tYW5kLCBhcmdzLCBub1NwbGl0QXJncywgZW5jb2RpbmcpIHtcbiAgICBjb25zdCBjb21tYW5kTnVtYmVyID0gZ2VuQ29tbWFuZE51bWJlcigpXG5cbiAgICBpZiAocHJvYyA9PT0gcHJvY2VzcykgeyAvLyBkZWJ1Z2dpbmdcbiAgICAgICAgZXhlY3V0ZShwcm9jLCBjb21tYW5kLCBjb21tYW5kTnVtYmVyLCBhcmdzLCBub1NwbGl0QXJncywgZW5jb2RpbmcpXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiAnZGVidWcnLCBlcnJvcjogbnVsbCB9KVxuICAgIH1cblxuICAgIGxldCBkYXRhRmluaXNoSGFuZGxlclxuICAgIGxldCBlcnJGaW5pc2hIYW5kbGVyXG4gICAgbGV0IGRhdGFFcnJcbiAgICBsZXQgZXJyRXJyXG5cbiAgICBjb25zdCBkYXRhUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZGF0YUZpbmlzaEhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdzdGRvdXQgc3RyZWFtIGZpbmlzaGVkIGJlZm9yZSBvcGVyYXRpb24gd2FzIGNvbXBsZXRlJykpXG4gICAgICAgIH1cbiAgICAgICAgc3Rkb3V0UndzLm9uY2UoJ2ZpbmlzaCcsIGRhdGFGaW5pc2hIYW5kbGVyKVxuICAgICAgICBzdGRvdXRSd3MuYWRkVG9SZXNvbHZlTWFwKGNvbW1hbmROdW1iZXIsIHJlc29sdmUpXG4gICAgfSkuY2F0Y2goZXJyb3IgPT4geyBkYXRhRXJyID0gZXJyb3IgfSlcbiAgICBjb25zdCBlcnJQcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBlcnJGaW5pc2hIYW5kbGVyID0gKCkgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignc3RkZXJyIHN0cmVhbSBmaW5pc2hlZCBiZWZvcmUgb3BlcmF0aW9uIHdhcyBjb21wbGV0ZScpKVxuICAgICAgICB9XG4gICAgICAgIHN0ZGVyclJ3cy5vbmNlKCdmaW5pc2gnLCBlcnJGaW5pc2hIYW5kbGVyKVxuICAgICAgICBzdGRlcnJSd3MuYWRkVG9SZXNvbHZlTWFwKGNvbW1hbmROdW1iZXIsIHJlc29sdmUpXG4gICAgfSkuY2F0Y2goZXJyb3IgPT4geyBlcnJFcnIgPSBlcnJvciB9KVxuXG4gICAgZXhlY3V0ZShwcm9jLCBjb21tYW5kLCBjb21tYW5kTnVtYmVyLCBhcmdzLCBub1NwbGl0QXJncywgZW5jb2RpbmcpXG5cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoW1xuICAgICAgICBkYXRhUHJvbWlzZSxcbiAgICAgICAgZXJyUHJvbWlzZSxcbiAgICBdKVxuICAgICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgICBzdGRlcnJSd3MucmVtb3ZlTGlzdGVuZXIoJ2ZpbmlzaCcsIGVyckZpbmlzaEhhbmRsZXIpXG4gICAgICAgICAgICBzdGRvdXRSd3MucmVtb3ZlTGlzdGVuZXIoJ2ZpbmlzaCcsIGRhdGFGaW5pc2hIYW5kbGVyKVxuICAgICAgICAgICAgaWYgKGRhdGFFcnIgJiYgIWVyckVycikge1xuICAgICAgICAgICAgICAgIHRocm93IGRhdGFFcnJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyRXJyICYmICFkYXRhRXJyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyRXJyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGFFcnIgJiYgZXJyRXJyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzdGRvdXQgYW5kIHN0ZGVyciBmaW5pc2hlZCBiZWZvcmUgb3BlcmF0aW9uIHdhcyBjb21wbGV0ZScpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGRhdGE6IHJlc1swXSA/IEpTT04ucGFyc2UocmVzWzBdKSA6IG51bGwsXG4gICAgICAgICAgICAgICAgZXJyb3I6IHJlc1sxXSB8fCBudWxsLFxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxufVxuXG5mdW5jdGlvbiBpc1JlYWRhYmxlKHN0cmVhbSkge1xuICAgIHJldHVybiBpc1N0cmVhbS5yZWFkYWJsZShzdHJlYW0pXG59XG5mdW5jdGlvbiBpc1dyaXRhYmxlKHN0cmVhbSkge1xuICAgIHJldHVybiBpc1N0cmVhbS53cml0YWJsZShzdHJlYW0pXG59XG5cbi8qKlxuICogU3Bhd24gZXhpZnRvb2wuXG4gKiBAcGFyYW0ge3N0cmluZ30gYmluIFBhdGggdG8gdGhlIGJpbmFyeVxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXSBvcHRpb25zIHRvIHBhc3MgdG8gY2hpbGRfcHJvY2Vzcy5zcGF3biBtZXRob2RcbiAqIEByZXR1cm5zIHtQcm9taXNlLjxDaGlsZFByb2Nlc3M+fSBBIHByb21pc2UgcmVzb2x2ZWQgd2l0aCB0aGUgcHJvY2VzcyBwb2ludGVyLCBvciByZWplY3RlZCBvbiBlcnJvci5cbiAqL1xuZnVuY3Rpb24gc3Bhd24oYmluLCBvcHRpb25zKSB7XG4gICAgY29uc3QgZWNob1N0cmluZyA9IERhdGUubm93KCkudG9TdHJpbmcoKVxuICAgIGNvbnN0IHByb2MgPSBjcC5zcGF3bihiaW4sIFsnLWVjaG8yJywgZWNob1N0cmluZywgJy1zdGF5X29wZW4nLCAnVHJ1ZScsICctQCcsICctJ10sIG9wdGlvbnMpXG4gICAgaWYgKCFpc1JlYWRhYmxlKHByb2Muc3RkZXJyKSkge1xuICAgICAgICBraWxsUHJvY2Vzcyhwcm9jKVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdQcm9jZXNzIHdhcyBub3Qgc3Bhd25lZCB3aXRoIGEgcmVhZGFibGUgc3RkZXJyLCBjaGVjayBzdGRpbyBvcHRpb25zLicpKVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGVjaG9IYW5kbGVyID0gKGRhdGEpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGQgPSBkYXRhLnRvU3RyaW5nKCkudHJpbSgpXG4gICAgICAgICAgICAvLyBsaXN0ZW5pbmcgZm9yIGVjaG8yIGluIHN0ZGVyciAoZWNobyBhbmQgZWNobzEgd29uJ3Qgd29yaylcbiAgICAgICAgICAgIGlmIChkID09PSBlY2hvU3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShwcm9jKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBVbmV4cGVjdGVkIHN0cmluZyBvbiBzdGFydDogJHtkfWApKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHByb2Muc3RkZXJyLm9uY2UoJ2RhdGEnLCBlY2hvSGFuZGxlcilcbiAgICAgICAgcHJvYy5vbmNlKCdlcnJvcicsIHJlamVjdClcbiAgICB9KVxufVxuXG5mdW5jdGlvbiBjaGVja0RhdGFPYmplY3QoZGF0YSkge1xuICAgIHJldHVybiBkYXRhID09PSBPYmplY3QoZGF0YSkgJiYgIUFycmF5LmlzQXJyYXkoZGF0YSlcbn1cblxuZnVuY3Rpb24gbWFwRGF0YVRvVGFnQXJyYXkoZGF0YSwgYXJyYXkpIHtcbiAgICBjb25zdCByZXMgPSBBcnJheS5pc0FycmF5KGFycmF5KSA/IGFycmF5IDogW11cbiAgICBPYmplY3RcbiAgICAgICAgLmtleXMoZGF0YSlcbiAgICAgICAgLmZvckVhY2godGFnID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gZGF0YVt0YWddXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZS5mb3JFYWNoKCh2KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyZyA9IGAke3RhZ309JHt2fWBcbiAgICAgICAgICAgICAgICAgICAgcmVzLnB1c2goYXJnKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGAke3RhZ309JHt2YWx1ZX1gKVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgIHJldHVybiByZXNcbn1cblxuLyoqXG4gKiBVc2UgcHJvY2Vzcy5raWxsIG9uIFBPU0lYIG9yIHRlcm1pbmF0ZSBwcm9jZXNzIHdpdGggdGFza2tpbGwgb24gV2luZG93cy5cbiAqIEBwYXJhbSB7Q2hpbGRQcm9jZXNzfSBwcm9jIFByb2Nlc3MgdG8gdGVybWluYXRlXG4gKi9cbmZ1bmN0aW9uIGtpbGxQcm9jZXNzKHByb2MpIHtcbiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgICAgICBjcC5leGVjKGB0YXNra2lsbCAvdCAvRiAvUElEICR7cHJvYy5waWR9YClcbiAgICB9IGVsc2Uge1xuICAgICAgICBwcm9jLmtpbGwoKVxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3Bhd24sXG4gICAgY2xvc2UsXG4gICAgZXhlY3V0ZUNvbW1hbmQsXG4gICAgY2hlY2tEYXRhT2JqZWN0LFxuICAgIG1hcERhdGFUb1RhZ0FycmF5LFxuICAgIGdldEFyZ3MsXG4gICAgZXhlY3V0ZSxcbiAgICBpc1N0cmluZyxcbiAgICBpc09iamVjdCxcbiAgICBpc1JlYWRhYmxlLFxuICAgIGlzV3JpdGFibGUsXG4gICAga2lsbFByb2Nlc3MsXG59XG4iXX0= \ No newline at end of file diff --git a/dist/test/context/detached.js b/dist/test/context/detached.js new file mode 100644 index 0000000..6ffb4f0 --- /dev/null +++ b/dist/test/context/detached.js @@ -0,0 +1,114 @@ +'use strict'; + +require('source-map-support/register'); + +var cp = require('child_process'); +var makepromise = require('makepromise'); +var debuglog = require('util').debuglog('detached'); +var path = require('path'); + +var FORK_PATH = path.join(__dirname, '../fixtures/detached'); + +var isWindows = process.platform === 'win32'; + +var createFork = function createFork(modulePath, detached, env) { + return cp.spawn(process.argv[0], [modulePath], { + detached: detached, + // not doing this will not allow debugging, as fork will try to connect + // to the same debug port as parent + execArgv: [], + env: Object.assign({}, process.env, env), + stdio: ['pipe', 'pipe', 'pipe', 'ipc'] + }); +}; + +function getGrep(include, exclude) { + var grep = include.join('\\|'); + var vgrep = [].concat(exclude, 'grep').join('\\|'); + var com = ['ps xao pid,ppid,pgid,stat,sess,tt,tty,command']; + if (grep) com.push('grep \'' + grep + '\''); + com.push('grep -v \'' + vgrep + '\''); + var s = com.join(' | '); + return s; +} + +function getWmic(include) { + var procs = include.map(function (p) { + return 'caption=\'' + p + '\''; + }).join(' or '); + return 'wmic process where "' + procs + '" get caption,processid,parentprocessid'; +} + +function ps(comment) { + var psInclude = ['node', 'perl', 'npm']; + var psExclude = ['Visual']; + var wmicInclude = ['node.exe', 'exiftool.exe', 'conhost.exe']; + var s = isWindows ? getWmic(wmicInclude) : getGrep(psInclude, psExclude); + return makepromise(cp.exec, [s]).then(function (r) { + debuglog(comment); + debuglog('======\n' + r); + debuglog('======'); + }); +} + +function killFork(proc, withGroup) { + return new Promise(function (resolve, reject) { + proc.once('exit', function () { + debuglog('killed %s', proc.pid); + resolve(); + }); + try { + var p = withGroup ? -proc.pid : proc.pid; + debuglog('going to kill %s', p); + process.kill(p); + } catch (err) { + debuglog(err.message); + reject(err); + } + }); +} + +/** + * This context will allow to create and destroy Node fork. + */ +var context = function DetachedContext() { + var _this = this; + + this.fork = null; + this.epPid = null; + + this.forkNode = function (exiftoolDetached) { + return ps('before starting fork').then(function () { + var env = exiftoolDetached ? { EXIFTOOL_DETACHED: true } : {}; + _this.fork = createFork(FORK_PATH, true, env); + debuglog('fork pid: %s', _this.fork.pid); + return new Promise(function (resolve) { + _this.fork.on('message', resolve); + }); + }).then(function (res) { + _this.epPid = res; + debuglog('exiftool pid: %s', _this.epPid); + _this.fork.on('disconnect', function () { + debuglog('fork disconnected'); + }); + _this.fork.on('exit', function () { + debuglog('fork exited'); + }); + return ps('after starting fork'); + }).then(function () { + return { epPid: _this.epPid, forkPid: _this.fork.pid }; + }); + }; + this.killFork = function (withGroup) { + if (!_this.fork) { + return Promise.reject(new Error('fork has not started')); + } + return killFork(_this.fork, withGroup); + }; + this._destroy = function () { + return ps('after test'); + }; +}; + +module.exports = context; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvY29udGV4dC9kZXRhY2hlZC5qcyJdLCJuYW1lcyI6WyJjcCIsInJlcXVpcmUiLCJtYWtlcHJvbWlzZSIsImRlYnVnbG9nIiwicGF0aCIsIkZPUktfUEFUSCIsImpvaW4iLCJfX2Rpcm5hbWUiLCJpc1dpbmRvd3MiLCJwcm9jZXNzIiwicGxhdGZvcm0iLCJjcmVhdGVGb3JrIiwibW9kdWxlUGF0aCIsImRldGFjaGVkIiwiZW52Iiwic3Bhd24iLCJhcmd2IiwiZXhlY0FyZ3YiLCJPYmplY3QiLCJhc3NpZ24iLCJzdGRpbyIsImdldEdyZXAiLCJpbmNsdWRlIiwiZXhjbHVkZSIsImdyZXAiLCJ2Z3JlcCIsImNvbmNhdCIsImNvbSIsInB1c2giLCJzIiwiZ2V0V21pYyIsInByb2NzIiwibWFwIiwicCIsInBzIiwiY29tbWVudCIsInBzSW5jbHVkZSIsInBzRXhjbHVkZSIsIndtaWNJbmNsdWRlIiwiZXhlYyIsInRoZW4iLCJyIiwia2lsbEZvcmsiLCJwcm9jIiwid2l0aEdyb3VwIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJvbmNlIiwicGlkIiwia2lsbCIsImVyciIsIm1lc3NhZ2UiLCJjb250ZXh0IiwiRGV0YWNoZWRDb250ZXh0IiwiZm9yayIsImVwUGlkIiwiZm9ya05vZGUiLCJleGlmdG9vbERldGFjaGVkIiwiRVhJRlRPT0xfREVUQUNIRUQiLCJvbiIsInJlcyIsImZvcmtQaWQiLCJFcnJvciIsIl9kZXN0cm95IiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQU1BLEtBQUtDLFFBQVEsZUFBUixDQUFYO0FBQ0EsSUFBTUMsY0FBY0QsUUFBUSxhQUFSLENBQXBCO0FBQ0EsSUFBTUUsV0FBV0YsUUFBUSxNQUFSLEVBQWdCRSxRQUFoQixDQUF5QixVQUF6QixDQUFqQjtBQUNBLElBQU1DLE9BQU9ILFFBQVEsTUFBUixDQUFiOztBQUVBLElBQU1JLFlBQVlELEtBQUtFLElBQUwsQ0FBVUMs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LEVBQWU7QUFDM0IsWUFBSSxDQUFDLE1BQUtXLElBQVYsRUFBZ0I7QUFDWixtQkFBT1YsUUFBUUUsTUFBUixDQUFlLElBQUlnQixLQUFKLENBQVUsc0JBQVYsQ0FBZixDQUFQO0FBQ0g7QUFDRCxlQUFPckIsU0FBUyxNQUFLYSxJQUFkLEVBQW9CWCxTQUFwQixDQUFQO0FBQ0gsS0FMRDtBQU1BLFNBQUtvQixRQUFMLEdBQWdCO0FBQUEsZUFBTTlCLEdBQUcsWUFBSCxDQUFOO0FBQUEsS0FBaEI7QUFDSCxDQWxDRDs7QUFvQ0ErQixPQUFPQyxPQUFQLEdBQWlCYixPQUFqQiIsImZpbGUiOiJkZXRhY2hlZC5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGNwID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpXG5jb25zdCBtYWtlcHJvbWlzZSA9IHJlcXVpcmUoJ21ha2Vwcm9taXNlJylcbmNvbnN0IGRlYnVnbG9nID0gcmVxdWlyZSgndXRpbCcpLmRlYnVnbG9nKCdkZXRhY2hlZCcpXG5jb25zdCBwYXRoID0gcmVxdWlyZSgncGF0aCcpXG5cbmNvbnN0IEZPUktfUEFUSCA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi9maXh0dXJlcy9kZXRhY2hlZCcpXG5cbmNvbnN0IGlzV2luZG93cyA9IHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMidcblxuY29uc3QgY3JlYXRlRm9yayA9IChtb2R1bGVQYXRoLCBkZXRhY2hlZCwgZW52KSA9PiBjcC5zcGF3bihcbiAgICBwcm9jZXNzLmFyZ3ZbMF0sXG4gICAgW21vZHVsZVBhdGhdLFxuICAgIHtcbiAgICAgICAgZGV0YWNoZWQsXG4gICAgICAgIC8vIG5vdCBkb2luZyB0aGlzIHdpbGwgbm90IGFsbG93IGRlYnVnZ2luZywgYXMgZm9yayB3aWxsIHRyeSB0byBjb25uZWN0XG4gICAgICAgIC8vIHRvIHRoZSBzYW1lIGRlYnVnIHBvcnQgYXMgcGFyZW50XG4gICAgICAgIGV4ZWNBcmd2OiBbXSxcbiAgICAgICAgZW52OiBPYmplY3QuYXNzaWduKHt9LCBwcm9jZXNzLmVudiwgZW52KSxcbiAgICAgICAgc3RkaW86IFsncGlwZScsICdwaXBlJywgJ3BpcGUnLCAnaXBjJ10sXG4gICAgfVxuKVxuXG5mdW5jdGlvbiBnZXRHcmVwKGluY2x1ZGUsIGV4Y2x1ZGUpIHtcbiAgICBjb25zdCBncmVwID0gaW5jbHVkZS5qb2luKCdcXFxcfCcpXG4gICAgY29uc3QgdmdyZXAgPSBbXS5jb25jYXQoZXhjbHVkZSwgJ2dyZXAnKS5qb2luKCdcXFxcfCcpXG4gICAgY29uc3QgY29tID0gWydwcyB4YW8gcGlkLHBwaWQscGdpZCxzdGF0LHNlc3MsdHQsdHR5LGNvbW1hbmQnXVxuICAgIGlmIChncmVwKSBjb20ucHVzaChgZ3JlcCAnJHtncmVwfSdgKVxuICAgIGNvbS5wdXNoKGBncmVwIC12ICcke3ZncmVwfSdgKVxuICAgIGNvbnN0IHMgPSBjb20uam9pbignIHwgJylcbiAgICByZXR1cm4gc1xufVxuXG5mdW5jdGlvbiBnZXRXbWljKGluY2x1ZGUpIHtcbiAgICBjb25zdCBwcm9jcyA9IGluY2x1ZGUubWFwKHAgPT4gYGNhcHRpb249JyR7cH0nYCkuam9pbignIG9yICcpXG4gICAgcmV0dXJuIGB3bWljIHByb2Nlc3Mgd2hlcmUgXCIke3Byb2NzfVwiIGdldCBjYXB0aW9uLHByb2Nlc3NpZCxwYXJlbnRwcm9jZXNzaWRgXG59XG5cbmZ1bmN0aW9uIHBzKGNvbW1lbnQpIHtcbiAgICBjb25zdCBwc0luY2x1ZGUgPSBbJ25vZGUnLCAncGVybCcsICducG0nXVxuICAgIGNvbnN0IHBzRXhjbHVkZSA9IFsnVmlzdWFsJ11cbiAgICBjb25zdCB3bWljSW5jbHVkZSA9IFsnbm9kZS5leGUnLCAnZXhpZnRvb2wuZXhlJywgJ2Nvbmhvc3QuZXhlJ11cbiAgICBjb25zdCBzID0gaXNXaW5kb3dzID8gZ2V0V21pYyh3bWljSW5jbHVkZSkgOiBnZXRHcmVwKHBzSW5jbHVkZSwgcHNFeGNsdWRlKVxuICAgIHJldHVybiBtYWtlcHJvbWlzZShjcC5leGVjLCBbc10pXG4gICAgICAgIC50aGVuKChyKSA9PiB7XG4gICAgICAgICAgICBkZWJ1Z2xvZyhjb21tZW50KVxuICAgICAgICAgICAgZGVidWdsb2coYD09PT09PVxcbiR7cn1gKVxuICAgICAgICAgICAgZGVidWdsb2coJz09PT09PScpXG4gICAgICAgIH0pXG59XG5cbmZ1bmN0aW9uIGtpbGxGb3JrKHByb2MsIHdpdGhHcm91cCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHByb2Mub25jZSgnZXhpdCcsICgpID0+IHtcbiAgICAgICAgICAgIGRlYnVnbG9nKCdraWxsZWQgJXMnLCBwcm9jLnBpZClcbiAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICB9KVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcCA9IHdpdGhHcm91cCA/IC1wcm9jLnBpZCA6IHByb2MucGlkXG4gICAgICAgICAgICBkZWJ1Z2xvZygnZ29pbmcgdG8ga2lsbCAlcycsIHApXG4gICAgICAgICAgICBwcm9jZXNzLmtpbGwocClcbiAgICAgICAgfSBjYXRjaChlcnIpIHtcbiAgICAgICAgICAgIGRlYnVnbG9nKGVyci5tZXNzYWdlKVxuICAgICAgICAgICAgcmVqZWN0KGVycilcbiAgICAgICAgfVxuICAgIH0pXG59XG5cbi8qKlxuICogVGhpcyBjb250ZXh0IHdpbGwgYWxsb3cgdG8gY3JlYXRlIGFuZCBkZXN0cm95IE5vZGUgZm9yay5cbiAqL1xuY29uc3QgY29udGV4dCA9IGZ1bmN0aW9uIERldGFjaGVkQ29udGV4dCgpIHtcbiAgICB0aGlzLmZvcmsgPSBudWxsXG4gICAgdGhpcy5lcFBpZCA9IG51bGxcblxuICAgIHRoaXMuZm9ya05vZGUgPSAoZXhpZnRvb2xEZXRhY2hlZCkgPT4ge1xuICAgICAgICByZXR1cm4gcHMoJ2JlZm9yZSBzdGFydGluZyBmb3JrJylcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBlbnYgPSBleGlmdG9vbERldGFjaGVkID8geyBFWElGVE9PTF9ERVRBQ0hFRDogdHJ1ZSB9IDoge31cbiAgICAgICAgICAgICAgICB0aGlzLmZvcmsgPSBjcmVhdGVGb3JrKEZPUktfUEFUSCwgdHJ1ZSwgZW52KVxuICAgICAgICAgICAgICAgIGRlYnVnbG9nKCdmb3JrIHBpZDogJXMnLCB0aGlzLmZvcmsucGlkKVxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcmsub24oJ21lc3NhZ2UnLCByZXNvbHZlKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZXBQaWQgPSByZXNcbiAgICAgICAgICAgICAgICBkZWJ1Z2xvZygnZXhpZnRvb2wgcGlkOiAlcycsIHRoaXMuZXBQaWQpXG4gICAgICAgICAgICAgICAgdGhpcy5mb3JrLm9uKCdkaXNjb25uZWN0JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkZWJ1Z2xvZygnZm9yayBkaXNjb25uZWN0ZWQnKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgdGhpcy5mb3JrLm9uKCdleGl0JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkZWJ1Z2xvZygnZm9yayBleGl0ZWQnKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBzKCdhZnRlciBzdGFydGluZyBmb3JrJylcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbigoKSA9PiAoeyBlcFBpZDogdGhpcy5lcFBpZCwgZm9ya1BpZDogdGhpcy5mb3JrLnBpZCB9KSlcbiAgICB9XG4gICAgdGhpcy5raWxsRm9yayA9ICh3aXRoR3JvdXApID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmZvcmspIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ2ZvcmsgaGFzIG5vdCBzdGFydGVkJykpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtpbGxGb3JrKHRoaXMuZm9yaywgd2l0aEdyb3VwKVxuICAgIH1cbiAgICB0aGlzLl9kZXN0cm95ID0gKCkgPT4gcHMoJ2FmdGVyIHRlc3QnKVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbnRleHRcbiJdfQ== \ No newline at end of file diff --git a/dist/test/fixtures/detached.js b/dist/test/fixtures/detached.js new file mode 100644 index 0000000..bc851b6 --- /dev/null +++ b/dist/test/fixtures/detached.js @@ -0,0 +1,53 @@ +'use strict'; + +require('source-map-support/register'); + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +var _require = require('exiftool-context'), + bin = _require.exiftoolBin; + +var exiftool = require('../../src/'); + +if (typeof process.send !== 'function') { + throw new Error('This module should be spawned with an IPC channel.'); +} + +var EXIFTOOL_DETACHED = process.env.EXIFTOOL_DETACHED; + + +var detached = EXIFTOOL_DETACHED === 'true'; + +_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { + var ep, pid; + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _context.prev = 0; + ep = new exiftool.ExiftoolProcess(bin); + _context.next = 4; + return ep.open({ detached: detached }); + + case 4: + pid = _context.sent; + + process.send(pid); + _context.next = 12; + break; + + case 8: + _context.prev = 8; + _context.t0 = _context['catch'](0); + + console.log(_context.t0); // eslint-disable-line no-console + process.exit(1); + + case 12: + case 'end': + return _context.stop(); + } + } + }, _callee, undefined, [[0, 8]]); +}))(); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvZml4dHVyZXMvZGV0YWNoZWQuanMiXSwibmFtZXMiOlsicmVxdWlyZSIsImJpbiIsImV4aWZ0b29sQmluIiwiZXhpZnRvb2wiLCJwcm9jZXNzIiwic2VuZCIsIkVycm9yIiwiRVhJRlRPT0xfREVUQUNIRUQiLCJlbnYiLCJkZXRhY2hlZCIsImVwIiwiRXhpZnRvb2xQcm9jZXNzIiwib3BlbiIsInBpZCIsImNvbnNvbGUiLCJsb2ciLCJleGl0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7ZUFBNkJBLFFBQVEsa0JBQVIsQztJQUFSQyxHLFlBQWJDLFc7O0FBQ1IsSUFBTUMsV0FBV0gsUUFBUSxZQUFSLENBQWpCOztBQUVBLElBQUksT0FBT0ksUUFBUUMsSUFBZixLQUF3QixVQUE1QixFQUF3QztBQUNwQyxVQUFNLElBQUlDLEtBQUosQ0FBVSxvREFBVixDQUFOO0FBQ0g7O0lBRU9DLGlCLEdBQXNCSCxRQUFRSSxHLENBQTlCRCxpQjs7O0FBRVIsSUFBTUUsV0FBV0Ysc0JBQXNCLE1BQXZDOztBQUVBLHdEQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBRWFHLHNCQUZiLEdBRWtCLElBQUlQLFNBQVNRLGVBQWIsQ0FBNkJWLEdBQTdCLENBRmxCO0FBQUE7QUFBQSwyQkFHeUJTLEdBQUdFLElBQUgsQ0FBUSxFQUFFSCxrQkFBRixFQUFSLENBSHpCOztBQUFBO0FBR2FJLHVCQUhiOztBQUlPVCw0QkFBUUMsSUFBUixDQUFhUSxHQUFiO0FBSlA7QUFBQTs7QUFBQTtBQUFBO0FBQUE7O0FBTU9DLDRCQUFRQyxHQUFSLGNBTlAsQ0FNd0I7QUFDakJYLDRCQUFRWSxJQUFSLENBQWEsQ0FBYjs7QUFQUDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxDQUFEIiwiZmlsZSI6ImRldGFjaGVkLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgeyBleGlmdG9vbEJpbjogYmluIH0gPSByZXF1aXJlKCdleGlmdG9vbC1jb250ZXh0JylcbmNvbnN0IGV4aWZ0b29sID0gcmVxdWlyZSgnLi4vLi4vc3JjLycpXG5cbmlmICh0eXBlb2YgcHJvY2Vzcy5zZW5kICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaGlzIG1vZHVsZSBzaG91bGQgYmUgc3Bhd25lZCB3aXRoIGFuIElQQyBjaGFubmVsLicpXG59XG5cbmNvbnN0IHsgRVhJRlRPT0xfREVUQUNIRUQgfSA9IHByb2Nlc3MuZW52XG5cbmNvbnN0IGRldGFjaGVkID0gRVhJRlRPT0xfREVUQUNIRUQgPT09ICd0cnVlJztcblxuKGFzeW5jICgpID0+IHtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBlcCA9IG5ldyBleGlmdG9vbC5FeGlmdG9vbFByb2Nlc3MoYmluKVxuICAgICAgICBjb25zdCBwaWQgPSBhd2FpdCBlcC5vcGVuKHsgZGV0YWNoZWQgfSlcbiAgICAgICAgcHJvY2Vzcy5zZW5kKHBpZClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5sb2coZXJyKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpXG4gICAgfVxufSkoKVxuIl19 \ No newline at end of file diff --git a/dist/test/lib/kill-pid.js b/dist/test/lib/kill-pid.js new file mode 100644 index 0000000..37ce16b --- /dev/null +++ b/dist/test/lib/kill-pid.js @@ -0,0 +1,46 @@ +'use strict'; + +require('source-map-support/register'); + +var cp = require('child_process'); +var ps = require('ps-node'); + +var isWindows = process.platform === 'win32'; +// use this function when we only have a pid, but not process, i.e., +// we can't assign on('exit') listener +function killUnixPid(pid) { + if (isWindows) { + return Promise.reject(new Error('This function is not available on win')); + } + return new Promise(function (resolve, reject) { + ps.kill(pid, function (err) { + if (err) return reject(err); + return resolve(pid); + }); + }); +} + +function killWinPid(pid) { + if (!isWindows) { + return Promise.reject(new Error('This function is only available on win')); + } + return new Promise(function (resolve, reject) { + cp.exec('taskkill /t /F /PID ' + pid, function (err, stdout) { + if (err) return reject(err); + if (!/SUCCESS/.test(stdout)) return reject(new Error(stdout.trim())); + resolve(pid); + }); + }); +} + +/** + * Kill a process by pid, if pointer is not available. + * @param {number|string} pid Process ID + * @returns {Promise.} Promise resolved with the pid. + */ +function killPid(pid) { + return isWindows ? killWinPid(pid) : killUnixPid(pid); +} + +module.exports = killPid; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvbGliL2tpbGwtcGlkLmpzIl0sIm5hbWVzIjpbImNwIiwicmVxdWlyZSIsInBzIiwiaXNXaW5kb3dzIiwicHJvY2VzcyIsInBsYXRmb3JtIiwia2lsbFVuaXhQaWQiLCJwaWQiLCJQcm9taXNlIiwicmVqZWN0IiwiRXJyb3IiLCJyZXNvbHZlIiwia2lsbCIsImVyciIsImtpbGxXaW5QaWQiLCJleGVjIiwic3Rkb3V0IiwidGVzdCIsInRyaW0iLCJraWxsUGlkIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQU1BLEtBQUtDLFFBQVEsZUFBUixDQUFYO0FBQ0EsSUFBTUMsS0FBS0QsUUFBUSxTQUFSLENBQVg7O0FBRUEsSUFBTUUsWUFBWUMsUUFBUUMsUUFBUixLQUFxQixPQUF2QztBQUNBO0FBQ0E7QUFDQSxTQUFTQyxXQUFULENBQXFCQyxHQUFyQixFQUEwQjtBQUN0QixRQUFJSixTQUFKLEVBQWU7QUFDWCxlQUFPSyxRQUFRQyxNQUFSLENBQWUsSUFBSUMsS0FBSixDQUFVLHVDQUFWLENBQWYsQ0FBUDtBQUNIO0FBQ0QsV0FBTyxJQUFJRixPQUFKLENBQVksVUFBQ0csT0FBRCxFQUFVRixNQUFWLEVBQXFCO0FBQ3BDUCxXQUFHVSxJQUFILENBQVFMLEdBQVIsRUFBYSxVQUFDTSxHQUFELEVBQVM7QUFDbEIsZ0JBQUlBLEdBQUosRUFBUyxPQUFPSixPQUFPSSxHQUFQLENBQVA7QUFDVCxtQkFBT0YsUUFBUUosR0FBUixDQUFQO0FBQ0gsU0FIRDtBQUlILEtBTE0sQ0FBUDtBQU1IOztBQUVELFNBQVNPLFVBQVQsQ0FBb0JQLEdBQXBCLEVBQXlCO0FBQ3JCLFFBQUksQ0FBQ0osU0FBTCxFQUFnQjtBQUNaLGVBQU9LLFFBQVFDLE1BQVIsQ0FBZSxJQUFJQyxLQUFKLENBQVUsd0NBQVYsQ0FBZixDQUFQO0FBQ0g7QUFDRCxXQUFPLElBQUlGLE9BQUosQ0FBWSxVQUFDRyxPQUFELEVBQVVGLE1BQVYsRUFBcUI7QUFDcENULFdBQUdlLElBQUgsMEJBQStCUixHQUEvQixFQUFzQyxVQUFDTSxHQUFELEVBQU1HLE1BQU4sRUFBaUI7QUFDbkQsZ0JBQUlILEdBQUosRUFBUyxPQUFPSixPQUFPSSxHQUFQLENBQVA7QUFDVCxnQkFBSSxDQUFDLFVBQVVJLElBQVYsQ0FBZUQsTUFBZixDQUFMLEVBQTZCLE9BQU9QLE9BQU8sSUFBSUMsS0FBSixDQUFVTSxPQUFPRSxJQUFQLEVBQVYsQ0FBUCxDQUFQO0FBQzdCUCxvQkFBUUosR0FBUjtBQUNILFNBSkQ7QUFLSCxLQU5NLENBQVA7QUFPSDs7QUFFRDs7Ozs7QUFLQSxTQUFTWSxPQUFULENBQWlCWixHQUFqQixFQUFzQjtBQUNsQixXQUFPSixZQUFZVyxXQUFXUCxHQUFYLENBQVosR0FBOEJELFlBQVlDLEdBQVosQ0FBckM7QUFDSDs7QUFFRGEsT0FBT0MsT0FBUCxHQUFpQkYsT0FBakIiLCJmaWxlIjoia2lsbC1waWQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBjcCA9IHJlcXVpcmUoJ2NoaWxkX3Byb2Nlc3MnKVxuY29uc3QgcHMgPSByZXF1aXJlKCdwcy1ub2RlJylcblxuY29uc3QgaXNXaW5kb3dzID0gcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJ1xuLy8gdXNlIHRoaXMgZnVuY3Rpb24gd2hlbiB3ZSBvbmx5IGhhdmUgYSBwaWQsIGJ1dCBub3QgcHJvY2VzcywgaS5lLixcbi8vIHdlIGNhbid0IGFzc2lnbiBvbignZXhpdCcpIGxpc3RlbmVyXG5mdW5jdGlvbiBraWxsVW5peFBpZChwaWQpIHtcbiAgICBpZiAoaXNXaW5kb3dzKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1RoaXMgZnVuY3Rpb24gaXMgbm90IGF2YWlsYWJsZSBvbiB3aW4nKSlcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgcHMua2lsbChwaWQsIChlcnIpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKVxuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocGlkKVxuICAgICAgICB9KVxuICAgIH0pXG59XG5cbmZ1bmN0aW9uIGtpbGxXaW5QaWQocGlkKSB7XG4gICAgaWYgKCFpc1dpbmRvd3MpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignVGhpcyBmdW5jdGlvbiBpcyBvbmx5IGF2YWlsYWJsZSBvbiB3aW4nKSlcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY3AuZXhlYyhgdGFza2tpbGwgL3QgL0YgL1BJRCAke3BpZH1gLCAoZXJyLCBzdGRvdXQpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKVxuICAgICAgICAgICAgaWYgKCEvU1VDQ0VTUy8udGVzdChzdGRvdXQpKSByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihzdGRvdXQudHJpbSgpKSlcbiAgICAgICAgICAgIHJlc29sdmUocGlkKVxuICAgICAgICB9KVxuICAgIH0pXG59XG5cbi8qKlxuICogS2lsbCBhIHByb2Nlc3MgYnkgcGlkLCBpZiBwb2ludGVyIGlzIG5vdCBhdmFpbGFibGUuXG4gKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IHBpZCBQcm9jZXNzIElEXG4gKiBAcmV0dXJucyB7UHJvbWlzZS48c3RyaW5nfG51bWJlcj59IFByb21pc2UgcmVzb2x2ZWQgd2l0aCB0aGUgcGlkLlxuICovXG5mdW5jdGlvbiBraWxsUGlkKHBpZCkge1xuICAgIHJldHVybiBpc1dpbmRvd3MgPyBraWxsV2luUGlkKHBpZCkgOiBraWxsVW5peFBpZChwaWQpXG59XG5cbm1vZHVsZS5leHBvcnRzID0ga2lsbFBpZFxuIl19 \ No newline at end of file diff --git a/dist/test/spec/begin-ready.js b/dist/test/spec/begin-ready.js new file mode 100644 index 0000000..c3d4a56 --- /dev/null +++ b/dist/test/spec/begin-ready.js @@ -0,0 +1,220 @@ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +require('source-map-support/register'); + +var assert = require('assert'); + +var _require = require('stream'), + Readable = _require.Readable, + Writable = _require.Writable; + +var _require2 = require('../../src/begin-ready'), + createBeginReadyMatchTransformStream = _require2.createBeginReadyMatchTransformStream, + createResolverWriteStream = _require2.createResolverWriteStream, + setupResolveWriteStreamPipe = _require2.setupResolveWriteStreamPipe; + +/** + * Pipe Readable stream in object mode into process.stdout, + * using JSON.stringify to print data. This might results in + * MaxListenersExceededWarning in tests, when process.stdout + * gets assigned a lot of stream listeners such as end, drain, + * error, finish, unpipe, close. + */ +// function debugObjectReadStream(rs, name) { +// rs.pipe(new Transform({ +// objectMode: true, +// transform: (chunk, enc, next) => { +// const s = JSON.stringify(chunk, null, 2) +// console.log(`Some data from ${name} rs: `) +// next(null, `${s}\r\n`) +// }, +// })).pipe(process.stdout) +// } + +var commandNumber = '376080'; +var commandNumber2 = '65754'; + +var data = '\n[{\n "SourceFile": "test/fixtures/CANON/IMG_9857.JPG",\n "ExifToolVersion": 10.25,\n "FileName": "IMG_9857.JPG",\n "Directory": "test/fixtures/CANON",\n "FileSize": "51 kB",\n "FileModifyDate": "2016:05:16 00:25:40+01:00",\n "FileAccessDate": "2016:11:26 01:20:48+00:00",\n "FileInodeChangeDate": "2016:05:16 00:25:40+01:00",\n "FilePermissions": "rw-r--r--",\n "FileType": "JPEG",\n "FileTypeExtension": "jpg",\n "MIMEType": "image/jpeg",\n "XMPToolkit": "Image::ExifTool 10.11",\n "CreatorWorkURL": "https://sobesednik.media",\n "Scene": "011200",\n "Creator": "Photographer Name",\n "ImageWidth": 500,\n "ImageHeight": 333,\n "EncodingProcess": "Baseline DCT, Huffman coding",\n "BitsPerSample": 8,\n "ColorComponents": 3,\n "YCbCrSubSampling": "YCbCr4:2:0 (2 2)",\n "ImageSize": "500x333",\n "Megapixels": 0.167\n}]\n'.trim(); + +var data2 = 'File not found: test/fixtures/no_such_file2.jpg'; + +var s = ('\n{begin' + commandNumber + '}\n' + data + '\n{ready' + commandNumber + '}\n').trim(); + +var s2 = ('\n{begin' + commandNumber2 + '}\n' + data2 + '\n{ready' + commandNumber2 + '}\n').trim(); +var exiftoolOutput = ('\n' + s + '\n' + s2 + '\n').trim(); + +var brtsTestSuite = { + createBeginReadyMatchTransformStream: { + 'should transform match data': function shouldTransformMatchData() { + var rs = new Readable({ objectMode: true }); + rs._read = function () { + var match = { + 1: commandNumber, + 2: data + }; + var match2 = { + 1: commandNumber2, + 2: data2 + }; + rs.push(match); + rs.push(match2); + rs.push(null); + }; + var brts = createBeginReadyMatchTransformStream(); + + return new Promise(function (resolve, reject) { + var ws = new Writable({ objectMode: true }); + var data = []; + ws._write = function (chunk, enc, next) { + data.push(chunk); + next(); + }; + ws.on('finish', function () { + resolve(data); + }); + ws.on('error', reject); + rs.pipe(brts).pipe(ws); + }).then(function (res) { + assert.equal(res.length, 2); + + var _res = _slicedToArray(res, 2), + output = _res[0], + output2 = _res[1]; + + assert.equal(output.cn, commandNumber); + assert.equal(output.d, data); + assert.equal(output2.cn, commandNumber2); + assert.equal(output2.d, data2); + }); + } + }, + createResolverWriteStream: { + 'should have _resolveMap property': function shouldHave_resolveMapProperty() { + var rws = createResolverWriteStream(); + assert.equal(_typeof(rws._resolveMap), 'object'); + }, + 'should have addToResolveMap function': function shouldHaveAddToResolveMapFunction() { + var rws = createResolverWriteStream(); + assert.equal(_typeof(rws.addToResolveMap), 'function'); + }, + 'should add resolve function to the map': function shouldAddResolveFunctionToTheMap() { + var rws = createResolverWriteStream(); + var handler = function handler() {}; + rws.addToResolveMap(commandNumber, handler); + assert.strictEqual(rws._resolveMap[commandNumber], handler); + }, + 'should throw an error when resolve is not a function': function shouldThrowAnErrorWhenResolveIsNotAFunction() { + var rws = createResolverWriteStream(); + assert.throws(function () { + return rws.addToResolveMap(commandNumber); + }, /resolve argument must be a function/); + }, + 'should throw an error when commandNumber is not a string': function shouldThrowAnErrorWhenCommandNumberIsNotAString() { + var rws = createResolverWriteStream(); + assert.throws(function () { + return rws.addToResolveMap(); + }, /commandNumber argument must be a string/); + }, + 'should throw an error when key already exists in the map': function shouldThrowAnErrorWhenKeyAlreadyExistsInTheMap() { + var rws = createResolverWriteStream(); + var handler = function handler() {}; + rws.addToResolveMap(commandNumber, handler); + assert.throws(function () { + return rws.addToResolveMap(commandNumber, handler); + }, /Command with the same number is already expected/); + }, + 'should call resolve and delete entry from resolveMap on data': function shouldCallResolveAndDeleteEntryFromResolveMapOnData() { + var rs = new Readable({ objectMode: true }); + rs._read = function () { + rs.push({ + cn: commandNumber, + d: data + }); + rs.push({ + cn: commandNumber2, + d: data2 + }); + rs.push(null); + }; + var results = []; + var handler = function handler(data) { + return results.push(data); + }; + var rws = createResolverWriteStream(); + rws.addToResolveMap(commandNumber, handler); + rws.addToResolveMap(commandNumber2, handler); + + rs.pipe(rws); + + return new Promise(function (resolve) { + return rws.on('finish', resolve); + }).then(function () { + assert.equal(results.length, 2); + assert.equal(results[0], data); + assert.equal(results[1], data2); + assert(!Object.keys(rws._resolveMap).length); + }); + }, + 'should call next with an error when command number cannot be found': function shouldCallNextWithAnErrorWhenCommandNumberCannotBeFound() { + var rs = new Readable({ objectMode: true }); + rs._read = function () { + rs.push({ + cn: commandNumber, + d: data + }); + rs.push({ + cn: commandNumber2, + d: data2 + }); + rs.push(null); + }; + var results = []; + var handler = function handler(data) { + return results.push(data); + }; + var rws = createResolverWriteStream(); + rws.addToResolveMap(commandNumber, handler); + + rs.pipe(rws); + + return new Promise(function (resolve) { + return rws.on('error', resolve); + }).then(function (err) { + assert.equal(err.message, 'Command with index ' + commandNumber2 + ' not found'); + assert.equal(results.length, 1); + assert.equal(results[0], data); + }); + } + }, + setupResolveWriteStreamPipe: { + 'should pipe exiftool data and call resolve functions': function shouldPipeExiftoolDataAndCallResolveFunctions() { + var rs = new Readable(); + rs._read = function () { + rs.push(exiftoolOutput); + rs.push(null); + }; + var results = []; + var rws = setupResolveWriteStreamPipe(rs); + rws.addToResolveMap(commandNumber, function (data) { + return results.push(data); + }); + rws.addToResolveMap(commandNumber2, function (data) { + return results.push(data); + }); + return new Promise(function (resolve) { + return rws.on('finish', resolve); + }).then(function () { + assert.equal(results.length, 2); + assert.equal(results[0], data); + assert.equal(results[1], data2); + }); + } + } +}; + +module.exports = brtsTestSuite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9iZWdpbi1yZWFkeS5qcyJdLCJuYW1lcyI6WyJhc3NlcnQiLCJyZXF1aXJlIiwiUmVhZGFibGUiLCJXcml0YWJsZSIsImNyZWF0ZUJlZ2luUmVhZHlNYXRjaFRyYW5zZm9ybVN0cmVhbSIsImNyZWF0ZVJlc29sdmVyV3JpdGVTdHJlYW0iLCJzZXR1cFJlc29sdmVXcml0ZVN0cmVhbVBpcGUiLCJjb21tYW5kTnVtYmVyIiwiY29tbWFuZE51bWJlcjIiLCJkYXRhIiwidHJpbSIsImRhdGEyIiwicyIsInMyIiwiZXhpZnRvb2xPdXRwdXQiLCJicnRzVGVzdFN1aXRlIiwicnMiLCJvYmplY3RNb2RlIiwiX3JlYWQiLCJtYXRjaCIsIm1hdGNoMiIsInB1c2giLCJicnRzIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJ3cyIsIl93cml0ZSIsImNodW5rIiwiZW5jIiwibmV4dCIsIm9uIiwicGlwZSIsInRoZW4iLCJyZXMiLCJlcXVhbCIsImxlbmd0aCIsIm91dHB1dCIsIm91dHB1dDIiLCJjbiIsImQiLCJyd3MiLCJfcmVzb2x2ZU1hcCIsImFkZFRvUmVzb2x2ZU1hcCIsImhhbmRsZXIiLCJzdHJpY3RFcXVhbCIsInRocm93cyIsInJlc3VsdHMiLCJPYmplY3QiLCJrZXlzIiwiZXJyIiwibWVzc2FnZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUEsSUFBTUEsU0FBU0MsUUFBUSxRQUFSLENBQWY7O2VBQytCQSxRQUFRLFFBQVIsQztJQUF2QkMsUSxZQUFBQSxRO0lBQVVDLFEsWUFBQUEsUTs7Z0JBS2RGLFFBQVEsdUJBQVIsQztJQUhBRyxvQyxhQUFBQSxvQztJQUNBQyx5QixhQUFBQSx5QjtJQUNBQywyQixhQUFBQSwyQjs7QUFHSjs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLElBQU1DLGdCQUFnQixRQUF0QjtBQUNB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b0JuQyxjQUFwQixFQUFvQyxVQUFDQyxJQUFEO0FBQUEsdUJBQVVzQyxRQUFRMUIsSUFBUixDQUFhWixJQUFiLENBQVY7QUFBQSxhQUFwQztBQUNBLG1CQUFPLElBQUljLE9BQUosQ0FBWTtBQUFBLHVCQUFXa0IsSUFBSVYsRUFBSixDQUFPLFFBQVAsRUFBaUJQLE9BQWpCLENBQVg7QUFBQSxhQUFaLEVBQ0ZTLElBREUsQ0FDRyxZQUFNO0FBQ1JqQyx1QkFBT21DLEtBQVAsQ0FBYVksUUFBUVgsTUFBckIsRUFBNkIsQ0FBN0I7QUFDQXBDLHVCQUFPbUMsS0FBUCxDQUFhWSxRQUFRLENBQVIsQ0FBYixFQUF5QnRDLElBQXpCO0FBQ0FULHVCQUFPbUMsS0FBUCxDQUFhWSxRQUFRLENBQVIsQ0FBYixFQUF5QnBDLEtBQXpCO0FBQ0gsYUFMRSxDQUFQO0FBTUg7QUFqQndCO0FBdklYLENBQXRCOztBQTRKQXlDLE9BQU9DLE9BQVAsR0FBaUJ0QyxhQUFqQiIsImZpbGUiOiJiZWdpbi1yZWFkeS5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpXG5jb25zdCB7IFJlYWRhYmxlLCBXcml0YWJsZSB9ID0gcmVxdWlyZSgnc3RyZWFtJylcbmNvbnN0IHtcbiAgICBjcmVhdGVCZWdpblJlYWR5TWF0Y2hUcmFuc2Zvcm1TdHJlYW0sXG4gICAgY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbSxcbiAgICBzZXR1cFJlc29sdmVXcml0ZVN0cmVhbVBpcGUsXG59ID0gcmVxdWlyZSgnLi4vLi4vc3JjL2JlZ2luLXJlYWR5JylcblxuLyoqXG4gKiBQaXBlIFJlYWRhYmxlIHN0cmVhbSBpbiBvYmplY3QgbW9kZSBpbnRvIHByb2Nlc3Muc3Rkb3V0LFxuICogdXNpbmcgSlNPTi5zdHJpbmdpZnkgdG8gcHJpbnQgZGF0YS4gVGhpcyBtaWdodCByZXN1bHRzIGluXG4gKiBNYXhMaXN0ZW5lcnNFeGNlZWRlZFdhcm5pbmcgaW4gdGVzdHMsIHdoZW4gcHJvY2Vzcy5zdGRvdXRcbiAqIGdldHMgYXNzaWduZWQgYSBsb3Qgb2Ygc3RyZWFtIGxpc3RlbmVycyBzdWNoIGFzIGVuZCwgZHJhaW4sXG4gKiBlcnJvciwgZmluaXNoLCB1bnBpcGUsIGNsb3NlLlxuICovXG4vLyBmdW5jdGlvbiBkZWJ1Z09iamVjdFJlYWRTdHJlYW0ocnMsIG5hbWUpIHtcbi8vICAgICBycy5waXBlKG5ldyBUcmFuc2Zvcm0oe1xuLy8gICAgICAgICBvYmplY3RNb2RlOiB0cnVlLFxuLy8gICAgICAgICB0cmFuc2Zvcm06IChjaHVuaywgZW5jLCBuZXh0KSA9PiB7XG4vLyAgICAgICAgICAgICBjb25zdCBzID0gSlNPTi5zdHJpbmdpZnkoY2h1bmssIG51bGwsIDIpXG4vLyAgICAgICAgICAgICBjb25zb2xlLmxvZyhgU29tZSBkYXRhIGZyb20gJHtuYW1lfSByczogYClcbi8vICAgICAgICAgICAgIG5leHQobnVsbCwgYCR7c31cXHJcXG5gKVxuLy8gICAgICAgICB9LFxuLy8gICAgIH0pKS5waXBlKHByb2Nlc3Muc3Rkb3V0KVxuLy8gfVxuXG5jb25zdCBjb21tYW5kTnVtYmVyID0gJzM3NjA4MCdcbmNvbnN0IGNvbW1hbmROdW1iZXIyID0gJzY1NzU0J1xuXG5jb25zdCBkYXRhID0gYFxuW3tcbiAgXCJTb3VyY2VGaWxlXCI6IFwidGVzdC9maXh0dXJlcy9DQU5PTi9JTUdfOTg1Ny5KUEdcIixcbiAgXCJFeGlmVG9vbFZlcnNpb25cIjogMTAuMjUsXG4gIFwiRmlsZU5hbWVcIjogXCJJTUdfOTg1Ny5KUEdcIixcbiAgXCJEaXJlY3RvcnlcIjogXCJ0ZXN0L2ZpeHR1cmVzL0NBTk9OXCIsXG4gIFwiRmlsZVNpemVcIjogXCI1MSBrQlwiLFxuICBcIkZpbGVNb2RpZnlEYXRlXCI6IFwiMjAxNjowNToxNiAwMDoyNTo0MCswMTowMFwiLFxuICBcIkZpbGVBY2Nlc3NEYXRlXCI6IFwiMjAxNjoxMToyNiAwMToyMDo0OCswMDowMFwiLFxuICBcIkZpbGVJbm9kZUNoYW5nZURhdGVcIjogXCIyMDE2OjA1OjE2IDAwOjI1OjQwKzAxOjAwXCIsXG4gIFwiRmlsZVBlcm1pc3Npb25zXCI6IFwicnctci0tci0tXCIsXG4gIFwiRmlsZVR5cGVcIjogXCJKUEVHXCIsXG4gIFwiRmlsZVR5cGVFeHRlbnNpb25cIjogXCJqcGdcIixcbiAgXCJNSU1FVHlwZVwiOiBcImltYWdlL2pwZWdcIixcbiAgXCJYTVBUb29sa2l0XCI6IFwiSW1hZ2U6OkV4aWZUb29sIDEwLjExXCIsXG4gIFwiQ3JlYXRvcldvcmtVUkxcIjogXCJodHRwczovL3NvYmVzZWRuaWsubWVkaWFcIixcbiAgXCJTY2VuZVwiOiBcIjAxMTIwMFwiLFxuICBcIkNyZWF0b3JcIjogXCJQaG90b2dyYXBoZXIgTmFtZVwiLFxuICBcIkltYWdlV2lkdGhcIjogNTAwLFxuICBcIkltYWdlSGVpZ2h0XCI6IDMzMyxcbiAgXCJFbmNvZGluZ1Byb2Nlc3NcIjogXCJCYXNlbGluZSBEQ1QsIEh1ZmZtYW4gY29kaW5nXCIsXG4gIFwiQml0c1BlclNhbXBsZVwiOiA4LFxuICBcIkNvbG9yQ29tcG9uZW50c1wiOiAzLFxuICBcIllDYkNyU3ViU2FtcGxpbmdcIjogXCJZQ2JDcjQ6MjowICgyIDIpXCIsXG4gIFwiSW1hZ2VTaXplXCI6IFwiNTAweDMzM1wiLFxuICBcIk1lZ2FwaXhlbHNcIjogMC4xNjdcbn1dXG5gXG4gICAgLnRyaW0oKVxuXG5jb25zdCBkYXRhMiA9ICdGaWxlIG5vdCBmb3VuZDogdGVzdC9maXh0dXJlcy9ub19zdWNoX2ZpbGUyLmpwZydcblxuY29uc3QgcyA9IGBcbntiZWdpbiR7Y29tbWFuZE51bWJlcn19XG4ke2RhdGF9XG57cmVhZHkke2NvbW1hbmROdW1iZXJ9fVxuYFxuICAgIC50cmltKClcblxuY29uc3QgczIgPSBgXG57YmVnaW4ke2NvbW1hbmROdW1iZXIyfX1cbiR7ZGF0YTJ9XG57cmVhZHkke2NvbW1hbmROdW1iZXIyfX1cbmBcbiAgICAudHJpbSgpXG5jb25zdCBleGlmdG9vbE91dHB1dCA9IGBcbiR7c31cbiR7czJ9XG5gXG4gICAgLnRyaW0oKVxuXG5jb25zdCBicnRzVGVzdFN1aXRlID0ge1xuICAgIGNyZWF0ZUJlZ2luUmVhZHlNYXRjaFRyYW5zZm9ybVN0cmVhbToge1xuICAgICAgICAnc2hvdWxkIHRyYW5zZm9ybSBtYXRjaCBkYXRhJzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcnMgPSBuZXcgUmVhZGFibGUoeyBvYmplY3RNb2RlOiB0cnVlIH0pXG4gICAgICAgICAgICBycy5fcmVhZCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXRjaCA9IHtcbiAgICAgICAgICAgICAgICAgICAgMTogY29tbWFuZE51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgMjogZGF0YSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgbWF0Y2gyID0ge1xuICAgICAgICAgICAgICAgICAgICAxOiBjb21tYW5kTnVtYmVyMixcbiAgICAgICAgICAgICAgICAgICAgMjogZGF0YTIsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJzLnB1c2gobWF0Y2gpXG4gICAgICAgICAgICAgICAgcnMucHVzaChtYXRjaDIpXG4gICAgICAgICAgICAgICAgcnMucHVzaChudWxsKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYnJ0cyA9IGNyZWF0ZUJlZ2luUmVhZHlNYXRjaFRyYW5zZm9ybVN0cmVhbSgpXG5cbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgd3MgPSBuZXcgV3JpdGFibGUoeyBvYmplY3RNb2RlOiB0cnVlIH0pXG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IFtdXG4gICAgICAgICAgICAgICAgd3MuX3dyaXRlID0gKGNodW5rLCBlbmMsIG5leHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5wdXNoKGNodW5rKVxuICAgICAgICAgICAgICAgICAgICBuZXh0KClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgd3Mub24oJ2ZpbmlzaCcsICgpID0+IHsgcmVzb2x2ZShkYXRhKSB9KVxuICAgICAgICAgICAgICAgIHdzLm9uKCdlcnJvcicsIHJlamVjdClcbiAgICAgICAgICAgICAgICBycy5waXBlKGJydHMpLnBpcGUod3MpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5sZW5ndGgsIDIpXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IFtvdXRwdXQsIG91dHB1dDJdID0gcmVzXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChvdXRwdXQuY24sIGNvbW1hbmROdW1iZXIpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChvdXRwdXQuZCwgZGF0YSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKG91dHB1dDIuY24sIGNvbW1hbmROdW1iZXIyKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwob3V0cHV0Mi5kLCBkYXRhMilcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgIH0sXG4gICAgY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbToge1xuICAgICAgICAnc2hvdWxkIGhhdmUgX3Jlc29sdmVNYXAgcHJvcGVydHknOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByd3MgPSBjcmVhdGVSZXNvbHZlcldyaXRlU3RyZWFtKClcbiAgICAgICAgICAgIGFzc2VydC5lcXVhbCh0eXBlb2YgcndzLl9yZXNvbHZlTWFwLCAnb2JqZWN0JylcbiAgICAgICAgfSxcbiAgICAgICAgJ3Nob3VsZCBoYXZlIGFkZFRvUmVzb2x2ZU1hcCBmdW5jdGlvbic6ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJ3cyA9IGNyZWF0ZVJlc29sdmVyV3JpdGVTdHJlYW0oKVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHR5cGVvZiByd3MuYWRkVG9SZXNvbHZlTWFwLCAnZnVuY3Rpb24nKVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIGFkZCByZXNvbHZlIGZ1bmN0aW9uIHRvIHRoZSBtYXAnOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByd3MgPSBjcmVhdGVSZXNvbHZlcldyaXRlU3RyZWFtKClcbiAgICAgICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoKSA9PiB7fVxuICAgICAgICAgICAgcndzLmFkZFRvUmVzb2x2ZU1hcChjb21tYW5kTnVtYmVyLCBoYW5kbGVyKVxuICAgICAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJ3cy5fcmVzb2x2ZU1hcFtjb21tYW5kTnVtYmVyXSwgaGFuZGxlcilcbiAgICAgICAgfSxcbiAgICAgICAgJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciB3aGVuIHJlc29sdmUgaXMgbm90IGEgZnVuY3Rpb24nOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByd3MgPSBjcmVhdGVSZXNvbHZlcldyaXRlU3RyZWFtKClcbiAgICAgICAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICAgICAgICAgKCkgPT4gcndzLmFkZFRvUmVzb2x2ZU1hcChjb21tYW5kTnVtYmVyKSxcbiAgICAgICAgICAgICAgICAvcmVzb2x2ZSBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24vXG4gICAgICAgICAgICApXG4gICAgICAgIH0sXG4gICAgICAgICdzaG91bGQgdGhyb3cgYW4gZXJyb3Igd2hlbiBjb21tYW5kTnVtYmVyIGlzIG5vdCBhIHN0cmluZyc6ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJ3cyA9IGNyZWF0ZVJlc29sdmVyV3JpdGVTdHJlYW0oKVxuICAgICAgICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgICAgICAgICAoKSA9PiByd3MuYWRkVG9SZXNvbHZlTWFwKCksXG4gICAgICAgICAgICAgICAgL2NvbW1hbmROdW1iZXIgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZy9cbiAgICAgICAgICAgIClcbiAgICAgICAgfSxcbiAgICAgICAgJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciB3aGVuIGtleSBhbHJlYWR5IGV4aXN0cyBpbiB0aGUgbWFwJzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcndzID0gY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbSgpXG4gICAgICAgICAgICBjb25zdCBoYW5kbGVyID0gKCkgPT4ge31cbiAgICAgICAgICAgIHJ3cy5hZGRUb1Jlc29sdmVNYXAoY29tbWFuZE51bWJlciwgaGFuZGxlcilcbiAgICAgICAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICAgICAgICAgKCkgPT4gcndzLmFkZFRvUmVzb2x2ZU1hcChjb21tYW5kTnVtYmVyLCBoYW5kbGVyKSxcbiAgICAgICAgICAgICAgICAvQ29tbWFuZCB3aXRoIHRoZSBzYW1lIG51bWJlciBpcyBhbHJlYWR5IGV4cGVjdGVkL1xuICAgICAgICAgICAgKVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIGNhbGwgcmVzb2x2ZSBhbmQgZGVsZXRlIGVudHJ5IGZyb20gcmVzb2x2ZU1hcCBvbiBkYXRhJzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcnMgPSBuZXcgUmVhZGFibGUoeyBvYmplY3RNb2RlOiB0cnVlfSlcbiAgICAgICAgICAgIHJzLl9yZWFkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbjogY29tbWFuZE51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgZDogZGF0YSxcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIHJzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbjogY29tbWFuZE51bWJlcjIsXG4gICAgICAgICAgICAgICAgICAgIGQ6IGRhdGEyLFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgcnMucHVzaChudWxsKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0cyA9IFtdXG4gICAgICAgICAgICBjb25zdCBoYW5kbGVyID0gKGRhdGEpID0+IHJlc3VsdHMucHVzaChkYXRhKVxuICAgICAgICAgICAgY29uc3QgcndzID0gY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbSgpXG4gICAgICAgICAgICByd3MuYWRkVG9SZXNvbHZlTWFwKGNvbW1hbmROdW1iZXIsIGhhbmRsZXIpXG4gICAgICAgICAgICByd3MuYWRkVG9SZXNvbHZlTWFwKGNvbW1hbmROdW1iZXIyLCBoYW5kbGVyKVxuXG4gICAgICAgICAgICBycy5waXBlKHJ3cylcblxuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gcndzLm9uKCdmaW5pc2gnLCByZXNvbHZlKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXN1bHRzLmxlbmd0aCwgMilcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc3VsdHNbMF0sIGRhdGEpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXN1bHRzWzFdLCBkYXRhMilcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KCFPYmplY3Qua2V5cyhyd3MuX3Jlc29sdmVNYXApLmxlbmd0aClcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIGNhbGwgbmV4dCB3aXRoIGFuIGVycm9yIHdoZW4gY29tbWFuZCBudW1iZXIgY2Fubm90IGJlIGZvdW5kJzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcnMgPSBuZXcgUmVhZGFibGUoeyBvYmplY3RNb2RlOiB0cnVlfSlcbiAgICAgICAgICAgIHJzLl9yZWFkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbjogY29tbWFuZE51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgZDogZGF0YSxcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIHJzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbjogY29tbWFuZE51bWJlcjIsXG4gICAgICAgICAgICAgICAgICAgIGQ6IGRhdGEyLFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgcnMucHVzaChudWxsKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0cyA9IFtdXG4gICAgICAgICAgICBjb25zdCBoYW5kbGVyID0gKGRhdGEpID0+IHJlc3VsdHMucHVzaChkYXRhKVxuICAgICAgICAgICAgY29uc3QgcndzID0gY3JlYXRlUmVzb2x2ZXJXcml0ZVN0cmVhbSgpXG4gICAgICAgICAgICByd3MuYWRkVG9SZXNvbHZlTWFwKGNvbW1hbmROdW1iZXIsIGhhbmRsZXIpXG5cbiAgICAgICAgICAgIHJzLnBpcGUocndzKVxuXG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiByd3Mub24oJ2Vycm9yJywgcmVzb2x2ZSkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwoZXJyLm1lc3NhZ2UsIGBDb21tYW5kIHdpdGggaW5kZXggJHtjb21tYW5kTnVtYmVyMn0gbm90IGZvdW5kYClcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc3VsdHMubGVuZ3RoLCAxKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzdWx0c1swXSwgZGF0YSlcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgIH0sXG4gICAgc2V0dXBSZXNvbHZlV3JpdGVTdHJlYW1QaXBlOiB7XG4gICAgICAgICdzaG91bGQgcGlwZSBleGlmdG9vbCBkYXRhIGFuZCBjYWxsIHJlc29sdmUgZnVuY3Rpb25zJzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcnMgPSBuZXcgUmVhZGFibGVcbiAgICAgICAgICAgIHJzLl9yZWFkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJzLnB1c2goZXhpZnRvb2xPdXRwdXQpXG4gICAgICAgICAgICAgICAgcnMucHVzaChudWxsKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0cyA9IFtdXG4gICAgICAgICAgICBjb25zdCByd3MgPSBzZXR1cFJlc29sdmVXcml0ZVN0cmVhbVBpcGUocnMpXG4gICAgICAgICAgICByd3MuYWRkVG9SZXNvbHZlTWFwKGNvbW1hbmROdW1iZXIsIChkYXRhKSA9PiByZXN1bHRzLnB1c2goZGF0YSkpXG4gICAgICAgICAgICByd3MuYWRkVG9SZXNvbHZlTWFwKGNvbW1hbmROdW1iZXIyLCAoZGF0YSkgPT4gcmVzdWx0cy5wdXNoKGRhdGEpKVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gcndzLm9uKCdmaW5pc2gnLCByZXNvbHZlKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXN1bHRzLmxlbmd0aCwgMilcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc3VsdHNbMF0sIGRhdGEpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXN1bHRzWzFdLCBkYXRhMilcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgIH0sXG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnJ0c1Rlc3RTdWl0ZVxuIl19 \ No newline at end of file diff --git a/dist/test/spec/codedcharacterset.js b/dist/test/spec/codedcharacterset.js new file mode 100644 index 0000000..7dc12f0 --- /dev/null +++ b/dist/test/spec/codedcharacterset.js @@ -0,0 +1,53 @@ +'use strict'; + +require('source-map-support/register'); + +var assert = require('assert'); + +var _require = require('os'), + EOL = _require.EOL; + +var context = require('exiftool-context'); +var exiftool = require('../../src/'); +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +var metadata = { + all: '', // remove all metadata at first + Title: 'åäö', + LocalCaption: 'local caption', + 'Caption-Abstract': 'C\xE2pt\xEF\xF6n \xC3bstr\xE1ct: \xE5\xE4\xF6', + Copyright: '2017 ©', + 'Keywords+': ['k\xEByw\xF4rd \xC3\u2026', 'keywórdB ©˙µå≥'], + Creator: 'Mr Author', + Rating: 5 +}; + +var IPTCEncoding = { + context: context, + 'should raise a warning when codedcharacterset=utf8 not provided for IPTC tags': function shouldRaiseAWarningWhenCodedcharactersetUtf8NotProvidedForIPTCTags(ctx) { + return ctx.createTempFile().then(function () { + return ctx.initAndWriteMetadata(ctx.tempFile, metadata); + }).then(function (res) { + assert.equal(res.data, null); + var expected = 'Warning: Some character(s) could not be encoded in Latin - ' + ctx.replaceSlashes(ctx.tempFile) + EOL + ' 1 image files updated'; + assert.equal(res.error, expected); + }); + }, + 'should successfully update the file when codedcharacterset=utf8 passed': function shouldSuccessfullyUpdateTheFileWhenCodedcharactersetUtf8Passed(ctx) { + var args = ['codedcharacterset=utf8']; + return ctx.createTempFile().then(function () { + return ctx.initAndWriteMetadata(ctx.tempFile, metadata, args); + }).then(function (res) { + assert.equal(res.data, null); + var expected = '1 image files updated'; + assert.equal(res.error, expected); + }); + } +}; + +module.exports = { + codedcharacterset: { + IPTCEncoding: IPTCEncoding + } +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9jb2RlZGNoYXJhY3RlcnNldC5qcyJdLCJuYW1lcyI6WyJhc3NlcnQiLCJyZXF1aXJlIiwiRU9MIiwiY29udGV4dCIsImV4aWZ0b29sIiwiZ2xvYmFsRXhpZnRvb2xDb25zdHJ1Y3RvciIsIkV4aWZ0b29sUHJvY2VzcyIsIm1ldGFkYXRhIiwiYWxsIiwiVGl0bGUiLCJMb2NhbENhcHRpb24iLCJDb3B5cmlnaHQiLCJDcmVhdG9yIiwiUmF0aW5nIiwiSVBUQ0VuY29kaW5nIiwiY3R4IiwiY3JlYXRlVGVtcEZpbGUiLCJ0aGVuIiwiaW5pdEFuZFdyaXRlTWV0YWRhdGEiLCJ0ZW1wRmlsZSIsInJlcyIsImVxdWFsIiwiZGF0YSIsImV4cGVjdGVkIiwicmVwbGFjZVNsYXNoZXMiLCJlcnJvciIsImFyZ3MiLCJtb2R1bGUiLCJleHBvcnRzIiwiY29kZWRjaGFyYWN0ZXJzZXQiXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxJQUFNQSxTQUFTQyxRQUFRLFFBQVIsQ0FBZjs7ZUFDZ0JBLFFBQVEsSUFBUixDO0lBQVJDLEcsWUFBQUEsRzs7QUFDUixJQUFNQyxVQUFVRixRQUFRLGtCQUFSLENBQWhCO0FBQ0EsSUFBTUcsV0FBV0gsUUFBUSxZQUFSLENBQWpCO0FBQ0FFLFFBQVFFLHlCQUFSLEdBQW9DRCxTQUFTRSxlQUE3Qzs7QUFFQSxJQUFNQyxXQUFXO0FBQ2JDLFNBQUssRUFEUSxFQUNKO0FBQ1RDLFdBQU8sS0FGTTtBQUdiQyxrQkFBYyxlQUhEO0FBSWIsd0JBQW9CLCtDQUpQO0FBS2JDLGVBQVcsUUFMRTtBQU1iLGlCQUFhLENBQUUsMEJBQUYsRUFBcUIsZ0JBQXJCLENBTkE7QUFPYkMsYUFBUyxXQVBJO0FBUWJDLFlBQVE7QUFSSyxDQUFqQjs7QUFXQSxJQUFNQyxlQUFlO0FBQ2pCWCxvQkFEaUI7QUFFakIscUZBQWlGLDRFQUFDWSxHQUFELEVBQVM7QUFDdEYsZUFBT0EsSUFBSUMsY0FBSixHQUNGQyxJQURFLENBQ0c7QUFBQSxtQkFBTUYsSUFBSUcsb0JBQUosQ0FBeUJILElBQUlJLFFBQTdCLEVBQXVDWixRQUF2QyxDQUFOO0FBQUEsU0FESCxFQUVGVSxJQUZFLENBRUcsVUFBQ0csR0FBRCxFQUFTO0FBQ1hwQixtQkFBT3FCLEtBQVAsQ0FBYUQsSUFBSUUsSUFBakIsRUFBdUIsSUFBdkI7QUFDQSxnQkFBTUMsMkVBQ2pCUixJQUFJUyxjQUFKLENBQW1CVCxJQUFJSSxRQUF2QixDQURpQixHQUNrQmpCLEdBRGxCLDhCQUFOO0FBR0FGLG1CQUFPcUIsS0FBUCxDQUFhRCxJQUFJSyxLQUFqQixFQUF3QkYsUUFBeEI7QUFDSCxTQVJFLENBQVA7QUFTSCxLQVpnQjtBQWFqQiw4RUFBMEUsd0VBQUNSLEdBQUQsRUFBUztBQUMvRSxZQUFNVyxPQUFPLENBQUMsd0JBQUQsQ0FBYjtBQUNBLGVBQU9YLElBQUlDLGNBQUosR0FDRkMsSUFERSxDQUNHO0FBQUEsbUJBQU1GLElBQUlHLG9CQUFKLENBQXlCSCxJQUFJSSxRQUE3QixFQUF1Q1osUUFBdkMsRUFBaURtQixJQUFqRCxDQUFOO0FBQUEsU0FESCxFQUVGVCxJQUZFLENBRUcsVUFBQ0csR0FBRCxFQUFTO0FBQ1hwQixtQkFBT3FCLEtBQVAsQ0FBYUQsSUFBSUUsSUFBakIsRUFBdUIsSUFBdkI7QUFDQSxnQkFBTUMsV0FBVyx1QkFBakI7QUFDQXZCLG1CQUFPcUIsS0FBUCxDQUFhRCxJQUFJSyxLQUFqQixFQUF3QkYsUUFBeEI7QUFDSCxTQU5FLENBQVA7QUFPSDtBQXRCZ0IsQ0FBckI7O0FBeUJBSSxPQUFPQyxPQUFQLEdBQWlCO0FBQ2JDLHVCQUFtQjtBQUNmZjtBQURlO0FBRE4sQ0FBakIiLCJmaWxlIjoiY29kZWRjaGFyYWN0ZXJzZXQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBhc3NlcnQgPSByZXF1aXJlKCdhc3NlcnQnKVxuY29uc3QgeyBFT0wgfSA9IHJlcXVpcmUoJ29zJylcbmNvbnN0IGNvbnRleHQgPSByZXF1aXJlKCdleGlmdG9vbC1jb250ZXh0JylcbmNvbnN0IGV4aWZ0b29sID0gcmVxdWlyZSgnLi4vLi4vc3JjLycpXG5jb250ZXh0Lmdsb2JhbEV4aWZ0b29sQ29uc3RydWN0b3IgPSBleGlmdG9vbC5FeGlmdG9vbFByb2Nlc3NcblxuY29uc3QgbWV0YWRhdGEgPSB7XG4gICAgYWxsOiAnJywgLy8gcmVtb3ZlIGFsbCBtZXRhZGF0YSBhdCBmaXJzdFxuICAgIFRpdGxlOiAnw6XDpMO2JyxcbiAgICBMb2NhbENhcHRpb246ICdsb2NhbCBjYXB0aW9uJyxcbiAgICAnQ2FwdGlvbi1BYnN0cmFjdCc6ICdDw6JwdMOvw7ZuIFxcdTAwQzNic3Ryw6FjdDogw6XDpMO2JyxcbiAgICBDb3B5cmlnaHQ6ICcyMDE3IMKpJyxcbiAgICAnS2V5d29yZHMrJzogWyAna8OreXfDtHJkIFxcdTAwQzPigKYnLCAna2V5d8OzcmRCIMKpy5nCtcOl4omlJyBdLFxuICAgIENyZWF0b3I6ICdNciBBdXRob3InLFxuICAgIFJhdGluZzogNSxcbn1cblxuY29uc3QgSVBUQ0VuY29kaW5nID0ge1xuICAgIGNvbnRleHQsXG4gICAgJ3Nob3VsZCByYWlzZSBhIHdhcm5pbmcgd2hlbiBjb2RlZGNoYXJhY3RlcnNldD11dGY4IG5vdCBwcm92aWRlZCBmb3IgSVBUQyB0YWdzJzogKGN0eCkgPT4ge1xuICAgICAgICByZXR1cm4gY3R4LmNyZWF0ZVRlbXBGaWxlKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IGN0eC5pbml0QW5kV3JpdGVNZXRhZGF0YShjdHgudGVtcEZpbGUsIG1ldGFkYXRhKSlcbiAgICAgICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmRhdGEsIG51bGwpXG4gICAgICAgICAgICAgICAgY29uc3QgZXhwZWN0ZWQgPSBgV2FybmluZzogU29tZSBjaGFyYWN0ZXIocykgY291bGQgbm90IGJlIGVuY29kZWQgaW4gTGF0aW5cXFxuIC0gJHtjdHgucmVwbGFjZVNsYXNoZXMoY3R4LnRlbXBGaWxlKX0ke0VPTH1cXFxuICAgIDEgaW1hZ2UgZmlsZXMgdXBkYXRlZGBcbiAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmVycm9yLCBleHBlY3RlZClcbiAgICAgICAgICAgIH0pXG4gICAgfSxcbiAgICAnc2hvdWxkIHN1Y2Nlc3NmdWxseSB1cGRhdGUgdGhlIGZpbGUgd2hlbiBjb2RlZGNoYXJhY3RlcnNldD11dGY4IHBhc3NlZCc6IChjdHgpID0+IHtcbiAgICAgICAgY29uc3QgYXJncyA9IFsnY29kZWRjaGFyYWN0ZXJzZXQ9dXRmOCddXG4gICAgICAgIHJldHVybiBjdHguY3JlYXRlVGVtcEZpbGUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gY3R4LmluaXRBbmRXcml0ZU1ldGFkYXRhKGN0eC50ZW1wRmlsZSwgbWV0YWRhdGEsIGFyZ3MpKVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXMuZGF0YSwgbnVsbClcbiAgICAgICAgICAgICAgICBjb25zdCBleHBlY3RlZCA9ICcxIGltYWdlIGZpbGVzIHVwZGF0ZWQnXG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5lcnJvciwgZXhwZWN0ZWQpXG4gICAgICAgICAgICB9KVxuICAgIH0sXG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNvZGVkY2hhcmFjdGVyc2V0OiB7XG4gICAgICAgIElQVENFbmNvZGluZyxcbiAgICB9LFxufVxuIl19 \ No newline at end of file diff --git a/dist/test/spec/constructor.js b/dist/test/spec/constructor.js new file mode 100644 index 0000000..9f87986 --- /dev/null +++ b/dist/test/spec/constructor.js @@ -0,0 +1,30 @@ +'use strict'; + +require('source-map-support/register'); + +var assert = require('assert'); +var context = require('exiftool-context'); +var exiftool = require('../../src/'); +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +var constructorTestSuite = { + context: context, + 'creates new ExiftoolProcess instance with default bin': function createsNewExiftoolProcessInstanceWithDefaultBin(ctx) { + var ep = new exiftool.ExiftoolProcess(); + assert(ep instanceof exiftool.ExiftoolProcess); + assert.equal(ep._bin, exiftool.EXIFTOOL_PATH); + assert.equal(ep._bin, ctx.defaultBin); + }, + 'instance\'s isOpen getter returns false': function instanceSIsOpenGetterReturnsFalse(ctx) { + ctx.create(); + assert(!ctx.ep.isOpen); + }, + 'creates new ExiftoolProcess object with specific bin': function createsNewExiftoolProcessObjectWithSpecificBin(ctx) { + var bin = '/usr/local/my-exiftool'; + ctx.create(bin); + assert.equal(ctx.ep._bin, bin); + } +}; + +module.exports = constructorTestSuite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9jb25zdHJ1Y3Rvci5qcyJdLCJuYW1lcyI6WyJhc3NlcnQiLCJyZXF1aXJlIiwiY29udGV4dCIsImV4aWZ0b29sIiwiZ2xvYmFsRXhpZnRvb2xDb25zdHJ1Y3RvciIsIkV4aWZ0b29sUHJvY2VzcyIsImNvbnN0cnVjdG9yVGVzdFN1aXRlIiwiY3R4IiwiZXAiLCJlcXVhbCIsIl9iaW4iLCJFWElGVE9PTF9QQVRIIiwiZGVmYXVsdEJpbiIsImNyZWF0ZSIsImlzT3BlbiIsImJpbiIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxJQUFNQSxTQUFTQyxRQUFRLFFBQVIsQ0FBZjtBQUNBLElBQU1DLFVBQVVELFFBQVEsa0JBQVIsQ0FBaEI7QUFDQSxJQUFNRSxXQUFXRixRQUFRLFlBQVIsQ0FBakI7QUFDQUMsUUFBUUUseUJBQVIsR0FBb0NELFNBQVNFLGVBQTdDOztBQUVBLElBQU1DLHVCQUF1QjtBQUN6Qkosb0JBRHlCO0FBRXpCLDZEQUF5RCx5REFBQ0ssR0FBRCxFQUFTO0FBQzlELFlBQU1DLEtBQUssSUFBSUwsU0FBU0UsZUFBYixFQUFYO0FBQ0FMLGVBQU9RLGNBQWNMLFNBQVNFLGVBQTlCO0FBQ0FMLGVBQU9TLEtBQVAsQ0FBYUQsR0FBR0UsSUFBaEIsRUFBc0JQLFNBQVNRLGFBQS9CO0FBQ0FYLGVBQU9TLEtBQVAsQ0FBYUQsR0FBR0UsSUFBaEIsRUFBc0JILElBQUlLLFVBQTFCO0FBQ0gsS0FQd0I7QUFRekIsK0NBQTJDLDJDQUFDTCxHQUFELEVBQVM7QUFDaERBLFlBQUlNLE1BQUo7QUFDQWIsZUFBTyxDQUFDTyxJQUFJQyxFQUFKLENBQU9NLE1BQWY7QUFDSCxLQVh3QjtBQVl6Qiw0REFBd0Qsd0RBQUNQLEdBQUQsRUFBUztBQUM3RCxZQUFNUSxNQUFNLHdCQUFaO0FBQ0FSLFlBQUlNLE1BQUosQ0FBV0UsR0FBWDtBQUNBZixlQUFPUyxLQUFQLENBQWFGLElBQUlDLEVBQUosQ0FBT0UsSUFBcEIsRUFBMEJLLEdBQTFCO0FBQ0g7QUFoQndCLENBQTdCOztBQW1CQUMsT0FBT0MsT0FBUCxHQUFpQlgsb0JBQWpCIiwiZmlsZSI6ImNvbnN0cnVjdG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0JylcbmNvbnN0IGNvbnRleHQgPSByZXF1aXJlKCdleGlmdG9vbC1jb250ZXh0JylcbmNvbnN0IGV4aWZ0b29sID0gcmVxdWlyZSgnLi4vLi4vc3JjLycpXG5jb250ZXh0Lmdsb2JhbEV4aWZ0b29sQ29uc3RydWN0b3IgPSBleGlmdG9vbC5FeGlmdG9vbFByb2Nlc3NcblxuY29uc3QgY29uc3RydWN0b3JUZXN0U3VpdGUgPSB7XG4gICAgY29udGV4dCxcbiAgICAnY3JlYXRlcyBuZXcgRXhpZnRvb2xQcm9jZXNzIGluc3RhbmNlIHdpdGggZGVmYXVsdCBiaW4nOiAoY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IGVwID0gbmV3IGV4aWZ0b29sLkV4aWZ0b29sUHJvY2VzcygpXG4gICAgICAgIGFzc2VydChlcCBpbnN0YW5jZW9mIGV4aWZ0b29sLkV4aWZ0b29sUHJvY2VzcylcbiAgICAgICAgYXNzZXJ0LmVxdWFsKGVwLl9iaW4sIGV4aWZ0b29sLkVYSUZUT09MX1BBVEgpXG4gICAgICAgIGFzc2VydC5lcXVhbChlcC5fYmluLCBjdHguZGVmYXVsdEJpbilcbiAgICB9LFxuICAgICdpbnN0YW5jZVxcJ3MgaXNPcGVuIGdldHRlciByZXR1cm5zIGZhbHNlJzogKGN0eCkgPT4ge1xuICAgICAgICBjdHguY3JlYXRlKClcbiAgICAgICAgYXNzZXJ0KCFjdHguZXAuaXNPcGVuKVxuICAgIH0sXG4gICAgJ2NyZWF0ZXMgbmV3IEV4aWZ0b29sUHJvY2VzcyBvYmplY3Qgd2l0aCBzcGVjaWZpYyBiaW4nOiAoY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IGJpbiA9ICcvdXNyL2xvY2FsL215LWV4aWZ0b29sJ1xuICAgICAgICBjdHguY3JlYXRlKGJpbilcbiAgICAgICAgYXNzZXJ0LmVxdWFsKGN0eC5lcC5fYmluLCBiaW4pXG4gICAgfSxcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb25zdHJ1Y3RvclRlc3RTdWl0ZVxuIl19 \ No newline at end of file diff --git a/dist/test/spec/detached-true.js b/dist/test/spec/detached-true.js new file mode 100644 index 0000000..119385f --- /dev/null +++ b/dist/test/spec/detached-true.js @@ -0,0 +1,236 @@ +'use strict'; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +require('source-map-support/register'); + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var makepromise = require('makepromise'); +var ps = require('ps-node'); +var assert = require('assert'); +var killPid = require('../lib/kill-pid'); + +var exiftool = require('../../src/'); +var context = require('../context/detached'); +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +var isWindows = process.platform === 'win32'; + +var checkPid = function checkPid(pid) { + return makepromise(ps.lookup, { pid: pid }); +}; +var checkPpid = function checkPpid(ppid) { + return makepromise(ps.lookup, { ppid: ppid }); +}; + +/** + * @typedef {Object} PSRes + * @property {string} pid + * @property {string} command + * @property {string[]} arguments + * @property {string} ppid + */ + +/** + * @typedef {Object} CheckPidsRes + * @property {PSRes} [fork] + * @property {PSRes} [ep] + * @property {PSRes} [epChild] + * @property {PSRes} [conhost] + */ + +/** + * @typedef {function(): Promise.} CheckPidsFn + */ + +/** + * Create checkPids function. + * @param {string|number} forkPid pid of Node fork + * @param {string|number} epPid exiftool pid + * @param {string|number} [epChildPid] on windows, child ep pid + * @param {string|number} [conhostPid] on windows, child conhost pid + * @returns {CheckPidsFn} Function to check pids with ps-node + */ +function createCheckPids(forkPid, epPid, epChildPid, conhostPid) { + assert(forkPid); + assert(epPid); + var arr = [forkPid, epPid]; + if (epChildPid) arr.push(epChildPid); + if (conhostPid) arr.push(conhostPid); + var checkPids = function checkPids() { + return checkPid(arr).then(function (res) { + var fork = res.find(function (r) { + return r.pid === '' + forkPid; + }); + var ep = res.find(function (r) { + return r.pid === '' + epPid; + }); + var epChild = epChildPid ? res.find(function (r) { + return r.pid === '' + epChildPid; + }) : undefined; + var conhost = conhostPid ? res.find(function (r) { + return r.pid === '' + conhostPid; + }) : undefined; + var o = { + fork: fork, + ep: ep, + epChild: epChild, + conhost: conhost + // filter out undefined + };var fo = Object.keys(o).reduce(function (acc, key) { + var value = o[key]; + if (value === undefined) { + return acc; + } + return Object.assign({}, acc, _defineProperty({}, key, value)); + }, {}); + return fo; + }); + }; + return checkPids; +} + +var findExiftoolChildAndConhost = function findExiftoolChildAndConhost(epPid, exiftoolDetached) { + if (!isWindows) { + return Promise.reject(new Error('This function is only available on Windows')); + } + return checkPpid(epPid).then(function (res) { + // if not detached, conhost is child of parent exiftool, + // which is already found above + if (!exiftoolDetached) return res; + // if detached, conhost is child of child exiftool, + // which we are now finding + + var _res = _slicedToArray(res, 1), + childExiftool = _res[0]; + + assert(childExiftool); + assert(/exiftool\.exe/.test(childExiftool.command)); + return checkPpid(childExiftool.pid).then(function (conhostRes) { + var _conhostRes = _slicedToArray(conhostRes, 1), + conhost = _conhostRes[0]; + + assert(conhost); + assert(/conhost.exe/.test(conhost.command)); + var all = [].concat(conhostRes, res); + return all; + }); + }).then(function (res) { + assert.equal(res.length, 2); + var conhost = res.find(function (p) { + return (/conhost\.exe/.test(p.command) + ); + }); + assert(conhost, 'conhost.exe should have been started as child of exiftool'); + var conhostPid = conhost.pid; + var epChild = res.find(function (p) { + return (/exiftool\.exe/.test(p.command) + ); + }); + assert(epChild, 'exiftool.exe should have been started as child of exiftool'); + var epChildPid = epChild.pid; + return { conhostPid: conhostPid, epChildPid: epChildPid }; + }); +}; + +/** + * Fork a node process with a module which will spawn exiftool. Because of the + * way exiftool works on Windows, it will spawn an extra process itself. + * @param {boolean} exiftoolDetached Whether to start exiftool in detached mode + * @returns {CheckPidsFn} A scoped function to check pids + */ +var setup = function setup(exiftoolDetached, ctx) { + var checkPids = void 0; + + return ctx.forkNode(exiftoolDetached).then(function (_ref) { + var forkPid = _ref.forkPid, + epPid = _ref.epPid; + + var res = { forkPid: forkPid, epPid: epPid }; + + if (isWindows) { + return findExiftoolChildAndConhost(epPid, exiftoolDetached).then(function (r) { + return Object.assign(res, r); + }); + } + return res; + }).then(function (res) { + checkPids = createCheckPids(res.forkPid, res.epPid, res.epChildPid, res.conhostPid); + return checkPids(); + }).then(function (res) { + assert(res.fork); + assert(res.ep); + if (isWindows) { + assert(res.epChild); + assert(res.conhost); + } + return checkPids; + }); +}; + +var createTestWin = function createTestWin(detached) { + var test = function test(ctx) { + var checkPids = void 0; + return setup(detached, ctx).then(function (res) { + checkPids = res; + return ctx.killFork().then(checkPids); + }).then(function (res) { + assert(!res.fork, 'Node fork should have quit'); + assert(res.epChild, 'Exiftool child should stay open'); + assert(res.conhost, 'conhost should stay open'); + + if (detached) { + assert(res.ep, 'Exiftool parent should stay open'); + } else { + assert(!res.ep, 'Exiftool parent should have quit'); + } + + // cleanup by killing child exiftool, this should kill the whole tree + return killPid(res.epChild.pid); + }); + }; + return test; +}; + +var createTest = function createTest(detached) { + var test = function test(ctx) { + var checkPids = void 0; + return setup(detached, ctx).then(function (res) { + checkPids = res; + return ctx.killFork(true).then(checkPids); + }).then(function (res) { + assert(!res.fork, 'Node fork should have quit'); + + if (detached) { + assert(res.ep, 'Exiftool parent should stay open'); + return killPid(res.ep.pid); + } else { + assert(!res.ep, 'Exiftool parent should have quit'); + } + }); + }; + return test; +}; + +var DetachedTrueTestSuite = {}; + +if (isWindows) { + Object.assign(DetachedTrueTestSuite, { + context: context, + 'should quit child process when fork exits without detached option (win)': createTestWin(), + 'should not quit child process when fork exits with detached option (win)': createTestWin(true) + }); +} else { + Object.assign(DetachedTrueTestSuite, { + context: context, + // Also note: on Linux, child processes of child processes will not be terminated when attempting to kill their parent. + // kill detached fork by passing -pid (i.e., pgid) + // https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal + 'should quit child process when fork exits without detached option': createTest(), + 'should not quit child process when fork exits with detached option': createTest(true) + }); +} + +module.exports = DetachedTrueTestSuite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9kZXRhY2hlZC10cnVlLmpzIl0sIm5hbWVzIjpbIm1ha2Vwcm9taXNlIiwicmVxdWlyZSIsInBzIiwiYXNzZXJ0Iiwia2lsbFBpZCIsImV4aWZ0b29sIiwiY29udGV4dCIsImdsb2JhbEV4aWZ0b29sQ29uc3RydWN0b3IiLCJFeGlmdG9vbFByb2Nlc3MiLCJpc1dpbmRvd3MiLCJwcm9jZXNzIiwicGxhdGZvcm0iLCJjaGVja1BpZCIsImxvb2t1cCIsInBpZCIsImNoZWNrUHBpZCIsInBwaWQiLCJjcmVhdGVDaGVja1BpZHMiLCJmb3JrUGlkIiwiZXBQaWQiLCJlcENoaWxkUGlkIiwiY29uaG9zdFBpZCIsImFyciIsInB1c2giLCJjaGVja1BpZHMiLCJ0aGVuIiwicmVzIiwiZm9yayIsImZpbmQiLCJyIiwiZXAiLCJlcENoaWxkIiwidW5kZWZpbmVkIiwiY29uaG9zdCIsIm8iLCJmbyIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJhY2MiLCJrZXkiLCJ2YWx1ZSIsImFzc2lnbiIsImZpbmRFeGlmdG9vbENoaWxkQW5kQ29uaG9zdCIsImV4aWZ0b29sRGV0YWNoZWQiLCJQcm9taXNlIiwicmVqZWN0IiwiRXJyb3IiLCJjaGlsZEV4aWZ0b29sIiwidGVzdCIsImNvbW1hbmQiLCJjb25ob3N0UmVzIiwiYWxsIiwiY29uY2F0IiwiZXF1YWwiLCJsZW5ndGgiLCJwIiwic2V0dXAiLCJjdHgiLCJmb3JrTm9kZSIsImNyZWF0ZVRlc3RXaW4iLCJkZXRhY2hlZCIsImtpbGxGb3JrIiwiY3JlYXRlVGVzdCIsIkRldGFjaGVkVHJ1ZVRlc3RTdWl0ZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUEsSUFBTUEsY0FBY0MsUUFBUSxhQUFSLENBQXBCO0FBQ0EsSUFBTUMsS0FBS0QsUUFBUSxTQUFSLENBQVg7QUFDQSxJQUFNRSxTQUFTRixRQUFRLFFBQVIsQ0FBZjtBQUNBLElBQU1HLFVBQVVILFFBQVEs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O0FBQ0EsdUJBQU8xQixRQUFRc0IsSUFBSUksRUFBSixDQUFPaEIsR0FBZixDQUFQO0FBQ0gsYUFIRCxNQUdPO0FBQ0hYLHVCQUFPLENBQUN1QixJQUFJSSxFQUFaLEVBQWdCLGtDQUFoQjtBQUNIO0FBQ0osU0FkRSxDQUFQO0FBZUgsS0FqQkQ7QUFrQkEsV0FBT21CLElBQVA7QUFDSCxDQXBCRDs7QUFzQkEsSUFBTWUsd0JBQXdCLEVBQTlCOztBQUVBLElBQUl2RCxTQUFKLEVBQWU7QUFDWDJCLFdBQU9NLE1BQVAsQ0FBY3NCLHFCQUFkLEVBQXFDO0FBQ2pDMUQsd0JBRGlDO0FBRWpDLG1GQUEyRXNELGVBRjFDO0FBR2pDLG9GQUE0RUEsY0FBYyxJQUFkO0FBSDNDLEtBQXJDO0FBS0gsQ0FORCxNQU1PO0FBQ0h4QixXQUFPTSxNQUFQLENBQWNzQixxQkFBZCxFQUFxQztBQUNqQzFELHdCQURpQztBQUVqQztBQUNBO0FBQ0E7QUFDQSw2RUFBcUV5RCxZQUxwQztBQU1qQyw4RUFBc0VBLFdBQVcsSUFBWDtBQU5yQyxLQUFyQztBQVFIOztBQUdERSxPQUFPQyxPQUFQLEdBQWlCRixxQkFBakIiLCJmaWxlIjoiZGV0YWNoZWQtdHJ1ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IG1ha2Vwcm9taXNlID0gcmVxdWlyZSgnbWFrZXByb21pc2UnKVxuY29uc3QgcHMgPSByZXF1aXJlKCdwcy1ub2RlJylcbmNvbnN0IGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpXG5jb25zdCBraWxsUGlkID0gcmVxdWlyZSgnLi4vbGliL2tpbGwtcGlkJylcblxuY29uc3QgZXhpZnRvb2wgPSByZXF1aXJlKCcuLi8uLi9zcmMvJylcbmNvbnN0IGNvbnRleHQgPSByZXF1aXJlKCcuLi9jb250ZXh0L2RldGFjaGVkJylcbmNvbnRleHQuZ2xvYmFsRXhpZnRvb2xDb25zdHJ1Y3RvciA9IGV4aWZ0b29sLkV4aWZ0b29sUHJvY2Vzc1xuXG5jb25zdCBpc1dpbmRvd3MgPSBwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInXG5cbmNvbnN0IGNoZWNrUGlkID0gcGlkID0+IG1ha2Vwcm9taXNlKHBzLmxvb2t1cCwgeyBwaWQgfSlcbmNvbnN0IGNoZWNrUHBpZCA9IHBwaWQgPT4gbWFrZXByb21pc2UocHMubG9va3VwLCB7IHBwaWQgfSlcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQU1Jlc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IHBpZFxuICogQHByb3BlcnR5IHtzdHJpbmd9IGNvbW1hbmRcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nW119IGFyZ3VtZW50c1xuICogQHByb3BlcnR5IHtzdHJpbmd9IHBwaWRcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IENoZWNrUGlkc1Jlc1xuICogQHByb3BlcnR5IHtQU1Jlc30gW2ZvcmtdXG4gKiBAcHJvcGVydHkge1BTUmVzfSBbZXBdXG4gKiBAcHJvcGVydHkge1BTUmVzfSBbZXBDaGlsZF1cbiAqIEBwcm9wZXJ0eSB7UFNSZXN9IFtjb25ob3N0XVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKCk6IFByb21pc2UuPENoZWNrUGlkc1Jlcz59IENoZWNrUGlkc0ZuXG4gKi9cblxuLyoqXG4gKiBDcmVhdGUgY2hlY2tQaWRzIGZ1bmN0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBmb3JrUGlkIHBpZCBvZiBOb2RlIGZvcmtcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gZXBQaWQgZXhpZnRvb2wgcGlkXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IFtlcENoaWxkUGlkXSBvbiB3aW5kb3dzLCBjaGlsZCBlcCBwaWRcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gW2Nvbmhvc3RQaWRdIG9uIHdpbmRvd3MsIGNoaWxkIGNvbmhvc3QgcGlkXG4gKiBAcmV0dXJucyB7Q2hlY2tQaWRzRm59IEZ1bmN0aW9uIHRvIGNoZWNrIHBpZHMgd2l0aCBwcy1ub2RlXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUNoZWNrUGlkcyhmb3JrUGlkLCBlcFBpZCwgZXBDaGlsZFBpZCwgY29uaG9zdFBpZCkge1xuICAgIGFzc2VydChmb3JrUGlkKVxuICAgIGFzc2VydChlcFBpZClcbiAgICBjb25zdCBhcnIgPSBbZm9ya1BpZCwgZXBQaWRdXG4gICAgaWYgKGVwQ2hpbGRQaWQpIGFyci5wdXNoKGVwQ2hpbGRQaWQpXG4gICAgaWYgKGNvbmhvc3RQaWQpIGFyci5wdXNoKGNvbmhvc3RQaWQpXG4gICAgY29uc3QgY2hlY2tQaWRzID0gKCkgPT4gY2hlY2tQaWQoYXJyKVxuICAgICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmb3JrID0gcmVzLmZpbmQociA9PiByLnBpZCA9PT0gYCR7Zm9ya1BpZH1gKVxuICAgICAgICAgICAgY29uc3QgZXAgPSByZXMuZmluZChyID0+IHIucGlkID09PSBgJHtlcFBpZH1gKVxuICAgICAgICAgICAgY29uc3QgZXBDaGlsZCA9IGVwQ2hpbGRQaWQgPyByZXMuZmluZChyID0+IHIucGlkID09PSBgJHtlcENoaWxkUGlkfWApIDogdW5kZWZpbmVkXG4gICAgICAgICAgICBjb25zdCBjb25ob3N0ID0gY29uaG9zdFBpZCA/IHJlcy5maW5kKHIgPT4gci5waWQgPT09IGAke2Nvbmhvc3RQaWR9YCkgOiB1bmRlZmluZWRcbiAgICAgICAgICAgIGNvbnN0IG8gPSB7XG4gICAgICAgICAgICAgICAgZm9yayxcbiAgICAgICAgICAgICAgICBlcCxcbiAgICAgICAgICAgICAgICBlcENoaWxkLFxuICAgICAgICAgICAgICAgIGNvbmhvc3QsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBmaWx0ZXIgb3V0IHVuZGVmaW5lZFxuICAgICAgICAgICAgY29uc3QgZm8gPSBPYmplY3Qua2V5cyhvKS5yZWR1Y2UoKGFjYywga2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvW2tleV1cbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWNjXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBhY2MsIHtcbiAgICAgICAgICAgICAgICAgICAgW2tleV06IHZhbHVlLFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9LCB7fSlcbiAgICAgICAgICAgIHJldHVybiBmb1xuICAgICAgICB9KVxuICAgIHJldHVybiBjaGVja1BpZHNcbn1cblxuY29uc3QgZmluZEV4aWZ0b29sQ2hpbGRBbmRDb25ob3N0ID0gKGVwUGlkLCBleGlmdG9vbERldGFjaGVkKSA9PiB7XG4gICAgaWYgKCFpc1dpbmRvd3MpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignVGhpcyBmdW5jdGlvbiBpcyBvbmx5IGF2YWlsYWJsZSBvbiBXaW5kb3dzJykpXG4gICAgfVxuICAgIHJldHVybiBjaGVja1BwaWQoZXBQaWQpXG4gICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgIC8vIGlmIG5vdCBkZXRhY2hlZCwgY29uaG9zdCBpcyBjaGlsZCBvZiBwYXJlbnQgZXhpZnRvb2wsXG4gICAgICAgICAgICAvLyB3aGljaCBpcyBhbHJlYWR5IGZvdW5kIGFib3ZlXG4gICAgICAgICAgICBpZiAoIWV4aWZ0b29sRGV0YWNoZWQpIHJldHVybiByZXNcbiAgICAgICAgICAgIC8vIGlmIGRldGFjaGVkLCBjb25ob3N0IGlzIGNoaWxkIG9mIGNoaWxkIGV4aWZ0b29sLFxuICAgICAgICAgICAgLy8gd2hpY2ggd2UgYXJlIG5vdyBmaW5kaW5nXG4gICAgICAgICAgICBjb25zdCBbY2hpbGRFeGlmdG9vbF0gPSByZXNcbiAgICAgICAgICAgIGFzc2VydChjaGlsZEV4aWZ0b29sKVxuICAgICAgICAgICAgYXNzZXJ0KC9leGlmdG9vbFxcLmV4ZS8udGVzdChjaGlsZEV4aWZ0b29sLmNvbW1hbmQpKVxuICAgICAgICAgICAgcmV0dXJuIGNoZWNrUHBpZChjaGlsZEV4aWZ0b29sLnBpZCkudGhlbigoY29uaG9zdFJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtjb25ob3N0XSA9IGNvbmhvc3RSZXNcbiAgICAgICAgICAgICAgICBhc3NlcnQoY29uaG9zdClcbiAgICAgICAgICAgICAgICBhc3NlcnQoL2Nvbmhvc3QuZXhlLy50ZXN0KGNvbmhvc3QuY29tbWFuZCkpXG4gICAgICAgICAgICAgICAgY29uc3QgYWxsID0gW10uY29uY2F0KGNvbmhvc3RSZXMsIHJlcylcbiAgICAgICAgICAgICAgICByZXR1cm4gYWxsXG4gICAgICAgICAgICB9KVxuICAgICAgICB9KVxuICAgICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmxlbmd0aCwgMilcbiAgICAgICAgICAgIGNvbnN0IGNvbmhvc3QgPSByZXMuZmluZChwID0+IC9jb25ob3N0XFwuZXhlLy50ZXN0KHAuY29tbWFuZCkpXG4gICAgICAgICAgICBhc3NlcnQoY29uaG9zdCwgJ2Nvbmhvc3QuZXhlIHNob3VsZCBoYXZlIGJlZW4gc3RhcnRlZCBhcyBjaGlsZCBvZiBleGlmdG9vbCcpXG4gICAgICAgICAgICBjb25zdCBjb25ob3N0UGlkID0gY29uaG9zdC5waWRcbiAgICAgICAgICAgIGNvbnN0IGVwQ2hpbGQgPSByZXMuZmluZChwID0+IC9leGlmdG9vbFxcLmV4ZS8udGVzdChwLmNvbW1hbmQpKVxuICAgICAgICAgICAgYXNzZXJ0KGVwQ2hpbGQsICdleGlmdG9vbC5leGUgc2hvdWxkIGhhdmUgYmVlbiBzdGFydGVkIGFzIGNoaWxkIG9mIGV4aWZ0b29sJylcbiAgICAgICAgICAgIGNvbnN0IGVwQ2hpbGRQaWQgPSBlcENoaWxkLnBpZFxuICAgICAgICAgICAgcmV0dXJuIHsgY29uaG9zdFBpZCwgZXBDaGlsZFBpZCB9XG4gICAgICAgIH0pXG59XG5cbi8qKlxuICogRm9yayBhIG5vZGUgcHJvY2VzcyB3aXRoIGEgbW9kdWxlIHdoaWNoIHdpbGwgc3Bhd24gZXhpZnRvb2wuIEJlY2F1c2Ugb2YgdGhlXG4gKiB3YXkgZXhpZnRvb2wgd29ya3Mgb24gV2luZG93cywgaXQgd2lsbCBzcGF3biBhbiBleHRyYSBwcm9jZXNzIGl0c2VsZi5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZXhpZnRvb2xEZXRhY2hlZCBXaGV0aGVyIHRvIHN0YXJ0IGV4aWZ0b29sIGluIGRldGFjaGVkIG1vZGVcbiAqIEByZXR1cm5zIHtDaGVja1BpZHNGbn0gQSBzY29wZWQgZnVuY3Rpb24gdG8gY2hlY2sgcGlkc1xuICovXG5jb25zdCBzZXR1cCA9IChleGlmdG9vbERldGFjaGVkLCBjdHgpID0+IHtcbiAgICBsZXQgY2hlY2tQaWRzXG5cbiAgICByZXR1cm4gY3R4LmZvcmtOb2RlKGV4aWZ0b29sRGV0YWNoZWQpXG4gICAgICAgIC50aGVuKCh7IGZvcmtQaWQsIGVwUGlkIH0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IHsgZm9ya1BpZCwgZXBQaWQgfVxuXG4gICAgICAgICAgICBpZiAoaXNXaW5kb3dzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpbmRFeGlmdG9vbENoaWxkQW5kQ29uaG9zdChlcFBpZCwgZXhpZnRvb2xEZXRhY2hlZClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4ociA9PiBPYmplY3QuYXNzaWduKHJlcywgcikpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgIGNoZWNrUGlkcyA9IGNyZWF0ZUNoZWNrUGlkcyhyZXMuZm9ya1BpZCwgcmVzLmVwUGlkLCByZXMuZXBDaGlsZFBpZCwgcmVzLmNvbmhvc3RQaWQpXG4gICAgICAgICAgICByZXR1cm4gY2hlY2tQaWRzKClcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgYXNzZXJ0KHJlcy5mb3JrKVxuICAgICAgICAgICAgYXNzZXJ0KHJlcy5lcClcbiAgICAgICAgICAgIGlmIChpc1dpbmRvd3MpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQocmVzLmVwQ2hpbGQpXG4gICAgICAgICAgICAgICAgYXNzZXJ0KHJlcy5jb25ob3N0KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNoZWNrUGlkc1xuICAgICAgICB9KVxufVxuXG5jb25zdCBjcmVhdGVUZXN0V2luID0gKGRldGFjaGVkKSA9PiB7XG4gICAgY29uc3QgdGVzdCA9IChjdHgpID0+IHtcbiAgICAgICAgbGV0IGNoZWNrUGlkc1xuICAgICAgICByZXR1cm4gc2V0dXAoZGV0YWNoZWQsIGN0eClcbiAgICAgICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgICAgICBjaGVja1BpZHMgPSByZXNcbiAgICAgICAgICAgICAgICByZXR1cm4gY3R4LmtpbGxGb3JrKCkudGhlbihjaGVja1BpZHMpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydCghcmVzLmZvcmssICdOb2RlIGZvcmsgc2hvdWxkIGhhdmUgcXVpdCcpXG4gICAgICAgICAgICAgICAgYXNzZXJ0KHJlcy5lcENoaWxkLCAnRXhpZnRvb2wgY2hpbGQgc2hvdWxkIHN0YXkgb3BlbicpXG4gICAgICAgICAgICAgICAgYXNzZXJ0KHJlcy5jb25ob3N0LCAnY29uaG9zdCBzaG91bGQgc3RheSBvcGVuJylcblxuICAgICAgICAgICAgICAgIGlmIChkZXRhY2hlZCkge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQocmVzLmVwLCAnRXhpZnRvb2wgcGFyZW50IHNob3VsZCBzdGF5IG9wZW4nKVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydCghcmVzLmVwLCAnRXhpZnRvb2wgcGFyZW50IHNob3VsZCBoYXZlIHF1aXQnKVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGNsZWFudXAgYnkga2lsbGluZyBjaGlsZCBleGlmdG9vbCwgdGhpcyBzaG91bGQga2lsbCB0aGUgd2hvbGUgdHJlZVxuICAgICAgICAgICAgICAgIHJldHVybiBraWxsUGlkKHJlcy5lcENoaWxkLnBpZClcbiAgICAgICAgICAgIH0pXG4gICAgfVxuICAgIHJldHVybiB0ZXN0XG59XG5cbmNvbnN0IGNyZWF0ZVRlc3QgPSAoZGV0YWNoZWQpID0+IHtcbiAgICBjb25zdCB0ZXN0ID0gKGN0eCkgPT4ge1xuICAgICAgICBsZXQgY2hlY2tQaWRzXG4gICAgICAgIHJldHVybiBzZXR1cChkZXRhY2hlZCwgY3R4KVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGNoZWNrUGlkcyA9IHJlc1xuICAgICAgICAgICAgICAgIHJldHVybiBjdHgua2lsbEZvcmsodHJ1ZSkudGhlbihjaGVja1BpZHMpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydCghcmVzLmZvcmssICdOb2RlIGZvcmsgc2hvdWxkIGhhdmUgcXVpdCcpXG5cbiAgICAgICAgICAgICAgICBpZiAoZGV0YWNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KHJlcy5lcCwgJ0V4aWZ0b29sIHBhcmVudCBzaG91bGQgc3RheSBvcGVuJylcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGtpbGxQaWQocmVzLmVwLnBpZClcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoIXJlcy5lcCwgJ0V4aWZ0b29sIHBhcmVudCBzaG91bGQgaGF2ZSBxdWl0JylcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgIH1cbiAgICByZXR1cm4gdGVzdFxufVxuXG5jb25zdCBEZXRhY2hlZFRydWVUZXN0U3VpdGUgPSB7fVxuXG5pZiAoaXNXaW5kb3dzKSB7XG4gICAgT2JqZWN0LmFzc2lnbihEZXRhY2hlZFRydWVUZXN0U3VpdGUsIHtcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgJ3Nob3VsZCBxdWl0IGNoaWxkIHByb2Nlc3Mgd2hlbiBmb3JrIGV4aXRzIHdpdGhvdXQgZGV0YWNoZWQgb3B0aW9uICh3aW4pJzogY3JlYXRlVGVzdFdpbigpLFxuICAgICAgICAnc2hvdWxkIG5vdCBxdWl0IGNoaWxkIHByb2Nlc3Mgd2hlbiBmb3JrIGV4aXRzIHdpdGggZGV0YWNoZWQgb3B0aW9uICh3aW4pJzogY3JlYXRlVGVzdFdpbih0cnVlKSxcbiAgICB9KVxufSBlbHNlIHtcbiAgICBPYmplY3QuYXNzaWduKERldGFjaGVkVHJ1ZVRlc3RTdWl0ZSwge1xuICAgICAgICBjb250ZXh0LFxuICAgICAgICAvLyBBbHNvIG5vdGU6IG9uIExpbnV4LCBjaGlsZCBwcm9jZXNzZXMgb2YgY2hpbGQgcHJvY2Vzc2VzIHdpbGwgbm90IGJlIHRlcm1pbmF0ZWQgd2hlbiBhdHRlbXB0aW5nIHRvIGtpbGwgdGhlaXIgcGFyZW50LlxuICAgICAgICAvLyBraWxsIGRldGFjaGVkIGZvcmsgYnkgcGFzc2luZyAtcGlkIChpLmUuLCBwZ2lkKVxuICAgICAgICAvLyBodHRwczovL25vZGVqcy5vcmcvYXBpL2NoaWxkX3Byb2Nlc3MuaHRtbCNjaGlsZF9wcm9jZXNzX3N1YnByb2Nlc3Nfa2lsbF9zaWduYWxcbiAgICAgICAgJ3Nob3VsZCBxdWl0IGNoaWxkIHByb2Nlc3Mgd2hlbiBmb3JrIGV4aXRzIHdpdGhvdXQgZGV0YWNoZWQgb3B0aW9uJzogY3JlYXRlVGVzdCgpLFxuICAgICAgICAnc2hvdWxkIG5vdCBxdWl0IGNoaWxkIHByb2Nlc3Mgd2hlbiBmb3JrIGV4aXRzIHdpdGggZGV0YWNoZWQgb3B0aW9uJzogY3JlYXRlVGVzdCh0cnVlKSxcbiAgICB9KVxufVxuXG5cbm1vZHVsZS5leHBvcnRzID0gRGV0YWNoZWRUcnVlVGVzdFN1aXRlXG4iXX0= \ No newline at end of file diff --git a/dist/test/spec/exiftool.js b/dist/test/spec/exiftool.js new file mode 100644 index 0000000..93652e3 --- /dev/null +++ b/dist/test/spec/exiftool.js @@ -0,0 +1,279 @@ +'use strict'; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +require('source-map-support/register'); + +var _require = require('os'), + EOL = _require.EOL; + +var assert = require('assert'); +var child_process = require('child_process'); +var context = require('exiftool-context'); +var exiftool = require('../../src/'); +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +var ChildProcess = child_process.ChildProcess; + + +var exiftoolTestSuite = { + context: context, + open: { + 'opens exiftool': function opensExiftool(ctx) { + return ctx.createOpen().then(function (pid) { + assert(ctx.ep._process instanceof ChildProcess); + assert(ctx.ep._process.stdout.readable); + assert(ctx.ep._process.stderr.readable); + assert(ctx.ep._process.stdin.writable); + assert(ctx.ep.isOpen); + assert.equal(typeof pid === 'undefined' ? 'undefined' : _typeof(pid), 'number'); + assert.equal(pid, ctx.ep._process.pid); + }); + }, + 'returns rejected promise when exiftool executable not found': function returnsRejectedPromiseWhenExiftoolExecutableNotFound(ctx) { + return ctx.createOpen('notexiftool').then(function () { + throw new Error('open should have resulted in error'); + }, function (err) { + assert.equal(err.message, 'spawn notexiftool ENOENT'); + }); + }, + 'emits OPEN event with PID': function emitsOPENEventWithPID(ctx) { + ctx.create(); + var eventPromise = new Promise(function (resolve) { + return ctx.ep.on(exiftool.events.OPEN, resolve); + }); + return ctx.open().then(function () { + return eventPromise; + }).then(function (pid) { + return assert.equal(pid, ctx.ep._process.pid); + }); + }, + 'returns rejected promise when process is open already': function returnsRejectedPromiseWhenProcessIsOpenAlready(ctx) { + return ctx.createOpen().then(function () { + return ctx.open(); + }).then(function () { + throw new Error('second open should have resulted in error'); + }, function (err) { + assert.equal(err.message, 'Exiftool process is already open'); + }); + } + }, + close: { + 'closes the process': function closesTheProcess(ctx) { + return ctx.createOpen().then(function () { + return ctx.close(); + }).then(function () { + assert(ctx.ep._process instanceof ChildProcess); + assert(!ctx.ep._process.stdout.readable); + assert(!ctx.ep._process.stderr.readable); + assert(!ctx.ep._process.stdin.writable); + assert(!ctx.ep.isOpen); + }); + }, + 'updates resolve write streams to be finished': function updatesResolveWriteStreamsToBeFinished(ctx) { + return ctx.createOpen().then(function () { + return ctx.close(); + }).then(function () { + assert(ctx.ep._stdoutResolveWs._writableState.finished); + assert(ctx.ep._stderrResolveWs._writableState.finished); + }); + }, + 'completes remaining jobs': function completesRemainingJobs(ctx) { + return ctx.createOpen().then(function () { + var p = ctx.ep.readMetadata(ctx.jpegFile).then(function (res) { + assert(Array.isArray(res.data)); + assert.equal(res.error, null); + res.data.forEach(ctx.assertJpegMetadata); + }); + var p2 = ctx.ep.readMetadata(ctx.jpegFile2).then(function (res) { + assert(Array.isArray(res.data)); + assert.equal(res.error, null); + res.data.forEach(ctx.assertJpegMetadata); + }); + var readPromises = Promise.all([p, p2]); + + return ctx.close().then(function () { + assert(!Object.keys(ctx.ep._stdoutResolveWs._resolveMap).length); + assert(!Object.keys(ctx.ep._stderrResolveWs._resolveMap).length); + }).then(function () { + return readPromises; + }); + }); + }, + 'emits EXIT event': function emitsEXITEvent(ctx) { + ctx.create(); + var eventPromise = new Promise(function (resolve) { + return ctx.ep.on(exiftool.events.EXIT, resolve); + }); + return ctx.open().then(function () { + return ctx.close(); + }).then(function () { + return eventPromise; + }); + }, + 'sets open to false': function setsOpenToFalse(ctx) { + return ctx.createOpen().then(function () { + return ctx.close(); + }).then(function () { + return assert(!ctx.ep.isOpen); + }); + }, + 'returns rejected promise when process not open': function returnsRejectedPromiseWhenProcessNotOpen(ctx) { + return ctx.create().close().then(function () { + throw new Error('close should have resulted in error'); + }, function (err) { + assert.equal(err.message, 'Exiftool process is not open'); + }); + } + }, + readMetadata: { + 'returns rejected promise when trying to execute when not open': function returnsRejectedPromiseWhenTryingToExecuteWhenNotOpen(ctx) { + return ctx.create().readMetadata(ctx.jpegFile).then(function () { + throw new Error('readMetadata should have resulted in error'); + }).catch(function (err) { + return assert.equal(err.message, 'exiftool is not open'); + }); + }, + 'reads metadata of files in a directory': function readsMetadataOfFilesInADirectory(ctx) { + return ctx.initAndReadMetadata(ctx.folder).then(function (res) { + assert(Array.isArray(res.data)); + assert.equal(res.data.length, 5); + res.data.forEach(ctx.assertJpegMetadata); + assert.equal(res.error, '1 directories scanned' + EOL + ' 5 image files read'); + }); + }, + 'returns null data for empty directory and info error': function returnsNullDataForEmptyDirectoryAndInfoError(ctx) { + return ctx.initAndReadMetadata(ctx.emptyFolder).then(function (res) { + assert.equal(res.data, null); + assert.equal(res.error, '1 directories scanned' + EOL + ' 0 image files read'); + }); + }, + 'allows to specify arguments': function allowsToSpecifyArguments(ctx) { + return ctx.initAndReadMetadata(ctx.jpegFile, ['Orientation', 'n']).then(function (res) { + assert.equal(res.error, null); + assert(Array.isArray(res.data)); + var expected = { + SourceFile: ctx.replaceSlashes(ctx.jpegFile), + Orientation: 6 + }; + assert.deepEqual(res.data[0], expected); + }); + }, + 'reads metadata of a file': function readsMetadataOfAFile(ctx) { + return ctx.initAndReadMetadata(ctx.jpegFile).then(function (res) { + assert.equal(res.error, null); + assert(Array.isArray(res.data)); + + var _res$data = _slicedToArray(res.data, 1), + metadata = _res$data[0]; + + var expected = { + SourceFile: ctx.replaceSlashes(ctx.jpegFile), + Directory: ctx.replaceSlashes(ctx.folder), + FileName: 'IMG_9858.JPG', + FileSize: '52 kB', + FileType: 'JPEG', + FileTypeExtension: 'jpg', + MIMEType: 'image/jpeg', + ExifByteOrder: 'Big-endian (Motorola, MM)', + Orientation: 'Rotate 90 CW', + XResolution: 72, + YResolution: 72, + ResolutionUnit: 'inches', + YCbCrPositioning: 'Centered', + XMPToolkit: 'Image::ExifTool 10.40', + CreatorWorkURL: 'https://sobesednik.media', + Scene: '011200', + Creator: 'Photographer Name', + ImageWidth: 500, + ImageHeight: 334, + EncodingProcess: 'Baseline DCT, Huffman coding', + BitsPerSample: 8, + ColorComponents: 3, + YCbCrSubSampling: 'YCbCr4:2:0 (2 2)', + ImageSize: '500x334', + Megapixels: 0.167 + }; + Object.keys(expected).forEach(function (key) { + return assert.equal(metadata[key], expected[key]); + }); + }); + }, + 'returns promise with null data and error when file not found': function returnsPromiseWithNullDataAndErrorWhenFileNotFound(ctx) { + return ctx.initAndReadMetadata(ctx.fileDoesNotExist).then(function (res) { + assert.equal(res.data, null); + assert.equal(res.error, 'File not found: ' + ctx.fileDoesNotExist); + }); + }, + 'works with simultaneous requests': function worksWithSimultaneousRequests(ctx) { + return ctx.createOpen().then(function () { + return Promise.all([ctx.ep.readMetadata(ctx.fileDoesNotExist), ctx.ep.readMetadata(ctx.fileDoesNotExist2), ctx.ep.readMetadata(ctx.jpegFile), ctx.ep.readMetadata(ctx.jpegFile2)]); + }).then(function (res) { + assert.equal(res[0].data, null); + assert.equal(res[0].error, 'File not found: ' + ctx.fileDoesNotExist); + + assert.equal(res[1].data, null); + assert.equal(res[1].error, 'File not found: ' + ctx.fileDoesNotExist2); + + assert(Array.isArray(res[2].data)); + assert.equal(res[2].error, null); + res[2].data.forEach(ctx.assertJpegMetadata); + + assert(Array.isArray(res[3].data)); + assert.equal(res[3].error, null); + res[3].data.forEach(ctx.assertJpegMetadata); + }); + } + }, + writeMetadata: { + 'returns rejected promise when trying to execute when not open': function returnsRejectedPromiseWhenTryingToExecuteWhenNotOpen(ctx) { + return ctx.create().writeMetadata('/temp-file', { comment: 'test-comment' }, ['overwrite_original']).then(function () { + throw new Error('writeMetadata should have resulted in error'); + }).catch(function (err) { + return assert.equal(err.message, 'exiftool is not open'); + }); + }, + 'should return rejected promise when data is not an object': function shouldReturnRejectedPromiseWhenDataIsNotAnObject(ctx) { + return ctx.initAndWriteMetadata('file_path').then(function () { + throw new Error('writeMetadata should have resulted in error'); + }, function (err) { + assert.equal(err.message, 'Data argument is not an object'); + }); + }, + 'should write metadata': function shouldWriteMetadata(ctx) { + var keywords = ['keywordA', 'keywordB']; + var comment = 'hello world'; + var data = { + all: '', + comment: comment, // has to come after all in order not to be removed + 'Keywords+': keywords + }; + return ctx.createTempFile().then(function () { + return ctx.initAndWriteMetadata(ctx.tempFile, data, ['overwrite_original']); + }).then(function (res) { + assert.equal(res.data, null); + assert.equal(res.error, '1 image files updated'); + }).then(function () { + return ctx.ep.readMetadata(ctx.tempFile); + }).then(function (res) { + assert(Array.isArray(res.data)); + assert.equal(res.error, null); + + var _res$data2 = _slicedToArray(res.data, 1), + metadata = _res$data2[0]; + + assert.equal(metadata.Keywords.length, keywords.length); + metadata.Keywords.forEach(function (keyword, index) { + assert.equal(keyword, keywords[index]); + }); + assert.equal(metadata.Comment, comment); + assert.equal(metadata.Scene, undefined); // should be removed with -all= + }); + } + } +}; + +module.exports = exiftoolTestSuite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9leGlmdG9vbC5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiRU9MIiwiYXNzZXJ0IiwiY2hpbGRfcHJvY2VzcyIsImNvbnRleHQiLCJleGlmdG9vbCIsImdsb2JhbEV4aWZ0b29sQ29uc3RydWN0b3IiLCJFeGlmdG9vbFByb2Nlc3MiLCJDaGlsZFByb2Nlc3MiLCJleGlmdG9vbFRlc3RTdWl0ZSIsIm9wZW4iLCJjdHgiLCJjcmVhdGVPcGVuIiwidGhlbiIsInBpZCIsImVwIiwiX3Byb2Nlc3MiLCJzdGRvdXQiLCJyZWFkYWJsZSIsInN0ZGVyciIsInN0ZGluIiwid3JpdGFibGUiLCJpc09wZW4iLCJlcXVhbCIsIkVycm9yIiwiZXJyIiwibWVzc2FnZSIsImNyZWF0ZSIsImV2ZW50UHJvbWlzZSIsIlByb21pc2UiLCJvbiIsImV2ZW50cyIsIk9QRU4iLCJyZXNvbHZlIiwiY2xvc2UiLCJfc3Rkb3V0UmVzb2x2ZVdzIiwiX3dyaXRhYmxlU3RhdGUiLCJmaW5pc2hlZCIsIl9zdGRlcnJSZXNvbHZlV3MiLCJwIiwicmVhZE1ldGFkYXRhIiwianBlZ0ZpbGUiLCJyZXMiLCJBcnJheSIsImlzQXJyYXkiLCJkYXRhIiwiZXJyb3IiLCJmb3JFYWNoIiwiYXNzZXJ0SnBlZ01ldGFkYXRhIiwicDIiLCJqcGVnRmlsZTIiLCJyZWFkUHJvbWlzZXMiLCJhbGwiLCJPYmplY3QiLCJrZXlzIiwiX3Jlc29sdmVNYXAiLCJsZW5ndGgiLCJFWElUIiwiY2F0Y2giLCJpbml0QW5kUmVhZE1ldGFkYXRhIiwiZm9sZGVyIiwiZW1wdHlGb2xkZXIiLCJleHBlY3RlZCIsIlNvdXJjZUZpbGUiLCJyZXBsYWNlU2xhc2hlcyIsIk9yaWVudGF0aW9uIiwiZGVlcEVxdWFsIiwibWV0YWRhdGEiLCJEaXJlY3RvcnkiLCJGaWxlTmFtZSIsIkZpbGVTaXplIiwiRmlsZVR5cGUiLCJGaWxlVHlwZUV4dGVuc2lvbiIsIk1JTUVUeXBlIiwiRXhpZkJ5dGVPcmRlciIsIlhSZXNvbHV0aW9uIiwiWVJlc29sdXRpb24iLCJSZXNvbHV0aW9uVW5pdCIsIllDYkNyUG9zaXRpb25pbmciLCJYTVBUb29sa2l0IiwiQ3JlYXRvcldvcmtVUkwiLCJTY2VuZSIsIkNyZWF0b3IiLCJJbWFnZVdpZHRoIiwiSW1hZ2VIZWlnaHQiLCJFbmNvZGluZ1Byb2Nlc3MiLCJCaXRzUGVyU2FtcGxlIiwiQ29sb3JDb21wb25lbnRzIiwiWUNiQ3JTdWJTYW1wbGluZyIsIkltYWdlU2l6ZSIsIk1lZ2FwaXhlbHMiLCJrZXkiLCJmaWxlRG9lc05vdEV4aXN0IiwiZmlsZURvZXNOb3RFeGlzdDIiLCJ3cml0ZU1ldGFkYXRhIiwiY29tbWVudCIsImluaXRBbmRXcml0ZU1ldGFkYXRhIiwia2V5d29yZHMiLCJjcmVhdGVUZW1wRmlsZSIsInRlbXBGaWxlIiwiS2V5d29yZHMiLCJrZXl3b3JkIiwiaW5kZXgiLCJDb21tZW50IiwidW5kZWZpbmVkIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7ZUFBZ0JBLFFBQVEsSUFBUixDO0lBQVJDLEcsWUFBQUEsRzs7QUFDUixJQUFNQyxTQUFTRixRQUFRLFFBQVIsQ0FBZjtBQUNBLElBQU1HLGdCQUFnQkgsUUFBUSxlQUFSLENBQXRCO0FBQ0EsSUFBTUksVUFBVUosUUFBUSxrQkFBUixDQUFoQjtBQUNBLElBQU1LLFdBQVdMLFFBQVEsWUFBUixDQUFqQjtBQUNBSSxRQUFRRSx5QkFBUixHQUFvQ0QsU0FBU0UsZUFBN0M7O0lBRVFDLFksR0FBaUJMLGEsQ0FBakJLLFk7OztBQUVSLElBQU1DLG9CQUFvQjtBQUN0Qkwsb0JBRHNCO0FBRXRCTSxVQUFNO0FBQ0YsMEJBQWtCLHVCQUFDQyxHQUFELEVBQVM7QUFDdkIsbUJBQU9BLElBQUlDLFVBQUosR0FDRkMsSUFERSxDQUNHLFVBQUNDLEdBQUQsRUFBUztBQUNYWix1QkFBT1MsSUFBSUksRUFBSixDQUFPQyxRQUFQLFlBQTJCUixZQUFsQztBQUNBTix1QkFBT1MsSUFBSUksRUFBSixDQUFP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aUJBQWpCIiwiZmlsZSI6ImV4aWZ0b29sLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgeyBFT0wgfSA9IHJlcXVpcmUoJ29zJylcbmNvbnN0IGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpXG5jb25zdCBjaGlsZF9wcm9jZXNzID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpXG5jb25zdCBjb250ZXh0ID0gcmVxdWlyZSgnZXhpZnRvb2wtY29udGV4dCcpXG5jb25zdCBleGlmdG9vbCA9IHJlcXVpcmUoJy4uLy4uL3NyYy8nKVxuY29udGV4dC5nbG9iYWxFeGlmdG9vbENvbnN0cnVjdG9yID0gZXhpZnRvb2wuRXhpZnRvb2xQcm9jZXNzXG5cbmNvbnN0IHsgQ2hpbGRQcm9jZXNzIH0gPSBjaGlsZF9wcm9jZXNzXG5cbmNvbnN0IGV4aWZ0b29sVGVzdFN1aXRlID0ge1xuICAgIGNvbnRleHQsXG4gICAgb3Blbjoge1xuICAgICAgICAnb3BlbnMgZXhpZnRvb2wnOiAoY3R4KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gY3R4LmNyZWF0ZU9wZW4oKVxuICAgICAgICAgICAgICAgIC50aGVuKChwaWQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KGN0eC5lcC5fcHJvY2VzcyBpbnN0YW5jZW9mIENoaWxkUHJvY2VzcylcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KGN0eC5lcC5fcHJvY2Vzcy5zdGRvdXQucmVhZGFibGUpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChjdHguZXAuX3Byb2Nlc3Muc3RkZXJyLnJlYWRhYmxlKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoY3R4LmVwLl9wcm9jZXNzLnN0ZGluLndyaXRhYmxlKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoY3R4LmVwLmlzT3BlbilcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHR5cGVvZiBwaWQsICdudW1iZXInKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocGlkLCBjdHguZXAuX3Byb2Nlc3MucGlkKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgICAgICdyZXR1cm5zIHJlamVjdGVkIHByb21pc2Ugd2hlbiBleGlmdG9vbCBleGVjdXRhYmxlIG5vdCBmb3VuZCc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguY3JlYXRlT3Blbignbm90ZXhpZnRvb2wnKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvcGVuIHNob3VsZCBoYXZlIHJlc3VsdGVkIGluIGVycm9yJylcbiAgICAgICAgICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChlcnIubWVzc2FnZSwgJ3NwYXduIG5vdGV4aWZ0b29sIEVOT0VOVCcpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfSxcbiAgICAgICAgJ2VtaXRzIE9QRU4gZXZlbnQgd2l0aCBQSUQnOiAoY3R4KSA9PiB7XG4gICAgICAgICAgICBjdHguY3JlYXRlKClcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50UHJvbWlzZSA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT5cbiAgICAgICAgICAgICAgICBjdHguZXAub24oZXhpZnRvb2wuZXZlbnRzLk9QRU4sIHJlc29sdmUpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICByZXR1cm4gY3R4Lm9wZW4oKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IGV2ZW50UHJvbWlzZSlcbiAgICAgICAgICAgICAgICAudGhlbihwaWQgPT4gYXNzZXJ0LmVxdWFsKHBpZCwgY3R4LmVwLl9wcm9jZXNzLnBpZCkpXG4gICAgICAgIH0sXG4gICAgICAgICdyZXR1cm5zIHJlamVjdGVkIHByb21pc2Ugd2hlbiBwcm9jZXNzIGlzIG9wZW4gYWxyZWFkeSc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguY3JlYXRlT3BlbigpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gY3R4Lm9wZW4oKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignc2Vjb25kIG9wZW4gc2hvdWxkIGhhdmUgcmVzdWx0ZWQgaW4gZXJyb3InKVxuICAgICAgICAgICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnRXhpZnRvb2wgcHJvY2VzcyBpcyBhbHJlYWR5IG9wZW4nKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgfSxcbiAgICBjbG9zZToge1xuICAgICAgICAnY2xvc2VzIHRoZSBwcm9jZXNzJzogKGN0eCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGN0eC5jcmVhdGVPcGVuKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBjdHguY2xvc2UoKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChjdHguZXAuX3Byb2Nlc3MgaW5zdGFuY2VvZiBDaGlsZFByb2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydCghY3R4LmVwLl9wcm9jZXNzLnN0ZG91dC5yZWFkYWJsZSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KCFjdHguZXAuX3Byb2Nlc3Muc3RkZXJyLnJlYWRhYmxlKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoIWN0eC5lcC5fcHJvY2Vzcy5zdGRpbi53cml0YWJsZSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KCFjdHguZXAuaXNPcGVuKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgICAgICd1cGRhdGVzIHJlc29sdmUgd3JpdGUgc3RyZWFtcyB0byBiZSBmaW5pc2hlZCc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguY3JlYXRlT3BlbigpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gY3R4LmNsb3NlKCkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoY3R4LmVwLl9zdGRvdXRSZXNvbHZlV3MuX3dyaXRhYmxlU3RhdGUuZmluaXNoZWQpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChjdHguZXAuX3N0ZGVyclJlc29sdmVXcy5fd3JpdGFibGVTdGF0ZS5maW5pc2hlZClcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgICAgICAnY29tcGxldGVzIHJlbWFpbmluZyBqb2JzJzogKGN0eCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGN0eC5jcmVhdGVPcGVuKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHAgPSBjdHguZXBcbiAgICAgICAgICAgICAgICAgICAgICAgIC5yZWFkTWV0YWRhdGEoY3R4LmpwZWdGaWxlKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydChBcnJheS5pc0FycmF5KHJlcy5kYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmVycm9yLCBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcy5kYXRhLmZvckVhY2goY3R4LmFzc2VydEpwZWdNZXRhZGF0YSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHAyID0gY3R4LmVwXG4gICAgICAgICAgICAgICAgICAgICAgICAucmVhZE1ldGFkYXRhKGN0eC5qcGVnRmlsZTIpXG4gICAgICAgICAgICAgICAgICAgICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KEFycmF5LmlzQXJyYXkocmVzLmRhdGEpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXMuZXJyb3IsIG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzLmRhdGEuZm9yRWFjaChjdHguYXNzZXJ0SnBlZ01ldGFkYXRhKVxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhZFByb21pc2VzID0gUHJvbWlzZS5hbGwoW3AsIHAyXSlcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3R4LmNsb3NlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQoIU9iamVjdC5rZXlzKGN0eC5lcC5fc3Rkb3V0UmVzb2x2ZVdzLl9yZXNvbHZlTWFwKS5sZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KCFPYmplY3Qua2V5cyhjdHguZXAuX3N0ZGVyclJlc29sdmVXcy5fcmVzb2x2ZU1hcCkubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlYWRQcm9taXNlcylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgICAgICAnZW1pdHMgRVhJVCBldmVudCc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIGN0eC5jcmVhdGUoKVxuICAgICAgICAgICAgY29uc3QgZXZlbnRQcm9taXNlID0gbmV3IFByb21pc2UocmVzb2x2ZSA9PlxuICAgICAgICAgICAgICAgIGN0eC5lcC5vbihleGlmdG9vbC5ldmVudHMuRVhJVCwgcmVzb2x2ZSlcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIHJldHVybiBjdHgub3BlbigpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gY3R4LmNsb3NlKCkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gZXZlbnRQcm9taXNlKVxuICAgICAgICB9LFxuICAgICAgICAnc2V0cyBvcGVuIHRvIGZhbHNlJzogKGN0eCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGN0eC5jcmVhdGVPcGVuKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBjdHguY2xvc2UoKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBhc3NlcnQoIWN0eC5lcC5pc09wZW4pKVxuICAgICAgICB9LFxuICAgICAgICAncmV0dXJucyByZWplY3RlZCBwcm9taXNlIHdoZW4gcHJvY2VzcyBub3Qgb3Blbic6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguY3JlYXRlKClcbiAgICAgICAgICAgICAgICAuY2xvc2UoKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjbG9zZSBzaG91bGQgaGF2ZSByZXN1bHRlZCBpbiBlcnJvcicpXG4gICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwoZXJyLm1lc3NhZ2UsICdFeGlmdG9vbCBwcm9jZXNzIGlzIG5vdCBvcGVuJylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgIH0sXG4gICAgcmVhZE1ldGFkYXRhOiB7XG4gICAgICAgICdyZXR1cm5zIHJlamVjdGVkIHByb21pc2Ugd2hlbiB0cnlpbmcgdG8gZXhlY3V0ZSB3aGVuIG5vdCBvcGVuJzogKGN0eCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGN0eC5jcmVhdGUoKVxuICAgICAgICAgICAgICAgIC5yZWFkTWV0YWRhdGEoY3R4LmpwZWdGaWxlKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWFkTWV0YWRhdGEgc2hvdWxkIGhhdmUgcmVzdWx0ZWQgaW4gZXJyb3InKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVyciA9PiBhc3NlcnQuZXF1YWwoZXJyLm1lc3NhZ2UsICdleGlmdG9vbCBpcyBub3Qgb3BlbicpKVxuICAgICAgICB9LFxuICAgICAgICAncmVhZHMgbWV0YWRhdGEgb2YgZmlsZXMgaW4gYSBkaXJlY3RvcnknOiAoY3R4KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gY3R4LmluaXRBbmRSZWFkTWV0YWRhdGEoY3R4LmZvbGRlcilcbiAgICAgICAgICAgICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChBcnJheS5pc0FycmF5KHJlcy5kYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5kYXRhLmxlbmd0aCwgNSlcbiAgICAgICAgICAgICAgICAgICAgcmVzLmRhdGEuZm9yRWFjaChjdHguYXNzZXJ0SnBlZ01ldGFkYXRhKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmVycm9yLCBgMSBkaXJlY3RvcmllcyBzY2FubmVkJHtFT0x9ICAgIDUgaW1hZ2UgZmlsZXMgcmVhZGApXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfSxcbiAgICAgICAgJ3JldHVybnMgbnVsbCBkYXRhIGZvciBlbXB0eSBkaXJlY3RvcnkgYW5kIGluZm8gZXJyb3InOiAoY3R4KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gY3R4LmluaXRBbmRSZWFkTWV0YWRhdGEoY3R4LmVtcHR5Rm9sZGVyKVxuICAgICAgICAgICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5kYXRhLCBudWxsKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmVycm9yLCBgMSBkaXJlY3RvcmllcyBzY2FubmVkJHtFT0x9ICAgIDAgaW1hZ2UgZmlsZXMgcmVhZGApXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfSxcbiAgICAgICAgJ2FsbG93cyB0byBzcGVjaWZ5IGFyZ3VtZW50cyc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguaW5pdEFuZFJlYWRNZXRhZGF0YShjdHguanBlZ0ZpbGUsIFsnT3JpZW50YXRpb24nLCAnbiddKVxuICAgICAgICAgICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5lcnJvciwgbnVsbClcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KEFycmF5LmlzQXJyYXkocmVzLmRhdGEpKVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBleHBlY3RlZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFNvdXJjZUZpbGU6IGN0eC5yZXBsYWNlU2xhc2hlcyhjdHguanBlZ0ZpbGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgT3JpZW50YXRpb246IDYsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmRlZXBFcXVhbChyZXMuZGF0YVswXSwgZXhwZWN0ZWQpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfSxcbiAgICAgICAgJ3JlYWRzIG1ldGFkYXRhIG9mIGEgZmlsZSc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguaW5pdEFuZFJlYWRNZXRhZGF0YShjdHguanBlZ0ZpbGUpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmVycm9yLCBudWxsKVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoQXJyYXkuaXNBcnJheShyZXMuZGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgZGF0YTogW21ldGFkYXRhXSB9ID0gcmVzXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgU291cmNlRmlsZTogY3R4LnJlcGxhY2VTbGFzaGVzKGN0eC5qcGVnRmlsZSksXG4gICAgICAgICAgICAgICAgICAgICAgICBEaXJlY3Rvcnk6IGN0eC5yZXBsYWNlU2xhc2hlcyhjdHguZm9sZGVyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIEZpbGVOYW1lOiAnSU1HXzk4NTguSlBHJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIEZpbGVTaXplOiAnNTIga0InLFxuICAgICAgICAgICAgICAgICAgICAgICAgRmlsZVR5cGU6ICdKUEVHJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIEZpbGVUeXBlRXh0ZW5zaW9uOiAnanBnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIE1JTUVUeXBlOiAnaW1hZ2UvanBlZycsXG4gICAgICAgICAgICAgICAgICAgICAgICBFeGlmQnl0ZU9yZGVyOiAnQmlnLWVuZGlhbiAoTW90b3JvbGEsIE1NKScsXG4gICAgICAgICAgICAgICAgICAgICAgICBPcmllbnRhdGlvbjogJ1JvdGF0ZSA5MCBDVycsXG4gICAgICAgICAgICAgICAgICAgICAgICBYUmVzb2x1dGlvbjogNzIsXG4gICAgICAgICAgICAgICAgICAgICAgICBZUmVzb2x1dGlvbjogNzIsXG4gICAgICAgICAgICAgICAgICAgICAgICBSZXNvbHV0aW9uVW5pdDogJ2luY2hlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICBZQ2JDclBvc2l0aW9uaW5nOiAnQ2VudGVyZWQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgWE1QVG9vbGtpdDogJ0ltYWdlOjpFeGlmVG9vbCAxMC40MCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBDcmVhdG9yV29ya1VSTDogJ2h0dHBzOi8vc29iZXNlZG5pay5tZWRpYScsXG4gICAgICAgICAgICAgICAgICAgICAgICBTY2VuZTogJzAxMTIwMCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBDcmVhdG9yOiAnUGhvdG9ncmFwaGVyIE5hbWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgSW1hZ2VXaWR0aDogNTAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgSW1hZ2VIZWlnaHQ6IDMzNCxcbiAgICAgICAgICAgICAgICAgICAgICAgIEVuY29kaW5nUHJvY2VzczogJ0Jhc2VsaW5lIERDVCwgSHVmZm1hbiBjb2RpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgQml0c1BlclNhbXBsZTogOCxcbiAgICAgICAgICAgICAgICAgICAgICAgIENvbG9yQ29tcG9uZW50czogMyxcbiAgICAgICAgICAgICAgICAgICAgICAgIFlDYkNyU3ViU2FtcGxpbmc6ICdZQ2JDcjQ6MjowICgyIDIpJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIEltYWdlU2l6ZTogJzUwMHgzMzQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgTWVnYXBpeGVsczogMC4xNjcsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAua2V5cyhleHBlY3RlZClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5mb3JFYWNoKGtleSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChtZXRhZGF0YVtrZXldLCBleHBlY3RlZFtrZXldKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgICAgICdyZXR1cm5zIHByb21pc2Ugd2l0aCBudWxsIGRhdGEgYW5kIGVycm9yIHdoZW4gZmlsZSBub3QgZm91bmQnOiAoY3R4KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gY3R4LmluaXRBbmRSZWFkTWV0YWRhdGEoY3R4LmZpbGVEb2VzTm90RXhpc3QpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmRhdGEsIG51bGwpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXMuZXJyb3IsIGBGaWxlIG5vdCBmb3VuZDogJHtjdHguZmlsZURvZXNOb3RFeGlzdH1gKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgICAgICd3b3JrcyB3aXRoIHNpbXVsdGFuZW91cyByZXF1ZXN0cyc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguY3JlYXRlT3BlbigpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgICAgICAgICBjdHguZXAucmVhZE1ldGFkYXRhKGN0eC5maWxlRG9lc05vdEV4aXN0KSxcbiAgICAgICAgICAgICAgICAgICAgY3R4LmVwLnJlYWRNZXRhZGF0YShjdHguZmlsZURvZXNOb3RFeGlzdDIpLFxuICAgICAgICAgICAgICAgICAgICBjdHguZXAucmVhZE1ldGFkYXRhKGN0eC5qcGVnRmlsZSksXG4gICAgICAgICAgICAgICAgICAgIGN0eC5lcC5yZWFkTWV0YWRhdGEoY3R4LmpwZWdGaWxlMiksXG4gICAgICAgICAgICAgICAgXSkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzWzBdLmRhdGEsIG51bGwpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXNbMF0uZXJyb3IsIGBGaWxlIG5vdCBmb3VuZDogJHtjdHguZmlsZURvZXNOb3RFeGlzdH1gKVxuXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXNbMV0uZGF0YSwgbnVsbClcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc1sxXS5lcnJvciwgYEZpbGUgbm90IGZvdW5kOiAke2N0eC5maWxlRG9lc05vdEV4aXN0Mn1gKVxuXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChBcnJheS5pc0FycmF5KHJlc1syXS5kYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc1syXS5lcnJvciwgbnVsbClcbiAgICAgICAgICAgICAgICAgICAgcmVzWzJdLmRhdGEuZm9yRWFjaChjdHguYXNzZXJ0SnBlZ01ldGFkYXRhKVxuXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChBcnJheS5pc0FycmF5KHJlc1szXS5kYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc1szXS5lcnJvciwgbnVsbClcbiAgICAgICAgICAgICAgICAgICAgcmVzWzNdLmRhdGEuZm9yRWFjaChjdHguYXNzZXJ0SnBlZ01ldGFkYXRhKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgfSxcbiAgICB3cml0ZU1ldGFkYXRhOiB7XG4gICAgICAgICdyZXR1cm5zIHJlamVjdGVkIHByb21pc2Ugd2hlbiB0cnlpbmcgdG8gZXhlY3V0ZSB3aGVuIG5vdCBvcGVuJzogKGN0eCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGN0eC5jcmVhdGUoKVxuICAgICAgICAgICAgICAgIC53cml0ZU1ldGFkYXRhKCcvdGVtcC1maWxlJywgeyBjb21tZW50OiAndGVzdC1jb21tZW50JyB9LCBbJ292ZXJ3cml0ZV9vcmlnaW5hbCddKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd3cml0ZU1ldGFkYXRhIHNob3VsZCBoYXZlIHJlc3VsdGVkIGluIGVycm9yJylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnIgPT4gYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnZXhpZnRvb2wgaXMgbm90IG9wZW4nKSlcbiAgICAgICAgfSxcbiAgICAgICAgJ3Nob3VsZCByZXR1cm4gcmVqZWN0ZWQgcHJvbWlzZSB3aGVuIGRhdGEgaXMgbm90IGFuIG9iamVjdCc6IChjdHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjdHguaW5pdEFuZFdyaXRlTWV0YWRhdGEoJ2ZpbGVfcGF0aCcpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3dyaXRlTWV0YWRhdGEgc2hvdWxkIGhhdmUgcmVzdWx0ZWQgaW4gZXJyb3InKVxuICAgICAgICAgICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnRGF0YSBhcmd1bWVudCBpcyBub3QgYW4gb2JqZWN0JylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIHdyaXRlIG1ldGFkYXRhJzogKGN0eCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qga2V5d29yZHMgPSBbICdrZXl3b3JkQScsICdrZXl3b3JkQicgXVxuICAgICAgICAgICAgY29uc3QgY29tbWVudCA9ICdoZWxsbyB3b3JsZCdcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgICAgICAgYWxsOiAnJyxcbiAgICAgICAgICAgICAgICBjb21tZW50LCAvLyBoYXMgdG8gY29tZSBhZnRlciBhbGwgaW4gb3JkZXIgbm90IHRvIGJlIHJlbW92ZWRcbiAgICAgICAgICAgICAgICAnS2V5d29yZHMrJzoga2V5d29yZHMsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY3R4LmNyZWF0ZVRlbXBGaWxlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBjdHguaW5pdEFuZFdyaXRlTWV0YWRhdGEoY3R4LnRlbXBGaWxlLCBkYXRhLCBbJ292ZXJ3cml0ZV9vcmlnaW5hbCddKSlcbiAgICAgICAgICAgICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXMuZGF0YSwgbnVsbClcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5lcnJvciwgJzEgaW1hZ2UgZmlsZXMgdXBkYXRlZCcpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBjdHguZXAucmVhZE1ldGFkYXRhKGN0eC50ZW1wRmlsZSkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoQXJyYXkuaXNBcnJheShyZXMuZGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXMuZXJyb3IsIG51bGwpXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgZGF0YTogW21ldGFkYXRhXSB9ID0gcmVzXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChtZXRhZGF0YS5LZXl3b3Jkcy5sZW5ndGgsIGtleXdvcmRzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEuS2V5d29yZHMuZm9yRWFjaCgoa2V5d29yZCwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChrZXl3b3JkLCBrZXl3b3Jkc1tpbmRleF0pXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChtZXRhZGF0YS5Db21tZW50LCBjb21tZW50KVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwobWV0YWRhdGEuU2NlbmUsIHVuZGVmaW5lZCkgLy8gc2hvdWxkIGJlIHJlbW92ZWQgd2l0aCAtYWxsPVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgfSxcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBleGlmdG9vbFRlc3RTdWl0ZVxuIl19 \ No newline at end of file diff --git a/dist/test/spec/filename-encoding.js b/dist/test/spec/filename-encoding.js new file mode 100644 index 0000000..b9864d8 --- /dev/null +++ b/dist/test/spec/filename-encoding.js @@ -0,0 +1,39 @@ +'use strict'; + +require('source-map-support/register'); + +var assert = require('assert'); +var context = require('exiftool-context'); +var exiftool = require('../../src/'); +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +/* +* If something is going wrong with this test suite, check +* https://github.com/Sobesednik/exiftool-context#filenamewithencoding +*/ +var Encoding = { + context: context, + /*'should contain correct file in the repo': (ctx) => { + const fs = require('fs') + const path = require('path') + const basename = path.basename(ctx.filenameWithEncoding) + const dir = path.dirname(ctx.filenameWithEncoding) + console.log('File to read: %s', ctx.filenameWithEncoding) + console.log('Filename in unicode to read: %s', ctx.toUnicode(basename)) + const res = fs.readdirSync(dir) + console.log('Files in fixtures:') + res.map(n => ` ${n}: ${ctx.toUnicode(n)}`).forEach(n => console.log(n)) + },*/ + 'should read file with filename in utf8': function shouldReadFileWithFilenameInUtf8(ctx) { + return ctx.initAndReadMetadata(ctx.filenameWithEncoding, ['charset filename=utf8']).then(function (res) { + assert.notEqual(res.data, null); + assert.equal(res.data[0].SourceFile, ctx.replaceSlashes(ctx.filenameWithEncoding)); + assert.equal(res.error, null); + }); + } +}; + +module.exports = { + encoding: Encoding +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9maWxlbmFtZS1lbmNvZGluZy5qcyJdLCJuYW1lcyI6WyJhc3NlcnQiLCJyZXF1aXJlIiwiY29udGV4dCIsImV4aWZ0b29sIiwiZ2xvYmFsRXhpZnRvb2xDb25zdHJ1Y3RvciIsIkV4aWZ0b29sUHJvY2VzcyIsIkVuY29kaW5nIiwiY3R4IiwiaW5pdEFuZFJlYWRNZXRhZGF0YSIsImZpbGVuYW1lV2l0aEVuY29kaW5nIiwidGhlbiIsInJlcyIsIm5vdEVxdWFsIiwiZGF0YSIsImVxdWFsIiwiU291cmNlRmlsZSIsInJlcGxhY2VTbGFzaGVzIiwiZXJyb3IiLCJtb2R1bGUiLCJleHBvcnRzIiwiZW5jb2RpbmciXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxJQUFNQSxTQUFTQyxRQUFRLFFBQVIsQ0FBZjtBQUNBLElBQU1DLFVBQVVELFFBQVEsa0JBQVIsQ0FBaEI7QUFDQSxJQUFNRSxXQUFXRixRQUFRLFlBQVIsQ0FBakI7QUFDQUMsUUFBUUUseUJBQVIsR0FBb0NELFNBQVNFLGVBQTdDOztBQUVBOzs7O0FBSUEsSUFBTUMsV0FBVztBQUNiSixvQkFEYTtBQUViOzs7Ozs7Ozs7OztBQVlBLDhDQUEwQywwQ0FBQ0ssR0FBRCxFQUFTO0FBQy9DLGVBQU9BLElBQUlDLG1CQUFKLENBQXdCRCxJQUFJRSxvQkFBNUIsRUFBa0QsQ0FBQyx1QkFBRCxDQUFsRCxFQUNGQyxJQURFLENBQ0csVUFBQ0MsR0FBRCxFQUFTO0FBQ1hYLG1CQUFPWSxRQUFQLENBQWdCRCxJQUFJRSxJQUFwQixFQUEwQixJQUExQjtBQUNBYixtQkFBT2MsS0FBUCxDQUNJSCxJQUFJRSxJQUFKLENBQVMsQ0FBVCxFQUFZRSxVQURoQixFQUVJUixJQUFJUyxjQUFKLENBQW1CVCxJQUFJRSxvQkFBdkIsQ0FGSjtBQUlBVCxtQkFBT2MsS0FBUCxDQUFhSCxJQUFJTSxLQUFqQixFQUF3QixJQUF4QjtBQUNILFNBUkUsQ0FBUDtBQVNIO0FBeEJZLENBQWpCOztBQTJCQUMsT0FBT0MsT0FBUCxHQUFpQjtBQUNiQyxjQUFVZDtBQURHLENBQWpCIiwiZmlsZSI6ImZpbGVuYW1lLWVuY29kaW5nLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0JylcbmNvbnN0IGNvbnRleHQgPSByZXF1aXJlKCdleGlmdG9vbC1jb250ZXh0JylcbmNvbnN0IGV4aWZ0b29sID0gcmVxdWlyZSgnLi4vLi4vc3JjLycpXG5jb250ZXh0Lmdsb2JhbEV4aWZ0b29sQ29uc3RydWN0b3IgPSBleGlmdG9vbC5FeGlmdG9vbFByb2Nlc3NcblxuLypcbiogSWYgc29tZXRoaW5nIGlzIGdvaW5nIHdyb25nIHdpdGggdGhpcyB0ZXN0IHN1aXRlLCBjaGVja1xuKiBodHRwczovL2dpdGh1Yi5jb20vU29iZXNlZG5pay9leGlmdG9vbC1jb250ZXh0I2ZpbGVuYW1ld2l0aGVuY29kaW5nXG4qL1xuY29uc3QgRW5jb2RpbmcgPSB7XG4gICAgY29udGV4dCxcbiAgICAvKidzaG91bGQgY29udGFpbiBjb3JyZWN0IGZpbGUgaW4gdGhlIHJlcG8nOiAoY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKVxuICAgICAgICBjb25zdCBwYXRoID0gcmVxdWlyZSgncGF0aCcpXG4gICAgICAgIGNvbnN0IGJhc2VuYW1lID0gcGF0aC5iYXNlbmFtZShjdHguZmlsZW5hbWVXaXRoRW5jb2RpbmcpXG4gICAgICAgIGNvbnN0IGRpciA9IHBhdGguZGlybmFtZShjdHguZmlsZW5hbWVXaXRoRW5jb2RpbmcpXG5cbiAgICAgICAgY29uc29sZS5sb2coJ0ZpbGUgdG8gcmVhZDogJXMnLCBjdHguZmlsZW5hbWVXaXRoRW5jb2RpbmcpXG4gICAgICAgIGNvbnNvbGUubG9nKCdGaWxlbmFtZSBpbiB1bmljb2RlIHRvIHJlYWQ6ICVzJywgY3R4LnRvVW5pY29kZShiYXNlbmFtZSkpXG4gICAgICAgIGNvbnN0IHJlcyA9IGZzLnJlYWRkaXJTeW5jKGRpcilcbiAgICAgICAgY29uc29sZS5sb2coJ0ZpbGVzIGluIGZpeHR1cmVzOicpXG4gICAgICAgIHJlcy5tYXAobiA9PiBgICR7bn06ICR7Y3R4LnRvVW5pY29kZShuKX1gKS5mb3JFYWNoKG4gPT4gY29uc29sZS5sb2cobikpXG4gICAgfSwqL1xuICAgICdzaG91bGQgcmVhZCBmaWxlIHdpdGggZmlsZW5hbWUgaW4gdXRmOCc6IChjdHgpID0+IHtcbiAgICAgICAgcmV0dXJuIGN0eC5pbml0QW5kUmVhZE1ldGFkYXRhKGN0eC5maWxlbmFtZVdpdGhFbmNvZGluZywgWydjaGFyc2V0IGZpbGVuYW1lPXV0ZjgnXSlcbiAgICAgICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgICAgICBhc3NlcnQubm90RXF1YWwocmVzLmRhdGEsIG51bGwpXG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKFxuICAgICAgICAgICAgICAgICAgICByZXMuZGF0YVswXS5Tb3VyY2VGaWxlLFxuICAgICAgICAgICAgICAgICAgICBjdHgucmVwbGFjZVNsYXNoZXMoY3R4LmZpbGVuYW1lV2l0aEVuY29kaW5nKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmVycm9yLCBudWxsKVxuICAgICAgICAgICAgfSlcbiAgICB9LFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBlbmNvZGluZzogRW5jb2RpbmcsXG59XG4iXX0= \ No newline at end of file diff --git a/dist/test/spec/handle-streams-finish.js b/dist/test/spec/handle-streams-finish.js new file mode 100644 index 0000000..555f205 --- /dev/null +++ b/dist/test/spec/handle-streams-finish.js @@ -0,0 +1,152 @@ +'use strict'; + +require('source-map-support/register'); + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +var context = require('exiftool-context'); +var assert = require('assert'); +var exiftool = require('../../src/'); +var killPid = require('../lib/kill-pid'); + +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +// kill with operating system methods, rather than sending a signal, +// which does not work on Windows +function kill(proc) { + if (process.platform !== 'win32') { + return new Promise(function (resolve, reject) { + proc.once('error', reject); + proc.once('exit', resolve); + process.kill(proc.pid); + }); + } + return killPid(proc.pid); +} + +var expected = 'stdout and stderr finished before operation was complete'; + +var runTest = function () { + var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(ctx, getOperationPromise, createTempFile) { + var operationPromise, killPromise, message; + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + ctx.create(); + + if (!createTempFile) { + _context.next = 4; + break; + } + + _context.next = 4; + return ctx.createTempFile(); + + case 4: + _context.next = 6; + return ctx.ep.open(); + + case 6: + // stdin might throw "read ECONNRESET" on Linux for some reason + ctx.ep._process.stdin.on('error', function () {}); + // patch stdout so that we never resolve read metadata promise + ctx.ep._stdoutResolveWs._write = function (obj, enc, next) { + next(); + }; + operationPromise = getOperationPromise(); + killPromise = kill(ctx.ep._process); + _context.prev = 10; + _context.next = 13; + return operationPromise; + + case 13: + throw new Error('Expected operation to be rejected'); + + case 16: + _context.prev = 16; + _context.t0 = _context['catch'](10); + message = _context.t0.message; + + assert.equal(message, expected); + _context.next = 22; + return killPromise; + + case 22: + case 'end': + return _context.stop(); + } + } + }, _callee, undefined, [[10, 16]]); + })); + + return function runTest(_x, _x2, _x3) { + return _ref.apply(this, arguments); + }; +}(); + +var closeStreamsOnExitTestSuite = { + context: context, + 'should return rejected promise when reading': function () { + var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(ctx) { + var getOperationPromise; + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + getOperationPromise = function getOperationPromise() { + return ctx.ep.readMetadata(ctx.folder); + }; + + _context2.next = 3; + return runTest(ctx, getOperationPromise); + + case 3: + case 'end': + return _context2.stop(); + } + } + }, _callee2, undefined); + })); + + return function shouldReturnRejectedPromiseWhenReading(_x4) { + return _ref3.apply(this, arguments); + }; + }(), + 'should return rejected promise when writing': function () { + var _ref4 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(ctx) { + var getOperationPromise; + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + getOperationPromise = function getOperationPromise() { + var keywords = ['keywordA', 'keywordB']; + var comment = 'hello world'; + var data = { + all: '', + comment: comment, // has to come after all in order not to be removed + 'Keywords+': keywords + }; + return ctx.ep.writeMetadata(ctx.tempFile, data, ['overwrite_original']); + }; + + _context3.next = 3; + return runTest(ctx, getOperationPromise, true); + + case 3: + case 'end': + return _context3.stop(); + } + } + }, _callee3, undefined); + })); + + return function shouldReturnRejectedPromiseWhenWriting(_x5) { + return _ref4.apply(this, arguments); + }; + }() +}; + +module.exports = closeStreamsOnExitTestSuite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9oYW5kbGUtc3RyZWFtcy1maW5pc2guanMiXSwibmFtZXMiOlsiY29udGV4dCIsInJlcXVpcmUiLCJhc3NlcnQiLCJleGlmdG9vbCIsImtpbGxQaWQiLCJnbG9iYWxFeGlmdG9vbENvbnN0cnVjdG9yIiwiRXhpZnRvb2xQcm9jZXNzIiwia2lsbCIsInByb2MiLCJwcm9jZXNzIiwicGxhdGZvcm0iLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsIm9uY2UiLCJwaWQiLCJleHBlY3RlZCIsInJ1blRlc3QiLCJjdHgiLCJnZXRPcGVyYXRpb25Qcm9taXNlIiwiY3JlYXRlVGVtcEZpbGUiLCJjcmVhdGUiLCJlcCIsIm9wZW4iLCJfcHJvY2VzcyIsInN0ZGluIiwib24iLCJfc3Rkb3V0UmVzb2x2ZVdzIiwiX3dyaXRlIiwib2JqIiwiZW5jIiwibmV4dCIsIm9wZXJhdGlvblByb21pc2UiLCJraWxsUHJvbWlzZSIsIkVycm9yIiwibWVzc2FnZSIsImVxdWFsIiwiY2xvc2VTdHJlYW1zT25FeGl0VGVzdFN1aXRlIiwicmVhZE1ldGFkYXRhIiwiZm9sZGVyIiwia2V5d29yZHMiLCJjb21tZW50IiwiZGF0YSIsImFsbCIsIndyaXRlTWV0YWRhdGEiLCJ0ZW1wRmlsZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQU1BLFVBQVVDLFFBQVEsa0JBQVIsQ0FBaEI7QUFDQSxJQUFNQyxTQUFTRCxRQUFRLFFBQVIsQ0FBZjtBQUNBLElBQU1FLFdBQVdGLFFBQVEsWUFBUixDQUFqQjtBQUNBLElBQU1HLFVBQVVILFFBQVEsaUJBQVIsQ0FBaEI7O0FBRUFELFFBQVFLLHlCQUFSLEdBQW9DRixTQUFTRyxlQUE3Qzs7QUFFQTtBQUNBO0FBQ0EsU0FBU0MsSUFBVCxDQUFjQyxJQUFkLEVBQW9CO0FBQ2hCLFFBQUlDLFFBQVFDLFFBQVIsS0FBcUIsT0FBekIsRUFBa0M7QUFDOUIsZUFBTyxJQUFJQyxPQUFK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MkIsT0FBT0MsT0FBUCxHQUFpQlYsMkJBQWpCIiwiZmlsZSI6ImhhbmRsZS1zdHJlYW1zLWZpbmlzaC5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGNvbnRleHQgPSByZXF1aXJlKCdleGlmdG9vbC1jb250ZXh0JylcbmNvbnN0IGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpXG5jb25zdCBleGlmdG9vbCA9IHJlcXVpcmUoJy4uLy4uL3NyYy8nKVxuY29uc3Qga2lsbFBpZCA9IHJlcXVpcmUoJy4uL2xpYi9raWxsLXBpZCcpXG5cbmNvbnRleHQuZ2xvYmFsRXhpZnRvb2xDb25zdHJ1Y3RvciA9IGV4aWZ0b29sLkV4aWZ0b29sUHJvY2Vzc1xuXG4vLyBraWxsIHdpdGggb3BlcmF0aW5nIHN5c3RlbSBtZXRob2RzLCByYXRoZXIgdGhhbiBzZW5kaW5nIGEgc2lnbmFsLFxuLy8gd2hpY2ggZG9lcyBub3Qgd29yayBvbiBXaW5kb3dzXG5mdW5jdGlvbiBraWxsKHByb2MpIHtcbiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSAhPT0gJ3dpbjMyJykge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHJvYy5vbmNlKCdlcnJvcicsIHJlamVjdClcbiAgICAgICAgICAgIHByb2Mub25jZSgnZXhpdCcsIHJlc29sdmUpXG4gICAgICAgICAgICBwcm9jZXNzLmtpbGwocHJvYy5waWQpXG4gICAgICAgIH0pXG4gICAgfVxuICAgIHJldHVybiBraWxsUGlkKHByb2MucGlkKVxufVxuXG5jb25zdCBleHBlY3RlZCA9ICdzdGRvdXQgYW5kIHN0ZGVyciBmaW5pc2hlZCBiZWZvcmUgb3BlcmF0aW9uIHdhcyBjb21wbGV0ZSdcblxuY29uc3QgcnVuVGVzdCA9IGFzeW5jIChjdHgsIGdldE9wZXJhdGlvblByb21pc2UsIGNyZWF0ZVRlbXBGaWxlKSA9PiB7XG4gICAgY3R4LmNyZWF0ZSgpXG4gICAgaWYgKGNyZWF0ZVRlbXBGaWxlKSBhd2FpdCBjdHguY3JlYXRlVGVtcEZpbGUoKVxuICAgIGF3YWl0IGN0eC5lcC5vcGVuKClcbiAgICAvLyBzdGRpbiBtaWdodCB0aHJvdyBcInJlYWQgRUNPTk5SRVNFVFwiIG9uIExpbnV4IGZvciBzb21lIHJlYXNvblxuICAgIGN0eC5lcC5fcHJvY2Vzcy5zdGRpbi5vbignZXJyb3InLCAoKSA9PiB7fSlcbiAgICAvLyBwYXRjaCBzdGRvdXQgc28gdGhhdCB3ZSBuZXZlciByZXNvbHZlIHJlYWQgbWV0YWRhdGEgcHJvbWlzZVxuICAgIGN0eC5lcC5fc3Rkb3V0UmVzb2x2ZVdzLl93cml0ZSA9IChvYmosIGVuYywgbmV4dCkgPT4ge1xuICAgICAgICBuZXh0KClcbiAgICB9XG4gICAgY29uc3Qgb3BlcmF0aW9uUHJvbWlzZSA9IGdldE9wZXJhdGlvblByb21pc2UoKVxuXG4gICAgY29uc3Qga2lsbFByb21pc2UgPSBraWxsKGN0eC5lcC5fcHJvY2VzcylcblxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IG9wZXJhdGlvblByb21pc2VcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCBvcGVyYXRpb24gdG8gYmUgcmVqZWN0ZWQnKVxuICAgIH0gY2F0Y2ggKHsgbWVzc2FnZSB9KSB7XG4gICAgICAgIGFzc2VydC5lcXVhbChtZXNzYWdlLCBleHBlY3RlZClcbiAgICAgICAgYXdhaXQga2lsbFByb21pc2VcbiAgICB9XG59XG5cbmNvbnN0IGNsb3NlU3RyZWFtc09uRXhpdFRlc3RTdWl0ZSA9IHtcbiAgICBjb250ZXh0LFxuICAgICdzaG91bGQgcmV0dXJuIHJlamVjdGVkIHByb21pc2Ugd2hlbiByZWFkaW5nJzogYXN5bmMgKGN0eCkgPT4ge1xuICAgICAgICBjb25zdCBnZXRPcGVyYXRpb25Qcm9taXNlID0gKCkgPT4gY3R4LmVwLnJlYWRNZXRhZGF0YShjdHguZm9sZGVyKVxuICAgICAgICBhd2FpdCBydW5UZXN0KGN0eCwgZ2V0T3BlcmF0aW9uUHJvbWlzZSlcbiAgICB9LFxuICAgICdzaG91bGQgcmV0dXJuIHJlamVjdGVkIHByb21pc2Ugd2hlbiB3cml0aW5nJzogYXN5bmMgKGN0eCkgPT4ge1xuICAgICAgICBjb25zdCBnZXRPcGVyYXRpb25Qcm9taXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qga2V5d29yZHMgPSBbICdrZXl3b3JkQScsICdrZXl3b3JkQicgXVxuICAgICAgICAgICAgY29uc3QgY29tbWVudCA9ICdoZWxsbyB3b3JsZCdcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgICAgICAgYWxsOiAnJyxcbiAgICAgICAgICAgICAgICBjb21tZW50LCAvLyBoYXMgdG8gY29tZSBhZnRlciBhbGwgaW4gb3JkZXIgbm90IHRvIGJlIHJlbW92ZWRcbiAgICAgICAgICAgICAgICAnS2V5d29yZHMrJzoga2V5d29yZHMsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY3R4LmVwLndyaXRlTWV0YWRhdGEoY3R4LnRlbXBGaWxlLCBkYXRhLCBbJ292ZXJ3cml0ZV9vcmlnaW5hbCddKVxuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgcnVuVGVzdChjdHgsIGdldE9wZXJhdGlvblByb21pc2UsIHRydWUpXG4gICAgfSxcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjbG9zZVN0cmVhbXNPbkV4aXRUZXN0U3VpdGVcbiJdfQ== \ No newline at end of file diff --git a/dist/test/spec/lib.js b/dist/test/spec/lib.js new file mode 100644 index 0000000..4d7414b --- /dev/null +++ b/dist/test/spec/lib.js @@ -0,0 +1,141 @@ +'use strict'; + +require('source-map-support/register'); + +var assert = require('assert'); + +var _require = require('os'), + EOL = _require.EOL; + +var lib = require('../../src/lib'); + +var libTestSuite = { + checkDataObject: { + 'should return true on object': function shouldReturnTrueOnObject() { + var data = { + comment: 'hello world' + }; + assert(lib.checkDataObject(data)); + }, + 'should return true on Object': function shouldReturnTrueOnObject() { + var data = new Object('foo'); + assert(lib.checkDataObject(data)); + }, + 'should return false on string': function shouldReturnFalseOnString() { + assert(!lib.checkDataObject('hello world')); + }, + 'should return false on boolean': function shouldReturnFalseOnBoolean() { + assert(!lib.checkDataObject(true)); + }, + 'should return false on array': function shouldReturnFalseOnArray() { + assert(!lib.checkDataObject(['hello world'])); + } + }, + mapDataToTagArray: { + 'should return an array with tags': function shouldReturnAnArrayWithTags() { + var data = { + tagA: 'valueA', + tagB: 'valueB' + }; + var res = lib.mapDataToTagArray(data); + assert.equal(res[0], 'tagA=valueA'); + assert.equal(res[1], 'tagB=valueB'); + }, + 'should return multiple entries when value is an array': function shouldReturnMultipleEntriesWhenValueIsAnArray() { + var data = { + 'tag+': ['valueA', 'valueB'] + }; + var res = lib.mapDataToTagArray(data); + assert.equal(res[0], 'tag+=valueA'); + assert.equal(res[1], 'tag+=valueB'); + }, + 'should push values to existing array': function shouldPushValuesToExistingArray() { + var array = ['json']; + var data = { + tagA: 'valueA', + tagB: 'valueB', + 'tagC+': ['valueC1', 'valueC2'] + + }; + lib.mapDataToTagArray(data, array); + assert.equal(array[0], 'json'); + assert.equal(array[1], 'tagA=valueA'); + assert.equal(array[2], 'tagB=valueB'); + assert.equal(array[3], 'tagC+=valueC1'); + assert.equal(array[4], 'tagC+=valueC2'); + } + }, + getArgs: { + 'should return empty array if argument is not array': function shouldReturnEmptyArrayIfArgumentIsNotArray() { + var res = lib.getArgs('non-array'); + assert.deepEqual(res, []); + }, + 'should return empty array if argument is empty array': function shouldReturnEmptyArrayIfArgumentIsEmptyArray() { + var res = lib.getArgs([]); + assert.deepEqual(res, []); + }, + 'should map args array to a string': function shouldMapArgsArrayToAString() { + var args = ['Creator', 'CreatorWorkURL', 'Orientation']; + var res = lib.getArgs(args); + var expected = ['-Creator', '-CreatorWorkURL', '-Orientation']; + assert.equal(res.length, expected.length); + res.forEach(function (arg, index) { + return assert.equal(arg, expected[index]); + }); + }, + 'should exclude non-strings': function shouldExcludeNonStrings() { + var args = ['Creator', 'CreatorWorkURL', 'Orientation', false, NaN, 1024]; + var res = lib.getArgs(args); + var expected = ['-Creator', '-CreatorWorkURL', '-Orientation']; + assert.equal(res.length, expected.length); + res.forEach(function (arg, index) { + return assert.equal(arg, expected[index]); + }); + }, + 'should split arguments': function shouldSplitArguments() { + var args = ['Creator', 'ext dng', 'o metadata.txt']; + var res = lib.getArgs(args); + var expected = ['-Creator', '-ext', 'dng', '-o', 'metadata.txt']; + assert.equal(res.length, expected.length); + res.forEach(function (arg, index) { + return assert.equal(arg, expected[index]); + }); + }, + 'should not split arguments with noSplit': function shouldNotSplitArgumentsWithNoSplit() { + var args = ['keywords+=keyword A', 'keywords+=keyword B', 'comment=hello world']; + var res = lib.getArgs(args, true); + var expected = ['-keywords+=keyword A', '-keywords+=keyword B', '-comment=hello world']; + assert.equal(res.length, expected.length); + res.forEach(function (arg, index) { + return assert.equal(arg, expected[index]); + }); + } + }, + execute: { + 'should write to process stdin': function shouldWriteToProcessStdin() { + var records = []; + var process = { + stdin: { + write: function write(record) { + return records.push(record); + } + } + }; + var command = 'file.jpg'; + var commandNumber = 1; + var args = ['Creator', 'ext dng', 'o metadata.txt', false, NaN]; + var noSplitArgs = ['comment=hello world']; + lib.execute(process, command, commandNumber, args, noSplitArgs); + var expected = ['-comment=hello world', '-Creator', '-ext', 'dng', '-o', 'metadata.txt', '-json', '-s', 'file.jpg', '-echo1', '{begin1}', '-echo2', '{begin1}', '-echo4', '{ready1}', '-execute1'].reduce(function (acc, arg) { + return [].concat(acc, [arg, EOL]); + }, []); + assert.equal(records.length, expected.length); + records.forEach(function (arg, index) { + return assert.equal(arg, expected[index]); + }); + } + } +}; + +module.exports = libTestSuite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9saWIuanMiXSwibmFtZXMiOlsiYXNzZXJ0IiwicmVxdWlyZSIsIkVPTCIsImxpYiIsImxpYlRlc3RTdWl0ZSIsImNoZWNrRGF0YU9iamVjdCIsImRhdGEiLCJjb21tZW50IiwiT2JqZWN0IiwibWFwRGF0YVRvVGFnQXJyYXkiLCJ0YWdBIiwidGFnQiIsInJlcyIsImVxdWFsIiwiYXJyYXkiLCJnZXRBcmdzIiwiZGVlcEVxdWFsIiwiYXJncyIsImV4cGVjdGVkIiwibGVuZ3RoIiwiZm9yRWFjaCIsImFyZyIsImluZGV4IiwiTmFOIiwiZXhlY3V0ZSIsInJlY29yZHMiLCJwcm9jZXNzIiwic3RkaW4iLCJ3cml0ZSIsInB1c2giLCJyZWNvcmQiLCJjb21tYW5kIiwiY29tbWFuZE51bWJlciIsIm5vU3BsaXRBcmdzIiwicmVkdWNlIiwiYWNjIiwiY29uY2F0IiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQU1BLFNBQVNDLFFBQVEsUUFBUixDQUFmOztlQUNnQkEsUUFBUSxJQUFSLEM7SUFBUkMsRyxZQUFBQSxHOztBQUNSLElBQU1DLE1BQU1GLFFBQVEsZUFBUixDQUFaOztBQUVBLElBQU1HLGVBQWU7QUFDakJDLHFCQUFpQjtBQUNiLHdDQUFnQyxvQ0FBTTtBQUNsQyxnQkFBTUMsT0FBTztBQUNUQyx5QkFBUztBQURBLGFBQWI7QUFHQVAsbUJBQU9HLElBQUlFLGVBQUosQ0FBb0JDLElBQXBCLENBQVA7QUFDSCxTQU5ZO0FBT2Isd0NBQWdDLG9DQUFNO0FBQ2xDLGdCQUFNQSxPQUFPLElBQUlFLE1BQUosQ0FBVyxLQUFYLENBQWI7QUFDQVIsbUJBQU9HLElBQUlFLGVBQUosQ0FBb0JDLElBQXBCLENBQVA7QUFDSCxTQVZZO0FBV2IseUNBQWlDLHFDQUFNO0FBQ25DTixtQkFBTyxDQUFDRyxJQUFJRSxlQUFKLENBQW9CLGFBQXBCLENBQVI7QUFDSCxTQWJZO0FBY2IsMENBQWtDLHNDQUFNO0FB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QmMsQ0FBakI7QUFvQkFGLG1CQUFPYSxLQUFQLENBQWFZLFFBQVFOLE1BQXJCLEVBQTZCRCxTQUFTQyxNQUF0QztBQUNBTSxvQkFBUUwsT0FBUixDQUFnQixVQUFDQyxHQUFELEVBQU1DLEtBQU47QUFBQSx1QkFDWnRCLE9BQU9hLEtBQVAsQ0FBYVEsR0FBYixFQUFrQkgsU0FBU0ksS0FBVCxDQUFsQixDQURZO0FBQUEsYUFBaEI7QUFHSDtBQXJDSTtBQXRHUSxDQUFyQjs7QUErSUFlLE9BQU9DLE9BQVAsR0FBaUJsQyxZQUFqQiIsImZpbGUiOiJsaWIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBhc3NlcnQgPSByZXF1aXJlKCdhc3NlcnQnKVxuY29uc3QgeyBFT0wgfSA9IHJlcXVpcmUoJ29zJylcbmNvbnN0IGxpYiA9IHJlcXVpcmUoJy4uLy4uL3NyYy9saWInKVxuXG5jb25zdCBsaWJUZXN0U3VpdGUgPSB7XG4gICAgY2hlY2tEYXRhT2JqZWN0OiB7XG4gICAgICAgICdzaG91bGQgcmV0dXJuIHRydWUgb24gb2JqZWN0JzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IHtcbiAgICAgICAgICAgICAgICBjb21tZW50OiAnaGVsbG8gd29ybGQnLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXNzZXJ0KGxpYi5jaGVja0RhdGFPYmplY3QoZGF0YSkpXG4gICAgICAgIH0sXG4gICAgICAgICdzaG91bGQgcmV0dXJuIHRydWUgb24gT2JqZWN0JzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IG5ldyBPYmplY3QoJ2ZvbycpXG4gICAgICAgICAgICBhc3NlcnQobGliLmNoZWNrRGF0YU9iamVjdChkYXRhKSlcbiAgICAgICAgfSxcbiAgICAgICAgJ3Nob3VsZCByZXR1cm4gZmFsc2Ugb24gc3RyaW5nJzogKCkgPT4ge1xuICAgICAgICAgICAgYXNzZXJ0KCFsaWIuY2hlY2tEYXRhT2JqZWN0KCdoZWxsbyB3b3JsZCcpKVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIHJldHVybiBmYWxzZSBvbiBib29sZWFuJzogKCkgPT4ge1xuICAgICAgICAgICAgYXNzZXJ0KCFsaWIuY2hlY2tEYXRhT2JqZWN0KHRydWUpKVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIHJldHVybiBmYWxzZSBvbiBhcnJheSc6ICgpID0+IHtcbiAgICAgICAgICAgIGFzc2VydCghbGliLmNoZWNrRGF0YU9iamVjdChbJ2hlbGxvIHdvcmxkJ10pKVxuICAgICAgICB9LFxuICAgIH0sXG4gICAgbWFwRGF0YVRvVGFnQXJyYXk6IHtcbiAgICAgICAgJ3Nob3VsZCByZXR1cm4gYW4gYXJyYXkgd2l0aCB0YWdzJzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IHtcbiAgICAgICAgICAgICAgICB0YWdBOiAndmFsdWVBJyxcbiAgICAgICAgICAgICAgICB0YWdCOiAndmFsdWVCJyxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGxpYi5tYXBEYXRhVG9UYWdBcnJheShkYXRhKVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc1swXSwgJ3RhZ0E9dmFsdWVBJylcbiAgICAgICAgICAgIGFzc2VydC5lcXVhbChyZXNbMV0sICd0YWdCPXZhbHVlQicpXG4gICAgICAgIH0sXG4gICAgICAgICdzaG91bGQgcmV0dXJuIG11bHRpcGxlIGVudHJpZXMgd2hlbiB2YWx1ZSBpcyBhbiBhcnJheSc6ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgICAgICAgJ3RhZysnOiBbICd2YWx1ZUEnLCAndmFsdWVCJyBdLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzID0gbGliLm1hcERhdGFUb1RhZ0FycmF5KGRhdGEpXG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzWzBdLCAndGFnKz12YWx1ZUEnKVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlc1sxXSwgJ3RhZys9dmFsdWVCJylcbiAgICAgICAgfSxcbiAgICAgICAgJ3Nob3VsZCBwdXNoIHZhbHVlcyB0byBleGlzdGluZyBhcnJheSc6ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gWyAnanNvbicgXVxuICAgICAgICAgICAgY29uc3QgZGF0YSA9IHtcbiAgICAgICAgICAgICAgICB0YWdBOiAndmFsdWVBJyxcbiAgICAgICAgICAgICAgICB0YWdCOiAndmFsdWVCJyxcbiAgICAgICAgICAgICAgICAndGFnQysnOiBbICd2YWx1ZUMxJywgJ3ZhbHVlQzInIF0sXG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpYi5tYXBEYXRhVG9UYWdBcnJheShkYXRhLCBhcnJheSlcbiAgICAgICAgICAgIGFzc2VydC5lcXVhbChhcnJheVswXSwgJ2pzb24nKVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGFycmF5WzFdLCAndGFnQT12YWx1ZUEnKVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGFycmF5WzJdLCAndGFnQj12YWx1ZUInKVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGFycmF5WzNdLCAndGFnQys9dmFsdWVDMScpXG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwoYXJyYXlbNF0sICd0YWdDKz12YWx1ZUMyJylcbiAgICAgICAgfSxcbiAgICB9LFxuICAgIGdldEFyZ3M6IHtcbiAgICAgICAgJ3Nob3VsZCByZXR1cm4gZW1wdHkgYXJyYXkgaWYgYXJndW1lbnQgaXMgbm90IGFycmF5JzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzID0gbGliLmdldEFyZ3MoJ25vbi1hcnJheScpXG4gICAgICAgICAgICBhc3NlcnQuZGVlcEVxdWFsKHJlcywgW10pXG4gICAgICAgIH0sXG4gICAgICAgICdzaG91bGQgcmV0dXJuIGVtcHR5IGFycmF5IGlmIGFyZ3VtZW50IGlzIGVtcHR5IGFycmF5JzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzID0gbGliLmdldEFyZ3MoW10pXG4gICAgICAgICAgICBhc3NlcnQuZGVlcEVxdWFsKHJlcywgW10pXG4gICAgICAgIH0sXG4gICAgICAgICdzaG91bGQgbWFwIGFyZ3MgYXJyYXkgdG8gYSBzdHJpbmcnOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhcmdzID0gWydDcmVhdG9yJywgJ0NyZWF0b3JXb3JrVVJMJywgJ09yaWVudGF0aW9uJ11cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGxpYi5nZXRBcmdzKGFyZ3MpXG4gICAgICAgICAgICBjb25zdCBleHBlY3RlZCA9IFsnLUNyZWF0b3InLCAnLUNyZWF0b3JXb3JrVVJMJywgJy1PcmllbnRhdGlvbiddXG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmxlbmd0aCwgZXhwZWN0ZWQubGVuZ3RoKVxuICAgICAgICAgICAgcmVzLmZvckVhY2goKGFyZywgaW5kZXgpID0+XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGFyZywgZXhwZWN0ZWRbaW5kZXhdKVxuICAgICAgICAgICAgKVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIGV4Y2x1ZGUgbm9uLXN0cmluZ3MnOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhcmdzID0gWydDcmVhdG9yJywgJ0NyZWF0b3JXb3JrVVJMJywgJ09yaWVudGF0aW9uJywgZmFsc2UsIE5hTiwgMTAyNF1cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGxpYi5nZXRBcmdzKGFyZ3MpXG4gICAgICAgICAgICBjb25zdCBleHBlY3RlZCA9IFsnLUNyZWF0b3InLCAnLUNyZWF0b3JXb3JrVVJMJywgJy1PcmllbnRhdGlvbiddXG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwocmVzLmxlbmd0aCwgZXhwZWN0ZWQubGVuZ3RoKVxuICAgICAgICAgICAgcmVzLmZvckVhY2goKGFyZywgaW5kZXgpID0+XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGFyZywgZXhwZWN0ZWRbaW5kZXhdKVxuICAgICAgICAgICAgKVxuICAgICAgICB9LFxuICAgICAgICAnc2hvdWxkIHNwbGl0IGFyZ3VtZW50cyc6ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSBbJ0NyZWF0b3InLCAnZXh0IGRuZycsICdvICBtZXRhZGF0YS50eHQnXVxuICAgICAgICAgICAgY29uc3QgcmVzID0gbGliLmdldEFyZ3MoYXJncylcbiAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkID0gWyctQ3JlYXRvcicsICctZXh0JywgJ2RuZycsICctbycsICdtZXRhZGF0YS50eHQnXVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5sZW5ndGgsIGV4cGVjdGVkLmxlbmd0aClcbiAgICAgICAgICAgIHJlcy5mb3JFYWNoKChhcmcsIGluZGV4KSA9PlxuICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChhcmcsIGV4cGVjdGVkW2luZGV4XSlcbiAgICAgICAgICAgIClcbiAgICAgICAgfSxcbiAgICAgICAgJ3Nob3VsZCBub3Qgc3BsaXQgYXJndW1lbnRzIHdpdGggbm9TcGxpdCc6ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSBbJ2tleXdvcmRzKz1rZXl3b3JkIEEnLCAna2V5d29yZHMrPWtleXdvcmQgQicsICdjb21tZW50PWhlbGxvIHdvcmxkJ11cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGxpYi5nZXRBcmdzKGFyZ3MsIHRydWUpXG4gICAgICAgICAgICBjb25zdCBleHBlY3RlZCA9IFsnLWtleXdvcmRzKz1rZXl3b3JkIEEnLCAnLWtleXdvcmRzKz1rZXl3b3JkIEInLCAnLWNvbW1lbnQ9aGVsbG8gd29ybGQnXVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5sZW5ndGgsIGV4cGVjdGVkLmxlbmd0aClcbiAgICAgICAgICAgIHJlcy5mb3JFYWNoKChhcmcsIGluZGV4KSA9PlxuICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChhcmcsIGV4cGVjdGVkW2luZGV4XSlcbiAgICAgICAgICAgIClcbiAgICAgICAgfSxcbiAgICB9LFxuICAgIGV4ZWN1dGU6IHtcbiAgICAgICAgJ3Nob3VsZCB3cml0ZSB0byBwcm9jZXNzIHN0ZGluJzogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVjb3JkcyA9IFtdXG4gICAgICAgICAgICBjb25zdCBwcm9jZXNzID0ge1xuICAgICAgICAgICAgICAgIHN0ZGluOiB7XG4gICAgICAgICAgICAgICAgICAgIHdyaXRlOiByZWNvcmQgPT4gcmVjb3Jkcy5wdXNoKHJlY29yZCksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGNvbW1hbmQgPSAnZmlsZS5qcGcnXG4gICAgICAgICAgICBjb25zdCBjb21tYW5kTnVtYmVyID0gMVxuICAgICAgICAgICAgY29uc3QgYXJncyA9IFsgJ0NyZWF0b3InLCAnZXh0IGRuZycsICdvICBtZXRhZGF0YS50eHQnLCBmYWxzZSwgTmFOIF1cbiAgICAgICAgICAgIGNvbnN0IG5vU3BsaXRBcmdzID0gWyAnY29tbWVudD1oZWxsbyB3b3JsZCcgXVxuICAgICAgICAgICAgbGliLmV4ZWN1dGUocHJvY2VzcywgY29tbWFuZCwgY29tbWFuZE51bWJlciwgYXJncywgbm9TcGxpdEFyZ3MpXG4gICAgICAgICAgICBjb25zdCBleHBlY3RlZCA9IFtcbiAgICAgICAgICAgICAgICAnLWNvbW1lbnQ9aGVsbG8gd29ybGQnLFxuICAgICAgICAgICAgICAgICctQ3JlYXRvcicsXG4gICAgICAgICAgICAgICAgJy1leHQnLFxuICAgICAgICAgICAgICAgICdkbmcnLFxuICAgICAgICAgICAgICAgICctbycsXG4gICAgICAgICAgICAgICAgJ21ldGFkYXRhLnR4dCcsXG4gICAgICAgICAgICAgICAgJy1qc29uJyxcbiAgICAgICAgICAgICAgICAnLXMnLFxuICAgICAgICAgICAgICAgICdmaWxlLmpwZycsXG4gICAgICAgICAgICAgICAgJy1lY2hvMScsXG4gICAgICAgICAgICAgICAgJ3tiZWdpbjF9JyxcbiAgICAgICAgICAgICAgICAnLWVjaG8yJyxcbiAgICAgICAgICAgICAgICAne2JlZ2luMX0nLFxuICAgICAgICAgICAgICAgICctZWNobzQnLFxuICAgICAgICAgICAgICAgICd7cmVhZHkxfScsXG4gICAgICAgICAgICAgICAgJy1leGVjdXRlMScsXG4gICAgICAgICAgICBdLnJlZHVjZSgoYWNjLCBhcmcpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW10uY29uY2F0KGFjYywgW2FyZywgRU9MXSlcbiAgICAgICAgICAgIH0sIFtdKVxuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKHJlY29yZHMubGVuZ3RoLCBleHBlY3RlZC5sZW5ndGgpXG4gICAgICAgICAgICByZWNvcmRzLmZvckVhY2goKGFyZywgaW5kZXgpID0+XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGFyZywgZXhwZWN0ZWRbaW5kZXhdKVxuICAgICAgICAgICAgKVxuICAgICAgICB9LFxuICAgIH0sXG59XG5cbm1vZHVsZS5leHBvcnRzID0gbGliVGVzdFN1aXRlXG4iXX0= \ No newline at end of file diff --git a/dist/test/spec/options.js b/dist/test/spec/options.js new file mode 100644 index 0000000..b5b3268 --- /dev/null +++ b/dist/test/spec/options.js @@ -0,0 +1,53 @@ +'use strict'; + +require('source-map-support/register'); + +var context = require('exiftool-context'); +var assert = require('assert'); +var exiftool = require('../../src/'); +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +var OptionsTestSuite = { + context: context, + 'calls child_process.spawn with specified options': function callsChild_processSpawnWithSpecifiedOptions(ctx) { + ctx.mockSpawn(); + var options = { detached: true }; + + return ctx.createOpen(options).then(function () { + assert.equal(ctx.proc.args.options, options); + }); + }, + 'returns rejected promise when trying to open without readable stderr': function returnsRejectedPromiseWhenTryingToOpenWithoutReadableStderr(ctx) { + var options = { + stdio: ['pipe', 'pipe', 'ignore'] + }; + return ctx.createOpen(options).then(function () { + throw new Error('open should have resulted in error'); + }, function (err) { + assert.equal(err.message, 'Process was not spawned with a readable stderr, check stdio options.'); + }); + }, + 'returns rejected promise when trying to open without readable stdout': function returnsRejectedPromiseWhenTryingToOpenWithoutReadableStdout(ctx) { + var options = { + stdio: ['ignore', 'ignore', 'pipe'] + }; + return ctx.createOpen(options).then(function () { + throw new Error('open should have resulted in error'); + }, function (err) { + assert.equal(err.message, 'Process was not spawned with a readable stdout, check stdio options.'); + }); + }, + 'returns rejected promise when trying to open without stdin': function returnsRejectedPromiseWhenTryingToOpenWithoutStdin(ctx) { + var options = { + stdio: ['ignore', 'pipe', 'pipe'] + }; + return ctx.createOpen(options).then(function () { + throw new Error('open should have resulted in error'); + }, function (err) { + assert.equal(err.message, 'Process was not spawned with a writable stdin, check stdio options.'); + }); + } +}; + +module.exports = OptionsTestSuite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9vcHRpb25zLmpzIl0sIm5hbWVzIjpbImNvbnRleHQiLCJyZXF1aXJlIiwiYXNzZXJ0IiwiZXhpZnRvb2wiLCJnbG9iYWxFeGlmdG9vbENvbnN0cnVjdG9yIiwiRXhpZnRvb2xQcm9jZXNzIiwiT3B0aW9uc1Rlc3RTdWl0ZSIsImN0eCIsIm1vY2tTcGF3biIsIm9wdGlvbnMiLCJkZXRhY2hlZCIsImNyZWF0ZU9wZW4iLCJ0aGVuIiwiZXF1YWwiLCJwcm9jIiwiYXJncyIsInN0ZGlvIiwiRXJyb3IiLCJlcnIiLCJtZXNzYWdlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQU1BLFVBQVVDLFFBQVEsa0JBQVIsQ0FBaEI7QUFDQSxJQUFNQyxTQUFTRCxRQUFRLFFBQVIsQ0FBZjtBQUNBLElBQU1FLFdBQVdGLFFBQVEsWUFBUixDQUFqQjtBQUNBRCxRQUFRSSx5QkFBUixHQUFvQ0QsU0FBU0UsZUFBN0M7O0FBRUEsSUFBTUMsbUJBQW1CO0FBQ3JCTixvQkFEcUI7QUFFckIsd0RBQW9ELHFEQUFDTyxHQUFELEVBQVM7QUFDekRBLFlBQUlDLFNBQUo7QUFDQSxZQUFNQyxVQUFVLEVBQUVDLFVBQVUsSUFBWixFQUFoQjs7QUFFQSxlQUFPSCxJQUFJSSxVQUFKLENBQWVGLE9BQWYsRUFDRkcsSUFERSxDQUNHLFlBQU07QUFDUlYsbUJBQU9XLEtBQVAsQ0FBYU4sSUFBSU8sSUFBSixDQUFTQyxJQUFULENBQWNOLE9BQTNCLEVBQW9DQSxPQUFwQztBQUNILFNBSEUsQ0FBUDtBQUlILEtBVm9CO0FBV3JCLDRFQUF3RSxxRUFBQ0YsR0FBRCxFQUFTO0FBQzdFLFlBQU1FLFVBQVU7QUFDWk8sbUJBQU8sQ0FBQyxNQUFELEVBQVMsTUFBVCxFQUFpQixRQUFqQjtBQURLLFNBQWhCO0FBR0EsZUFBT1QsSUFBSUksVUFBSixDQUFlRixPQUFmLEVBQ0ZHLElBREUsQ0FDRyxZQUFNO0FBQ1Isa0JBQU0sSUFBSUssS0FBSixDQUFVLG9DQUFWLENBQU47QUFDSCxTQUhFLEVBR0EsVUFBQ0MsR0FBRCxFQUFTO0FBQ1JoQixtQkFBT1csS0FBUCxDQUFhSyxJQUFJQyxPQUFqQixFQUEwQixzRUFBMUI7QUFDSCxTQUxFLENBQVA7QUFNSCxLQXJCb0I7QUFzQnJCLDRFQUF3RSxxRUFBQ1osR0FBRCxFQUFTO0FBQzdFLFlBQU1FLFVBQVU7QUFDWk8sbUJBQU8sQ0FBQyxRQUFELEVBQVcsUUFBWCxFQUFxQixNQUFyQjtBQURLLFNBQWhCO0FBR0EsZUFBT1QsSUFBSUksVUFBSixDQUFlRixPQUFmLEVBQ0ZHLElBREUsQ0FDRyxZQUFNO0FBQ1Isa0JBQU0sSUFBSUssS0FBSixDQUFVLG9DQUFWLENBQU47QUFDSCxTQUhFLEVBR0EsVUFBQ0MsR0FBRCxFQUFTO0FBQ1JoQixtQkFBT1csS0FBUCxDQUFhSyxJQUFJQyxPQUFqQixFQUEwQixzRUFBMUI7QUFDSCxTQUxFLENBQVA7QUFNSCxLQWhDb0I7QUFpQ3JCLGtFQUE4RCw0REFBQ1osR0FBRCxFQUFTO0FBQ25FLFlBQU1FLFVBQVU7QUFDWk8sbUJBQU8sQ0FBQyxRQUFELEVBQVcsTUFBWCxFQUFtQixNQUFuQjtBQURLLFNBQWhCO0FBR0EsZUFBT1QsSUFBSUksVUFBSixDQUFlRixPQUFmLEVBQ0ZHLElBREUsQ0FDRyxZQUFNO0FBQ1Isa0JBQU0sSUFBSUssS0FBSixDQUFVLG9DQUFWLENBQU47QUFDSCxTQUhFLEVBR0EsVUFBQ0MsR0FBRCxFQUFTO0FBQ1JoQixtQkFBT1csS0FBUCxDQUFhSyxJQUFJQyxPQUFqQixFQUEwQixxRUFBMUI7QUFDSCxTQUxFLENBQVA7QUFNSDtBQTNDb0IsQ0FBekI7O0FBOENBQyxPQUFPQyxPQUFQLEdBQWlCZixnQkFBakIiLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGNvbnRleHQgPSByZXF1aXJlKCdleGlmdG9vbC1jb250ZXh0JylcbmNvbnN0IGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpXG5jb25zdCBleGlmdG9vbCA9IHJlcXVpcmUoJy4uLy4uL3NyYy8nKVxuY29udGV4dC5nbG9iYWxFeGlmdG9vbENvbnN0cnVjdG9yID0gZXhpZnRvb2wuRXhpZnRvb2xQcm9jZXNzXG5cbmNvbnN0IE9wdGlvbnNUZXN0U3VpdGUgPSB7XG4gICAgY29udGV4dCxcbiAgICAnY2FsbHMgY2hpbGRfcHJvY2Vzcy5zcGF3biB3aXRoIHNwZWNpZmllZCBvcHRpb25zJzogKGN0eCkgPT4ge1xuICAgICAgICBjdHgubW9ja1NwYXduKClcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHsgZGV0YWNoZWQ6IHRydWUgfVxuXG4gICAgICAgIHJldHVybiBjdHguY3JlYXRlT3BlbihvcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChjdHgucHJvYy5hcmdzLm9wdGlvbnMsIG9wdGlvbnMpXG4gICAgICAgICAgICB9KVxuICAgIH0sXG4gICAgJ3JldHVybnMgcmVqZWN0ZWQgcHJvbWlzZSB3aGVuIHRyeWluZyB0byBvcGVuIHdpdGhvdXQgcmVhZGFibGUgc3RkZXJyJzogKGN0eCkgPT4ge1xuICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgc3RkaW86IFsncGlwZScsICdwaXBlJywgJ2lnbm9yZSddLFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjdHguY3JlYXRlT3BlbihvcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignb3BlbiBzaG91bGQgaGF2ZSByZXN1bHRlZCBpbiBlcnJvcicpXG4gICAgICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnUHJvY2VzcyB3YXMgbm90IHNwYXduZWQgd2l0aCBhIHJlYWRhYmxlIHN0ZGVyciwgY2hlY2sgc3RkaW8gb3B0aW9ucy4nKVxuICAgICAgICAgICAgfSlcbiAgICB9LFxuICAgICdyZXR1cm5zIHJlamVjdGVkIHByb21pc2Ugd2hlbiB0cnlpbmcgdG8gb3BlbiB3aXRob3V0IHJlYWRhYmxlIHN0ZG91dCc6IChjdHgpID0+IHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIHN0ZGlvOiBbJ2lnbm9yZScsICdpZ25vcmUnLCAncGlwZSddLFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjdHguY3JlYXRlT3BlbihvcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignb3BlbiBzaG91bGQgaGF2ZSByZXN1bHRlZCBpbiBlcnJvcicpXG4gICAgICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnUHJvY2VzcyB3YXMgbm90IHNwYXduZWQgd2l0aCBhIHJlYWRhYmxlIHN0ZG91dCwgY2hlY2sgc3RkaW8gb3B0aW9ucy4nKVxuICAgICAgICAgICAgfSlcbiAgICB9LFxuICAgICdyZXR1cm5zIHJlamVjdGVkIHByb21pc2Ugd2hlbiB0cnlpbmcgdG8gb3BlbiB3aXRob3V0IHN0ZGluJzogKGN0eCkgPT4ge1xuICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgc3RkaW86IFsnaWdub3JlJywgJ3BpcGUnLCAncGlwZSddLFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjdHguY3JlYXRlT3BlbihvcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignb3BlbiBzaG91bGQgaGF2ZSByZXN1bHRlZCBpbiBlcnJvcicpXG4gICAgICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnUHJvY2VzcyB3YXMgbm90IHNwYXduZWQgd2l0aCBhIHdyaXRhYmxlIHN0ZGluLCBjaGVjayBzdGRpbyBvcHRpb25zLicpXG4gICAgICAgICAgICB9KVxuICAgIH0sXG59XG5cbm1vZHVsZS5leHBvcnRzID0gT3B0aW9uc1Rlc3RTdWl0ZVxuIl19 \ No newline at end of file diff --git a/dist/test/spec/read-from-stream.js b/dist/test/spec/read-from-stream.js new file mode 100644 index 0000000..893277a --- /dev/null +++ b/dist/test/spec/read-from-stream.js @@ -0,0 +1,158 @@ +'use strict'; + +require('source-map-support/register'); + +var assert = require('assert'); +var context = require('exiftool-context'); +var fs = require('fs'); +var makepromise = require('makepromise'); +var exiftool = require('../../src/'); +var executeWithRs = require('../../src/execute-with-rs'); + +context.globalExiftoolConstructor = exiftool.ExiftoolProcess; + +var readFromStreamTestSuite = { + context: context, + 'should read metadata from a read stream': function shouldReadMetadataFromAReadStream(ctx) { + ctx.create(); + return ctx.ep.open().then(function () { + var rs = fs.createReadStream(ctx.jpegFile); + return ctx.ep.readMetadata(rs); + }).then(function (res) { + assert(Array.isArray(res.data)); + assert(res.data.length > 0); + return ctx.assertJpegMetadata(res.data[0]); + }); + } +}; + +function assertDoesNotExist(file) { + return makepromise(fs.stat, [file]).then(function () { + throw new Error('should have thrown ENOENT error'); + }, function (err) { + if (!/ENOENT/.test(err.message)) { + throw err; + } + }); +} +function assertExists(file) { + return makepromise(fs.stat, [file]).then(function () {}); +} + +var readFromRsTestSuite = { + context: context, + 'should reject if non-readable passed': function shouldRejectIfNonReadablePassed() { + return executeWithRs('string', null, function () {}).then(function () { + throw new Error('should have thrown an error'); + }, function (err) { + assert.equal(err.message, 'Please pass a readable stream'); + }); + }, + 'should reject if executeCommand is not a function': function shouldRejectIfExecuteCommandIsNotAFunction(ctx) { + var rs = fs.createReadStream(ctx.jpegFile); + return executeWithRs(rs).then(function () { + throw new Error('should have thrown an error'); + }, function (err) { + assert.equal(err.message, 'executeCommand must be a function'); + }); + }, + 'should read from a rs': function shouldReadFromARs(ctx) { + ctx.create(); + return ctx.ep.open().then(function () { + var rs = fs.createReadStream(ctx.jpegFile); + var executeCommand = ctx.ep._executeCommand.bind(ctx.ep); + return executeWithRs(rs, null, executeCommand); + }).then(function (res) { + assert(Array.isArray(res.data)); + assert(res.data.length > 0); + return ctx.assertJpegMetadata(res.data[0]); + }); + }, + 'should return execute function result': function shouldReturnExecuteFunctionResult(ctx) { + var rs = fs.createReadStream(ctx.jpegFile); + var result = [{ some: 'metadata' }, null]; + var executeCommand = function executeCommand() { + return result; + }; + return executeWithRs(rs, null, executeCommand).then(function (res) { + assert.strictEqual(res, result); + }); + }, + 'should call executeCommand with an existing file': function shouldCallExecuteCommandWithAnExistingFile(ctx) { + var rs = fs.createReadStream(ctx.jpegFile); + var tempFile = void 0; + var fileCreated = false; + var error = void 0; + var executeCommand = function executeCommand(_tempFile) { + tempFile = _tempFile; + return assertExists(tempFile).then(function () { + fileCreated = true; + }, function (_error) { + error = _error; + }); + }; + return executeWithRs(rs, null, executeCommand).then(function () { + assert(fileCreated); + assert.equal(error, undefined); + }); + }, + 'should call executeCommand with args': function shouldCallExecuteCommandWithArgs(ctx) { + var rs = fs.createReadStream(ctx.jpegFile); + var testArgs = ['some-arg=value']; + var args = void 0; + var executeCommand = function executeCommand(_, _args) { + args = _args; + }; + return executeWithRs(rs, testArgs, executeCommand).then(function () { + assert.strictEqual(args, testArgs); + }); + }, + 'should remove temp file': function shouldRemoveTempFile(ctx) { + var rs = fs.createReadStream(ctx.jpegFile); + var tempFile = void 0; + var executeCommand = function executeCommand(_tempFile) { + tempFile = _tempFile; + }; + return executeWithRs(rs, null, executeCommand).then(function () { + return assertDoesNotExist(tempFile); + }); + }, + 'should reject with execution error': function shouldRejectWithExecutionError(ctx) { + ctx.create(); + var error = new Error('error during execution'); + return ctx.ep.open().then(function () { + var rs = fs.createReadStream(ctx.jpegFile); + var executeCommand = function executeCommand() { + throw error; + }; + return executeWithRs(rs, null, executeCommand); + }).then(function () { + throw new Error('should have thrown execution error'); + }, function (err) { + assert.strictEqual(err, error); + }); + }, + 'should remove temp file if executeCommand failed': function shouldRemoveTempFileIfExecuteCommandFailed(ctx) { + ctx.create(); + var error = new Error('error during execution'); + var tempFile = void 0; + return ctx.ep.open().then(function () { + var rs = fs.createReadStream(ctx.jpegFile); + var executeCommand = function executeCommand(_tempFile) { + tempFile = _tempFile; + throw error; + }; + return executeWithRs(rs, null, executeCommand); + }).then(function () { + throw new Error('should have thrown execution error'); + }, function () { + return assertDoesNotExist(tempFile); + }); + } +}; + +module.exports = { + readFromStreamTestSuite: readFromStreamTestSuite, + readFromRsTestSuite: readFromRsTestSuite +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Qvc3BlYy9yZWFkLWZyb20tc3RyZWFtLmpzIl0sIm5hbWVzIjpbImFzc2VydCIsInJlcXVpcmUiLCJjb250ZXh0IiwiZnMiLCJtYWtlcHJvbWlzZSIsImV4aWZ0b29sIiwiZXhlY3V0ZVdpdGhScyIsImdsb2JhbEV4aWZ0b29sQ29uc3RydWN0b3IiLCJFeGlmdG9vbFByb2Nlc3MiLCJyZWFkRnJvbVN0cmVhbVRlc3RTdWl0ZSIsImN0eCIsImNyZWF0ZSIsImVwIiwib3BlbiIsInRoZW4iLCJycyIsImNyZWF0ZVJlYWRTdHJlYW0iLCJqcGVnRmlsZSIsInJlYWRNZXRhZGF0YSIsInJlcyIsIkFycmF5IiwiaXNBcnJheSIsImRhdGEiLCJsZW5ndGgiLCJhc3NlcnRKcGVnTWV0YWRhdGEiLCJhc3NlcnREb2VzTm90RXhpc3QiLCJmaWxlIiwic3RhdCIsIkVycm9yIiwiZXJyIiwidGVzdCIsIm1lc3NhZ2UiLCJhc3NlcnRFeGlzdHMiLCJyZWFkRnJvbVJzVGVzdFN1aXRlIiwiZXF1YWwiLCJleGVjdXRlQ29tbWFuZCIsIl9leGVjdXRlQ29tbWFuZCIsImJpbmQiLCJyZXN1bHQiLCJzb21lIiwic3RyaWN0RXF1YWwiLCJ0ZW1wRmlsZSIsImZpbGVDcmVhdGVkIiwiZXJyb3IiLCJfdGVtcEZpbGUiLCJfZXJyb3IiLCJ1bmRlZmluZWQiLCJ0ZXN0QXJncyIsImFyZ3MiLCJfIiwiX2FyZ3MiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOzs7O0FBQUEsSUFBTUEsU0FBU0MsUUFBUSxRQUFSLENBQWY7QUFDQSxJQUFNQyxVQUFVRCxRQUFRLGtCQUFSLENBQWhCO0FBQ0EsSUFBTUUsS0FBS0YsUUFBUSxJQUFSLENBQVg7QUFDQSxJQUFNRyxjQUFjSCxRQUFRLGFBQVIsQ0FBcEI7QUFDQSxJQUFNSSxXQUFXSixRQUFRLFlBQVIsQ0FBakI7QUFDQSxJQUFNSyxnQkFBZ0JMLFFBQVEsMkJBQVIsQ0FBdEI7O0FBRUFDLFFBQVFLLHlCQUFS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T0gsbUJBQW1CZ0IsUUFBbkIsQ0FBUDtBQUNILFNBYkUsQ0FBUDtBQWNIO0FBMUh1QixDQUE1Qjs7QUE2SEFVLE9BQU9DLE9BQVAsR0FBaUI7QUFDYjNDLG9EQURhO0FBRWJ3QjtBQUZhLENBQWpCIiwiZmlsZSI6InJlYWQtZnJvbS1zdHJlYW0uanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBhc3NlcnQgPSByZXF1aXJlKCdhc3NlcnQnKVxuY29uc3QgY29udGV4dCA9IHJlcXVpcmUoJ2V4aWZ0b29sLWNvbnRleHQnKVxuY29uc3QgZnMgPSByZXF1aXJlKCdmcycpXG5jb25zdCBtYWtlcHJvbWlzZSA9IHJlcXVpcmUoJ21ha2Vwcm9taXNlJylcbmNvbnN0IGV4aWZ0b29sID0gcmVxdWlyZSgnLi4vLi4vc3JjLycpXG5jb25zdCBleGVjdXRlV2l0aFJzID0gcmVxdWlyZSgnLi4vLi4vc3JjL2V4ZWN1dGUtd2l0aC1ycycpXG5cbmNvbnRleHQuZ2xvYmFsRXhpZnRvb2xDb25zdHJ1Y3RvciA9IGV4aWZ0b29sLkV4aWZ0b29sUHJvY2Vzc1xuXG5jb25zdCByZWFkRnJvbVN0cmVhbVRlc3RTdWl0ZSA9IHtcbiAgICBjb250ZXh0LFxuICAgICdzaG91bGQgcmVhZCBtZXRhZGF0YSBmcm9tIGEgcmVhZCBzdHJlYW0nOiAoY3R4KSA9PiB7XG4gICAgICAgIGN0eC5jcmVhdGUoKVxuICAgICAgICByZXR1cm4gY3R4LmVwLm9wZW4oKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJzID0gZnMuY3JlYXRlUmVhZFN0cmVhbShjdHguanBlZ0ZpbGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGN0eC5lcC5yZWFkTWV0YWRhdGEocnMpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydCAoQXJyYXkuaXNBcnJheShyZXMuZGF0YSkpXG4gICAgICAgICAgICAgICAgYXNzZXJ0KHJlcy5kYXRhLmxlbmd0aCA+IDApXG4gICAgICAgICAgICAgICAgcmV0dXJuIGN0eC5hc3NlcnRKcGVnTWV0YWRhdGEocmVzLmRhdGFbMF0pXG4gICAgICAgICAgICB9KVxuICAgIH0sXG59XG5cbmZ1bmN0aW9uIGFzc2VydERvZXNOb3RFeGlzdChmaWxlKSB7XG4gICAgcmV0dXJuIG1ha2Vwcm9taXNlKGZzLnN0YXQsIFtmaWxlXSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzaG91bGQgaGF2ZSB0aHJvd24gRU5PRU5UIGVycm9yJylcbiAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgaWYgKCEvRU5PRU5ULy50ZXN0KGVyci5tZXNzYWdlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IGVyclxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxufVxuZnVuY3Rpb24gYXNzZXJ0RXhpc3RzKGZpbGUpIHtcbiAgICByZXR1cm4gbWFrZXByb21pc2UoZnMuc3RhdCwgW2ZpbGVdKVxuICAgICAgICAudGhlbigoKSA9PiB7fSlcbn1cblxuY29uc3QgcmVhZEZyb21Sc1Rlc3RTdWl0ZSA9IHtcbiAgICBjb250ZXh0LFxuICAgICdzaG91bGQgcmVqZWN0IGlmIG5vbi1yZWFkYWJsZSBwYXNzZWQnOiAoKSA9PiB7XG4gICAgICAgIHJldHVybiBleGVjdXRlV2l0aFJzKCdzdHJpbmcnLCBudWxsLCAoKSA9PiB7fSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Nob3VsZCBoYXZlIHRocm93biBhbiBlcnJvcicpXG4gICAgICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnUGxlYXNlIHBhc3MgYSByZWFkYWJsZSBzdHJlYW0nKVxuICAgICAgICAgICAgfSlcbiAgICB9LFxuICAgICdzaG91bGQgcmVqZWN0IGlmIGV4ZWN1dGVDb21tYW5kIGlzIG5vdCBhIGZ1bmN0aW9uJzogKGN0eCkgPT4ge1xuICAgICAgICBjb25zdCBycyA9IGZzLmNyZWF0ZVJlYWRTdHJlYW0oY3R4LmpwZWdGaWxlKVxuICAgICAgICByZXR1cm4gZXhlY3V0ZVdpdGhScyhycylcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Nob3VsZCBoYXZlIHRocm93biBhbiBlcnJvcicpXG4gICAgICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGVyci5tZXNzYWdlLCAnZXhlY3V0ZUNvbW1hbmQgbXVzdCBiZSBhIGZ1bmN0aW9uJylcbiAgICAgICAgICAgIH0pXG4gICAgfSxcbiAgICAnc2hvdWxkIHJlYWQgZnJvbSBhIHJzJzogKGN0eCkgPT4ge1xuICAgICAgICBjdHguY3JlYXRlKClcbiAgICAgICAgcmV0dXJuIGN0eC5lcC5vcGVuKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBycyA9IGZzLmNyZWF0ZVJlYWRTdHJlYW0oY3R4LmpwZWdGaWxlKVxuICAgICAgICAgICAgICAgIGNvbnN0IGV4ZWN1dGVDb21tYW5kID0gY3R4LmVwLl9leGVjdXRlQ29tbWFuZC5iaW5kKGN0eC5lcClcbiAgICAgICAgICAgICAgICByZXR1cm4gZXhlY3V0ZVdpdGhScyhycywgbnVsbCwgZXhlY3V0ZUNvbW1hbmQpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydCAoQXJyYXkuaXNBcnJheShyZXMuZGF0YSkpXG4gICAgICAgICAgICAgICAgYXNzZXJ0KHJlcy5kYXRhLmxlbmd0aCA+IDApXG4gICAgICAgICAgICAgICAgcmV0dXJuIGN0eC5hc3NlcnRKcGVnTWV0YWRhdGEocmVzLmRhdGFbMF0pXG4gICAgICAgICAgICB9KVxuICAgIH0sXG4gICAgJ3Nob3VsZCByZXR1cm4gZXhlY3V0ZSBmdW5jdGlvbiByZXN1bHQnOiAoY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IHJzID0gZnMuY3JlYXRlUmVhZFN0cmVhbShjdHguanBlZ0ZpbGUpXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFt7IHNvbWU6ICdtZXRhZGF0YScgfSwgbnVsbF1cbiAgICAgICAgY29uc3QgZXhlY3V0ZUNvbW1hbmQgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVXaXRoUnMocnMsIG51bGwsIGV4ZWN1dGVDb21tYW5kKVxuICAgICAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXMsIHJlc3VsdClcbiAgICAgICAgICAgIH0pXG4gICAgfSxcbiAgICAnc2hvdWxkIGNhbGwgZXhlY3V0ZUNvbW1hbmQgd2l0aCBhbiBleGlzdGluZyBmaWxlJzogKGN0eCkgPT4ge1xuICAgICAgICBjb25zdCBycyA9IGZzLmNyZWF0ZVJlYWRTdHJlYW0oY3R4LmpwZWdGaWxlKVxuICAgICAgICBsZXQgdGVtcEZpbGVcbiAgICAgICAgbGV0IGZpbGVDcmVhdGVkID0gZmFsc2VcbiAgICAgICAgbGV0IGVycm9yXG4gICAgICAgIGNvbnN0IGV4ZWN1dGVDb21tYW5kID0gKF90ZW1wRmlsZSkgPT4ge1xuICAgICAgICAgICAgdGVtcEZpbGUgPSBfdGVtcEZpbGVcbiAgICAgICAgICAgIHJldHVybiBhc3NlcnRFeGlzdHModGVtcEZpbGUpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBmaWxlQ3JlYXRlZCA9IHRydWVcbiAgICAgICAgICAgICAgICB9LCAoX2Vycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gX2Vycm9yXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXhlY3V0ZVdpdGhScyhycywgbnVsbCwgZXhlY3V0ZUNvbW1hbmQpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KGZpbGVDcmVhdGVkKVxuICAgICAgICAgICAgICAgIGFzc2VydC5lcXVhbChlcnJvciwgdW5kZWZpbmVkKVxuICAgICAgICAgICAgfSlcbiAgICB9LFxuICAgICdzaG91bGQgY2FsbCBleGVjdXRlQ29tbWFuZCB3aXRoIGFyZ3MnOiAoY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IHJzID0gZnMuY3JlYXRlUmVhZFN0cmVhbShjdHguanBlZ0ZpbGUpXG4gICAgICAgIGNvbnN0IHRlc3RBcmdzID0gWydzb21lLWFyZz12YWx1ZSddXG4gICAgICAgIGxldCBhcmdzXG4gICAgICAgIGNvbnN0IGV4ZWN1dGVDb21tYW5kID0gKF8sIF9hcmdzKSA9PiB7XG4gICAgICAgICAgICBhcmdzID0gX2FyZ3NcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXhlY3V0ZVdpdGhScyhycywgdGVzdEFyZ3MsIGV4ZWN1dGVDb21tYW5kKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhcmdzLCB0ZXN0QXJncylcbiAgICAgICAgICAgIH0pXG4gICAgfSxcbiAgICAnc2hvdWxkIHJlbW92ZSB0ZW1wIGZpbGUnOiAoY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IHJzID0gZnMuY3JlYXRlUmVhZFN0cmVhbShjdHguanBlZ0ZpbGUpXG4gICAgICAgIGxldCB0ZW1wRmlsZVxuICAgICAgICBjb25zdCBleGVjdXRlQ29tbWFuZCA9IChfdGVtcEZpbGUpID0+IHtcbiAgICAgICAgICAgIHRlbXBGaWxlID0gX3RlbXBGaWxlXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVXaXRoUnMocnMsIG51bGwsIGV4ZWN1dGVDb21tYW5kKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBhc3NlcnREb2VzTm90RXhpc3QodGVtcEZpbGUpXG4gICAgICAgICAgICB9KVxuICAgIH0sXG4gICAgJ3Nob3VsZCByZWplY3Qgd2l0aCBleGVjdXRpb24gZXJyb3InOiAoY3R4KSA9PiB7XG4gICAgICAgIGN0eC5jcmVhdGUoKVxuICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcignZXJyb3IgZHVyaW5nIGV4ZWN1dGlvbicpXG4gICAgICAgIHJldHVybiBjdHguZXAub3BlbigpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcnMgPSBmcy5jcmVhdGVSZWFkU3RyZWFtKGN0eC5qcGVnRmlsZSlcbiAgICAgICAgICAgICAgICBjb25zdCBleGVjdXRlQ29tbWFuZCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3JcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV4ZWN1dGVXaXRoUnMocnMsIG51bGwsIGV4ZWN1dGVDb21tYW5kKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Nob3VsZCBoYXZlIHRocm93biBleGVjdXRpb24gZXJyb3InKVxuICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlcnIsIGVycm9yKVxuICAgICAgICAgICAgfSlcbiAgICB9LFxuICAgICdzaG91bGQgcmVtb3ZlIHRlbXAgZmlsZSBpZiBleGVjdXRlQ29tbWFuZCBmYWlsZWQnOiAoY3R4KSA9PiB7XG4gICAgICAgIGN0eC5jcmVhdGUoKVxuICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcignZXJyb3IgZHVyaW5nIGV4ZWN1dGlvbicpXG4gICAgICAgIGxldCB0ZW1wRmlsZVxuICAgICAgICByZXR1cm4gY3R4LmVwLm9wZW4oKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJzID0gZnMuY3JlYXRlUmVhZFN0cmVhbShjdHguanBlZ0ZpbGUpXG4gICAgICAgICAgICAgICAgY29uc3QgZXhlY3V0ZUNvbW1hbmQgPSAoX3RlbXBGaWxlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBGaWxlID0gX3RlbXBGaWxlXG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBleGVjdXRlV2l0aFJzKHJzLCBudWxsLCBleGVjdXRlQ29tbWFuZClcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzaG91bGQgaGF2ZSB0aHJvd24gZXhlY3V0aW9uIGVycm9yJylcbiAgICAgICAgICAgIH0sICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXNzZXJ0RG9lc05vdEV4aXN0KHRlbXBGaWxlKVxuICAgICAgICAgICAgfSlcbiAgICB9LFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICByZWFkRnJvbVN0cmVhbVRlc3RTdWl0ZSxcbiAgICByZWFkRnJvbVJzVGVzdFN1aXRlLFxufVxuIl19 \ No newline at end of file diff --git a/examples/.eslintrc b/examples/.eslintrc index a85fe17..4fe6cc5 100644 --- a/examples/.eslintrc +++ b/examples/.eslintrc @@ -1,5 +1,6 @@ { "rules": { - "no-console": "off" + "no-console": "off", + "prefer-destructuring": "off" } } diff --git a/package.json b/package.json index bf8b8f9..4b47351 100644 --- a/package.json +++ b/package.json @@ -2,16 +2,23 @@ "name": "node-exiftool", "version": "2.3.0", "description": "A Node.js interface to exiftool command-line application.", - "main": "src/index.js", + "main": "dist/src/index.js", "files": [ + "dist/", "src/" ], "scripts": { "test": "cross-env ZOROASTER_TIMEOUT=10000 zoroaster test/spec", + "test-build": "cross-env ZOROASTER_TIMEOUT=10000 zoroaster dist/test/spec", "test-watch": "zoroaster test/spec --watch", "bench": "node benchmark/run", + "build-src": "babel src --out-dir dist/src", + "build-test": "babel test --out-dir dist/test", + "build": "run-s build-src build-test", + "build-and-test": "run-s build test-build", "callback-example": "LOCAL=1 node examples/callback examples/28.jpg", - "write-example": "node examples/write_metadata/index" + "write-example": "node examples/write_metadata/index", + "lint": "eslint ." }, "repository": { "type": "git", @@ -30,15 +37,23 @@ }, "homepage": "https://github.com/Sobesednik/node-exiftool#readme", "devDependencies": { + "babel-cli": "6.26.0", + "babel-plugin-source-map-support": "1.0.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-preset-es2015": "6.24.1", "cross-env": "5.0.0", + "eslint": "4.9.0", "exiftool-context": "1.4.0", "makepromise": "1.0.0", + "npm-run-all": "4.1.1", "ps-node": "0.1.6", "zoroaster": "0.4.6" }, "dependencies": { + "erotic": "0.1.0", "is-stream": "1.1.0", "restream": "1.2.0", + "source-map-support": "0.5.0", "wrote": "0.6.1" } } diff --git a/src/begin-ready.js b/src/begin-ready.js index fd3e420..b36f02e 100644 --- a/src/begin-ready.js +++ b/src/begin-ready.js @@ -1,7 +1,4 @@ -'use strict' - -const Transform = require('stream').Transform -const Writable = require('stream').Writable +const { Transform, Writable } = require('stream') const restream = require('restream') const BEGIN_READY_RE = /{begin(\d+)}([\s\S]*){ready\1}/g diff --git a/src/execute-with-rs.js b/src/execute-with-rs.js index 5d283b4..f409ee7 100644 --- a/src/execute-with-rs.js +++ b/src/execute-with-rs.js @@ -1,10 +1,9 @@ -'use strict' const wrote = require('wrote') -const Readable = require('stream').Readable +const { Readable } = require('stream') /** * Create temp file for rs, execute exiftool command, then erase file - * @param {Readable} rs a read strem + * @param {Readable} rs a read stream * @param {string[]} args Arguments * @param {function} executeCommand function which is responsible for executing the command */ diff --git a/src/index.js b/src/index.js index 48471b0..0edda02 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,3 @@ -'use strict' - const EventEmitter = require('events') const lib = require('./lib') const beginReady = require('./begin-ready') @@ -55,7 +53,7 @@ class ExiftoolProcess extends EventEmitter { * @returns {Promise.} A promise to spawn exiftool in stay_open * mode, resolved with pid. */ - open(encoding, options) { + async open(encoding, options) { let _encoding = encoding let _options = options // if encoding is not a string and options are not given, treat it as options @@ -65,45 +63,43 @@ class ExiftoolProcess extends EventEmitter { } this._assignEncoding(_encoding) if (this._open) { - return Promise.reject(new Error('Exiftool process is already open')) + throw new Error('Exiftool process is already open') + } + const exiftoolProcess = await lib.spawn(this._bin, _options) + //console.log(`Started exiftool process %s`, process.pid); + this.emit(events.OPEN, exiftoolProcess.pid) + this._process = exiftoolProcess + + this._process.on('exit', this._exitListener.bind(this)) + if (!lib.isReadable(this._process.stdout)) { + lib.killProcess(this._process) + throw new Error('Process was not spawned with a readable stdout, check stdio options.') + } + if (!lib.isWritable(this._process.stdin)) { + lib.killProcess(this._process) + throw new Error('Process was not spawned with a writable stdin, check stdio options.') } - return lib.spawn(this._bin, _options) - .then((exiftoolProcess) => { - //console.log(`Started exiftool process %s`, process.pid); - this.emit(events.OPEN, exiftoolProcess.pid) - this._process = exiftoolProcess - - this._process.on('exit', this._exitListener.bind(this)) - if (!lib.isReadable(this._process.stdout)) { - lib.killProcess(this._process) - throw new Error('Process was not spawned with a readable stdout, check stdio options.') - } - if (!lib.isWritable(this._process.stdin)) { - lib.killProcess(this._process) - throw new Error('Process was not spawned with a writable stdin, check stdio options.') - } - - // if process was spawned, stderr is readable (see lib/spawn) - - this._process.stdout.setEncoding(this._encoding) - this._process.stderr.setEncoding(this._encoding) - - // resolve-write streams - this._stdoutResolveWs = beginReady.setupResolveWriteStreamPipe(this._process.stdout) - this._stderrResolveWs = beginReady.setupResolveWriteStreamPipe(this._process.stderr) - - // handle errors so that Node does not crash - this._stdoutResolveWs.on('error', console.error) // eslint-disable-line no-console - this._stderrResolveWs.on('error', console.error) // eslint-disable-line no-console - - // debug - // exiftoolProcess.stdout.pipe(process.stdout) - // exiftoolProcess.stderr.pipe(process.stderr) - - this._open = true - - return exiftoolProcess.pid - }) + + // if process was spawned, stderr is readable (see lib/spawn) + + this._process.stdout.setEncoding(this._encoding) + this._process.stderr.setEncoding(this._encoding) + + // resolve-write streams + this._stdoutResolveWs = beginReady.setupResolveWriteStreamPipe(this._process.stdout) + this._stderrResolveWs = beginReady.setupResolveWriteStreamPipe(this._process.stderr) + + // handle errors so that Node does not crash + this._stdoutResolveWs.on('error', console.error) // eslint-disable-line no-console + this._stderrResolveWs.on('error', console.error) // eslint-disable-line no-console + + // debug + // exiftoolProcess.stdout.pipe(process.stdout) + // exiftoolProcess.stderr.pipe(process.stderr) + + this._open = true + + return exiftoolProcess.pid } _exitListener() { @@ -120,13 +116,13 @@ class ExiftoolProcess extends EventEmitter { return this._open } - _executeCommand(command, args, argsNoSplit, debug) { + async _executeCommand(command, args, argsNoSplit, debug) { //test this! if (!this._open) { - return Promise.reject(new Error('exiftool is not open')) + throw new Error('exiftool is not open') } if (this._process.signalCode === 'SIGTERM') { - return Promise.reject(new Error('Could not connect to the exiftool process')) + throw new Error('Could not connect to the exiftool process') } const proc = debug === true ? process : this._process @@ -159,12 +155,12 @@ class ExiftoolProcess extends EventEmitter { * @returns {Promise.<{{data, error}}>} A promise to write metadata, * resolved with data from stdout and stderr. */ - writeMetadata(file, data, args, debug) { + async writeMetadata(file, data, args, debug) { if (!lib.isString(file)) { throw new Error('File must be a string') } if (!lib.checkDataObject(data)) { - return Promise.reject(new Error('Data argument is not an object')) + throw new Error('Data argument is not an object') } const writeArgs = lib.mapDataToTagArray(data) diff --git a/src/lib.js b/src/lib.js index f21c113..3e7aee4 100644 --- a/src/lib.js +++ b/src/lib.js @@ -1,8 +1,7 @@ -'use strict' - const cp = require('child_process') -const EOL = require('os').EOL +const { EOL } = require('os') const isStream = require('is-stream') +const erotic = require('erotic') function writeStdIn(proc, data, encoding) { // console.log('write stdin', data) @@ -11,17 +10,18 @@ function writeStdIn(proc, data, encoding) { } function close(proc) { + const er = erotic() let errHandler return new Promise((resolve, reject) => { - errHandler = (err) => { - reject(new Error(`Could not write to stdin: ${err.message}`)) + errHandler = ({ message }) => { + const err = er(message) + reject(err) } proc.once('close', resolve) proc.stdin.once('error', errHandler) writeStdIn(proc, '-stay_open') writeStdIn(proc, 'false') - }) - .then(() => { + }).then(() => { proc.stdin.removeListener('error', errHandler) }) } @@ -46,7 +46,7 @@ function getArgs(args, noSplit) { .map(arg => `-${arg}`) .reduce((acc, arg) => [].concat(acc, noSplit ? [arg] : arg.split(/\s+/)) - , []) + , []) } /** @@ -80,6 +80,7 @@ function execute(proc, command, commandNumber, args, noSplitArgs, encoding) { ] ) if (process.env.DEBUG) { + // eslint-disable-next-line no-console console.log(JSON.stringify(allArgs, null, 2)) } allArgs.forEach(arg => writeStdIn(proc, arg, encoding)) diff --git a/test/fixtures/detached.js b/test/fixtures/detached.js index 37453c5..459d423 100644 --- a/test/fixtures/detached.js +++ b/test/fixtures/detached.js @@ -1,21 +1,21 @@ -const ExiftoolContext = require('exiftool-context') -const exiftool = require('../../.') - -const bin = ExiftoolContext.exiftoolBin -const ep = new exiftool.ExiftoolProcess(bin) +const { exiftoolBin: bin } = require('exiftool-context') +const exiftool = require('../../src/') if (typeof process.send !== 'function') { throw new Error('This module should be spawned with an IPC channel.') } -const EXIFTOOL_DETACHED = process.env.EXIFTOOL_DETACHED === 'true' +const { EXIFTOOL_DETACHED } = process.env + +const detached = EXIFTOOL_DETACHED === 'true'; -ep - .open({ detached: EXIFTOOL_DETACHED }) - .then((pid) => { +(async () => { + try { + const ep = new exiftool.ExiftoolProcess(bin) + const pid = await ep.open({ detached }) process.send(pid) - }) - .catch((err) => { + } catch (err) { console.log(err) // eslint-disable-line no-console process.exit(1) - }) + } +})() diff --git a/test/spec/begin-ready.js b/test/spec/begin-ready.js index ce1e376..1a0fb4b 100644 --- a/test/spec/begin-ready.js +++ b/test/spec/begin-ready.js @@ -1,11 +1,10 @@ const assert = require('assert') -const Readable = require('stream').Readable -const Writable = require('stream').Writable -const Transform = require('stream').Transform -const beginReady = require('../../src/begin-ready') -const createBeginReadyMatchTransformStream = beginReady.createBeginReadyMatchTransformStream -const createResolverWriteStream = beginReady.createResolverWriteStream -const setupResolveWriteStreamPipe = beginReady.setupResolveWriteStreamPipe +const { Readable, Writable } = require('stream') +const { + createBeginReadyMatchTransformStream, + createResolverWriteStream, + setupResolveWriteStreamPipe, +} = require('../../src/begin-ready') /** * Pipe Readable stream in object mode into process.stdout, @@ -14,16 +13,16 @@ const setupResolveWriteStreamPipe = beginReady.setupResolveWriteStreamPipe * gets assigned a lot of stream listeners such as end, drain, * error, finish, unpipe, close. */ -function debugObjectReadStream(rs, name) { - rs.pipe(new Transform({ - objectMode: true, - transform: (chunk, enc, next) => { - const s = JSON.stringify(chunk, null, 2) - console.log(`Some data from ${name} rs: `) - next(null, `${s}\r\n`) - }, - })).pipe(process.stdout) -} +// function debugObjectReadStream(rs, name) { +// rs.pipe(new Transform({ +// objectMode: true, +// transform: (chunk, enc, next) => { +// const s = JSON.stringify(chunk, null, 2) +// console.log(`Some data from ${name} rs: `) +// next(null, `${s}\r\n`) +// }, +// })).pipe(process.stdout) +// } const commandNumber = '376080' const commandNumber2 = '65754' @@ -111,8 +110,7 @@ const brtsTestSuite = { }) .then((res) => { assert.equal(res.length, 2) - const output = res[0] - const output2 = res[1] + const [output, output2] = res assert.equal(output.cn, commandNumber) assert.equal(output.d, data) assert.equal(output2.cn, commandNumber2) diff --git a/test/spec/codedcharacterset.js b/test/spec/codedcharacterset.js index c0fbbd1..741a90c 100644 --- a/test/spec/codedcharacterset.js +++ b/test/spec/codedcharacterset.js @@ -1,5 +1,5 @@ const assert = require('assert') -const EOL = require('os').EOL +const { EOL } = require('os') const context = require('exiftool-context') const exiftool = require('../../src/') context.globalExiftoolConstructor = exiftool.ExiftoolProcess diff --git a/test/spec/detached-true.js b/test/spec/detached-true.js index 7df45ee..cd3d1db 100644 --- a/test/spec/detached-true.js +++ b/test/spec/detached-true.js @@ -1,5 +1,3 @@ -'use strict' - const makepromise = require('makepromise') const ps = require('ps-node') const assert = require('assert') @@ -86,11 +84,11 @@ const findExiftoolChildAndConhost = (epPid, exiftoolDetached) => { if (!exiftoolDetached) return res // if detached, conhost is child of child exiftool, // which we are now finding - const childExiftool = res[0] + const [childExiftool] = res assert(childExiftool) assert(/exiftool\.exe/.test(childExiftool.command)) return checkPpid(childExiftool.pid).then((conhostRes) => { - const conhost = conhostRes[0] + const [conhost] = conhostRes assert(conhost) assert(/conhost.exe/.test(conhost.command)) const all = [].concat(conhostRes, res) @@ -119,10 +117,7 @@ const setup = (exiftoolDetached, ctx) => { let checkPids return ctx.forkNode(exiftoolDetached) - .then((meta) => { - const forkPid = meta.forkPid - const epPid = meta.epPid - + .then(({ forkPid, epPid }) => { const res = { forkPid, epPid } if (isWindows) { diff --git a/test/spec/exiftool.js b/test/spec/exiftool.js index 292bbae..0154b48 100644 --- a/test/spec/exiftool.js +++ b/test/spec/exiftool.js @@ -1,12 +1,11 @@ -const os = require('os') +const { EOL } = require('os') const assert = require('assert') const child_process = require('child_process') const context = require('exiftool-context') const exiftool = require('../../src/') context.globalExiftoolConstructor = exiftool.ExiftoolProcess -const ChildProcess = child_process.ChildProcess -const EOL = os.EOL +const { ChildProcess } = child_process const exiftoolTestSuite = { context, @@ -163,7 +162,7 @@ const exiftoolTestSuite = { .then((res) => { assert.equal(res.error, null) assert(Array.isArray(res.data)) - const metadata = res.data[0] + const { data: [metadata] } = res const expected = { SourceFile: ctx.replaceSlashes(ctx.jpegFile), Directory: ctx.replaceSlashes(ctx.folder), @@ -265,13 +264,13 @@ const exiftoolTestSuite = { .then((res) => { assert(Array.isArray(res.data)) assert.equal(res.error, null) - const meta = res.data[0] - assert.equal(meta.Keywords.length, keywords.length) - meta.Keywords.forEach((keyword, index) => { + const { data: [metadata] } = res + assert.equal(metadata.Keywords.length, keywords.length) + metadata.Keywords.forEach((keyword, index) => { assert.equal(keyword, keywords[index]) }) - assert.equal(meta.Comment, comment) - assert.equal(meta.Scene, undefined) // should be removed with -all= + assert.equal(metadata.Comment, comment) + assert.equal(metadata.Scene, undefined) // should be removed with -all= }) }, }, diff --git a/test/spec/handle-streams-finish.js b/test/spec/handle-streams-finish.js index f0d7d09..7b7f46d 100644 --- a/test/spec/handle-streams-finish.js +++ b/test/spec/handle-streams-finish.js @@ -1,5 +1,3 @@ -'use strict' - const context = require('exiftool-context') const assert = require('assert') const exiftool = require('../../src/') @@ -9,51 +7,49 @@ context.globalExiftoolConstructor = exiftool.ExiftoolProcess // kill with operating system methods, rather than sending a signal, // which does not work on Windows -function killAndWaitForExit(proc) { - const pid = proc.pid - const killPromise = killPid(pid) - const exitPromise = new Promise(resolve => proc.once('exit', resolve)) - return Promise.all([killPromise, exitPromise]) +function kill(proc) { + if (process.platform !== 'win32') { + return new Promise((resolve, reject) => { + proc.once('error', reject) + proc.once('exit', resolve) + process.kill(proc.pid) + }) + } + return killPid(proc.pid) } const expected = 'stdout and stderr finished before operation was complete' -const runTest = (ctx, getOperationPromise, createTempFile) => { - let err +const runTest = async (ctx, getOperationPromise, createTempFile) => { ctx.create() - return (createTempFile ? ctx.createTempFile() : Promise.resolve()) - .then(() => ctx.ep.open()) - .then(() => { - // stdin might throw "read ECONNRESET" on Linux for some reason - ctx.ep._process.stdin.on('error', () => {}) - // patch stdout so that we never resolve read metadata promise - ctx.ep._stdoutResolveWs._write = (obj, enc, next) => { - next() - } - const operationPromise = getOperationPromise() - .catch((error) => { err = error }) + if (createTempFile) await ctx.createTempFile() + await ctx.ep.open() + // stdin might throw "read ECONNRESET" on Linux for some reason + ctx.ep._process.stdin.on('error', () => {}) + // patch stdout so that we never resolve read metadata promise + ctx.ep._stdoutResolveWs._write = (obj, enc, next) => { + next() + } + const operationPromise = getOperationPromise() - const killPromise = killAndWaitForExit(ctx.ep._process) + const killPromise = kill(ctx.ep._process) - return Promise.all([operationPromise, killPromise]) - }) - .then(() => { - if (!err) { - throw new Error('Expected operation to be rejected') - } - throw err - }).catch((error) => { - assert.equal(error.message, expected) - }) + try { + await operationPromise + throw new Error('Expected operation to be rejected') + } catch ({ message }) { + assert.equal(message, expected) + await killPromise + } } const closeStreamsOnExitTestSuite = { context, - 'should return rejected promise on read': (ctx) => { + 'should return rejected promise when reading': async (ctx) => { const getOperationPromise = () => ctx.ep.readMetadata(ctx.folder) - return runTest(ctx, getOperationPromise) + await runTest(ctx, getOperationPromise) }, - 'should return rejected promise on write': (ctx) => { + 'should return rejected promise when writing': async (ctx) => { const getOperationPromise = () => { const keywords = [ 'keywordA', 'keywordB' ] const comment = 'hello world' @@ -65,7 +61,7 @@ const closeStreamsOnExitTestSuite = { return ctx.ep.writeMetadata(ctx.tempFile, data, ['overwrite_original']) } - return runTest(ctx, getOperationPromise, true) + await runTest(ctx, getOperationPromise, true) }, } diff --git a/test/spec/lib.js b/test/spec/lib.js index b07f103..22a1039 100644 --- a/test/spec/lib.js +++ b/test/spec/lib.js @@ -1,5 +1,5 @@ const assert = require('assert') -const EOL = require('os').EOL +const { EOL } = require('os') const lib = require('../../src/lib') const libTestSuite = { diff --git a/test/spec/read-from-stream.js b/test/spec/read-from-stream.js index 171e30c..89fdaaa 100644 --- a/test/spec/read-from-stream.js +++ b/test/spec/read-from-stream.js @@ -1,4 +1,3 @@ -'use strict' const assert = require('assert') const context = require('exiftool-context') const fs = require('fs')