exiftool-vendored
Advanced tools
Comparing version 25.1.0 to 25.2.0
@@ -0,3 +1,5 @@ | ||
import * as bc from "batch-cluster"; | ||
import { ExifToolOptions } from "./ExifToolOptions"; | ||
import { Omit } from "./Omit"; | ||
export declare const ConsoleLogger: bc.Logger; | ||
/** | ||
@@ -4,0 +6,0 @@ * Default values for `ExifToolOptions`, except for `processFactory` (which is |
@@ -26,4 +26,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.DefaultExifToolOptions = void 0; | ||
exports.DefaultExifToolOptions = exports.ConsoleLogger = void 0; | ||
const bc = __importStar(require("batch-cluster")); | ||
const node_util_1 = require("node:util"); | ||
const CapturedAtTagNames_1 = require("./CapturedAtTagNames"); | ||
@@ -36,2 +37,14 @@ const DefaultExiftoolArgs_1 = require("./DefaultExiftoolArgs"); | ||
const VersionTask_1 = require("./VersionTask"); | ||
const _debuglog = (0, node_util_1.debuglog)("exiftool-vendored"); | ||
function noop() { } | ||
exports.ConsoleLogger = { | ||
trace: noop, | ||
debug: _debuglog, | ||
info: _debuglog, | ||
warn: console.warn, | ||
error: console.error, | ||
}; | ||
function logger() { | ||
return (0, node_util_1.debuglog)("exiftool-vendored").enabled ? exports.ConsoleLogger : bc.NoLogger; | ||
} | ||
/** | ||
@@ -69,2 +82,3 @@ * Default values for `ExifToolOptions`, except for `processFactory` (which is | ||
inferTimezoneFromDatestampTags: [...CapturedAtTagNames_1.CapturedAtTagNames], | ||
logger, | ||
numericTags: [ | ||
@@ -71,0 +85,0 @@ "*Duration*", |
@@ -32,2 +32,3 @@ /// <reference types="node" /> | ||
export { ExifToolTask } from "./ExifToolTask"; | ||
export { exiftoolPath } from "./ExiftoolPath"; | ||
export { isGeolocationTag } from "./GeolocationTags"; | ||
@@ -42,4 +43,14 @@ export { parseJSON } from "./JSON"; | ||
* | ||
* Instances should be shared: consider using the exported singleton instance | ||
* of this class, {@link exiftool}. | ||
* **NOTE: Instances are expensive!** | ||
* | ||
* * use either the default exported singleton instance of this class, | ||
* {@link exiftool}, or your own singleton | ||
* | ||
* * make sure you await {@link ExifTool.end} when you're done with an instance | ||
* to clean up subprocesses | ||
* | ||
* * review the {@link ExifToolOptions} for configuration options--the default | ||
* values are conservative to avoid overwhelming your system. | ||
* | ||
* @see https://photostructure.github.io/exiftool-vendored.js/ for more documentation. | ||
*/ | ||
@@ -49,5 +60,5 @@ export declare class ExifTool { | ||
readonly options: ExifToolOptions; | ||
private readonly batchCluster; | ||
readonly batchCluster: bc.BatchCluster; | ||
constructor(options?: Partial<ExifToolOptions>); | ||
readonly exiftoolPath: () => Promise<string>; | ||
constructor(options?: Partial<ExifToolOptions>); | ||
/** | ||
@@ -54,0 +65,0 @@ * Register life cycle event listeners. Delegates to BatchProcess. |
@@ -35,3 +35,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.exiftool = exports.ExifTool = exports.DefaultWriteTaskOptions = exports.offsetMinutesToZoneName = exports.defaultVideosToUTC = exports.UnsetZoneOffsetMinutes = exports.UnsetZoneName = exports.UnsetZone = exports.DefaultReadTaskOptions = exports.parseJSON = exports.isGeolocationTag = exports.ExifToolTask = exports.ExifTime = exports.ExifDateTime = exports.ExifDate = exports.DefaultMaxProcs = exports.DefaultExiftoolArgs = exports.DefaultExifToolOptions = exports.CapturedAtTagNames = exports.BinaryField = void 0; | ||
exports.exiftool = exports.ExifTool = exports.DefaultWriteTaskOptions = exports.offsetMinutesToZoneName = exports.defaultVideosToUTC = exports.UnsetZoneOffsetMinutes = exports.UnsetZoneName = exports.UnsetZone = exports.DefaultReadTaskOptions = exports.parseJSON = exports.isGeolocationTag = exports.exiftoolPath = exports.ExifToolTask = exports.ExifTime = exports.ExifDateTime = exports.ExifDate = exports.DefaultMaxProcs = exports.DefaultExiftoolArgs = exports.DefaultExifToolOptions = exports.CapturedAtTagNames = exports.BinaryField = void 0; | ||
const bc = __importStar(require("batch-cluster")); | ||
@@ -47,2 +47,3 @@ const _cp = __importStar(require("node:child_process")); | ||
const ExifToolOptions_1 = require("./ExifToolOptions"); | ||
const ExiftoolPath_1 = require("./ExiftoolPath"); | ||
const IsWin32_1 = require("./IsWin32"); | ||
@@ -77,2 +78,4 @@ const Lazy_1 = require("./Lazy"); | ||
Object.defineProperty(exports, "ExifToolTask", { enumerable: true, get: function () { return ExifToolTask_1.ExifToolTask; } }); | ||
var ExiftoolPath_2 = require("./ExiftoolPath"); | ||
Object.defineProperty(exports, "exiftoolPath", { enumerable: true, get: function () { return ExiftoolPath_2.exiftoolPath; } }); | ||
var GeolocationTags_1 = require("./GeolocationTags"); | ||
@@ -92,2 +95,6 @@ Object.defineProperty(exports, "isGeolocationTag", { enumerable: true, get: function () { return GeolocationTags_1.isGeolocationTag; } }); | ||
Object.defineProperty(exports, "DefaultWriteTaskOptions", { enumerable: true, get: function () { return WriteTask_2.DefaultWriteTaskOptions; } }); | ||
/** | ||
* Is the #!/usr/bin/perl shebang line in exiftool-vendored.pl going to fail? If | ||
* so, we need to find `perl` ourselves, and ignore the shebang line. | ||
*/ | ||
const _ignoreShebang = (0, Lazy_1.lazy)(() => !(0, IsWin32_1.isWin32)() && !_fs.existsSync("/usr/bin/perl")); | ||
@@ -104,4 +111,14 @@ const whichPerl = (0, Lazy_1.lazy)(async () => { | ||
* | ||
* Instances should be shared: consider using the exported singleton instance | ||
* of this class, {@link exiftool}. | ||
* **NOTE: Instances are expensive!** | ||
* | ||
* * use either the default exported singleton instance of this class, | ||
* {@link exiftool}, or your own singleton | ||
* | ||
* * make sure you await {@link ExifTool.end} when you're done with an instance | ||
* to clean up subprocesses | ||
* | ||
* * review the {@link ExifToolOptions} for configuration options--the default | ||
* values are conservative to avoid overwhelming your system. | ||
* | ||
* @see https://photostructure.github.io/exiftool-vendored.js/ for more documentation. | ||
*/ | ||
@@ -111,2 +128,9 @@ class ExifTool { | ||
var _a; | ||
this.exiftoolPath = (0, Lazy_1.lazy)(async () => { | ||
var _a; | ||
const o = this.options; | ||
return ((_a = (await ((0, Object_1.isFunction)(o.exiftoolPath) | ||
? o.exiftoolPath(this.options.logger()) | ||
: o.exiftoolPath))) !== null && _a !== void 0 ? _a : (0, ExiftoolPath_1.exiftoolPath)(this.options.logger())); | ||
}); | ||
/** | ||
@@ -120,2 +144,4 @@ * Register life cycle event listeners. Delegates to BatchProcess. | ||
this.off = (event, listener) => this.batchCluster.off(event, listener); | ||
// calling whichPerl through this lazy() means we only do that task once per | ||
// instance. | ||
_ExifTool_checkForPerl.set(this, (0, Lazy_1.lazy)(async () => { | ||
@@ -151,3 +177,2 @@ if (this.options.checkPerl) { | ||
}; | ||
this.exiftoolPath = (0, Lazy_1.lazy)(async () => (0, Object_1.isFunction)(o.exiftoolPath) ? o.exiftoolPath(o.logger()) : o.exiftoolPath); | ||
const processFactory = async () => ignoreShebang | ||
@@ -154,0 +179,0 @@ ? _cp.spawn(await whichPerl(), [await this.exiftoolPath(), ...o.exiftoolArgs], spawnOpts) |
@@ -59,4 +59,6 @@ /// <reference types="node" /> | ||
* `exiftool-vendored.exe`. | ||
* | ||
* This must be the full path to `exiftool`, not just the directory. | ||
*/ | ||
exiftoolPath: string | ((logger?: bc.Logger) => string | Promise<string>); | ||
exiftoolPath: string | Promise<string> | ((logger?: bc.Logger) => string | Promise<string>); | ||
/** | ||
@@ -63,0 +65,0 @@ * Args passed to exiftool on launch. |
import { Logger } from "batch-cluster"; | ||
/** | ||
* This implementation relies on the fact that both `exiftool-vendored.pl` and | ||
* `exiftool-vendored.exe` both export the path to their respective exiftool | ||
* binary. | ||
* | ||
* When running in node, this method should suffice. | ||
* | ||
* When running in Electron, all bets are off, due to ASAR packaging and other | ||
* nonsense. As perl can't run from within an ASAR archive, `electron-builder` | ||
* must be configured to `asarUnpack` | ||
* "**/node_modules/exiftool-vendored.{pl,exe}/". See | ||
* <https://www.electron.build/generated/platformspecificbuildoptions#configuration-asarUnpack> | ||
* for details. | ||
* | ||
* If you're using `electron-forge`, add something like the following to your | ||
* ForgeConfig.packagerConfig.extraResource array: `fs.join(".", "node_modules", | ||
* "exiftool-vendored." + (isWin ? "exe" : "pl"))` but then you must specify a | ||
* custom exiftoolPath in your options hash, as subprocesses that use | ||
* ELECTRON_RUN_AS_NODE will no longer have process.resourcesPath set. | ||
* | ||
* If none of the above work for your use case, you can provide your own | ||
* `exiftoolPath` implementation to your instance of ExifTool | ||
* | ||
* @return the path to the exiftool binary, preferring the vendored version in | ||
* node_modules. | ||
*/ | ||
export declare function exiftoolPath(logger?: Logger): Promise<string>; |
@@ -25,5 +25,2 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -33,3 +30,2 @@ exports.exiftoolPath = void 0; | ||
const _path = __importStar(require("node:path")); | ||
const node_process_1 = __importDefault(require("node:process")); | ||
const IsWin32_1 = require("./IsWin32"); | ||
@@ -50,16 +46,37 @@ const Which_1 = require("./Which"); | ||
} | ||
/** | ||
* This implementation relies on the fact that both `exiftool-vendored.pl` and | ||
* `exiftool-vendored.exe` both export the path to their respective exiftool | ||
* binary. | ||
* | ||
* When running in node, this method should suffice. | ||
* | ||
* When running in Electron, all bets are off, due to ASAR packaging and other | ||
* nonsense. As perl can't run from within an ASAR archive, `electron-builder` | ||
* must be configured to `asarUnpack` | ||
* "**/node_modules/exiftool-vendored.{pl,exe}/". See | ||
* <https://www.electron.build/generated/platformspecificbuildoptions#configuration-asarUnpack> | ||
* for details. | ||
* | ||
* If you're using `electron-forge`, add something like the following to your | ||
* ForgeConfig.packagerConfig.extraResource array: `fs.join(".", "node_modules", | ||
* "exiftool-vendored." + (isWin ? "exe" : "pl"))` but then you must specify a | ||
* custom exiftoolPath in your options hash, as subprocesses that use | ||
* ELECTRON_RUN_AS_NODE will no longer have process.resourcesPath set. | ||
* | ||
* If none of the above work for your use case, you can provide your own | ||
* `exiftoolPath` implementation to your instance of ExifTool | ||
* | ||
* @return the path to the exiftool binary, preferring the vendored version in | ||
* node_modules. | ||
*/ | ||
async function exiftoolPath(logger) { | ||
const path = tryRequire({ prefix: "", logger }); | ||
// This s/app.asar/app.asar.unpacked/ path switch adds support for Electron | ||
// apps that are ASAR-packed (like by electron-builder). This is necessary because | ||
// Note that we can't reliably automatically detect that we're running in | ||
// electron because child processes that are spawned by the main process will | ||
// most likely need the ELECTRON_RUN_AS_NODE environment variable set, which | ||
// will unset the process.versions.electron field. | ||
const fixedPath = path === null || path === void 0 ? void 0 : path.split(_path.sep).map((ea) => (ea === "app.asar" ? "app.asar.unpacked" : ea)).join(_path.sep); | ||
// Note also, that we must check for the fixedPath first, because Electron's | ||
// ASAR shenanigans will make existsSync return true even for asar-packed | ||
// resources. | ||
if (fixedPath != null && _fs.existsSync(fixedPath)) { | ||
return fixedPath; | ||
// apps whose modules are ASAR-packed (like by electron-builder). | ||
const asarUnpackedPath = path === null || path === void 0 ? void 0 : path.split(_path.sep).map((ea) => (ea === "app.asar" ? "app.asar.unpacked" : ea)).join(_path.sep); | ||
// NOTE: we must check for the fixedPath FIRST, because Electron's ASAR | ||
// shenanigans will make existsSync return true for asar-packed resources | ||
if (asarUnpackedPath != null && _fs.existsSync(asarUnpackedPath)) { | ||
return asarUnpackedPath; | ||
} | ||
@@ -70,4 +87,4 @@ if (path != null && _fs.existsSync(path)) { | ||
logger === null || logger === void 0 ? void 0 : logger.warn("Failed to find exiftool via " + vendorPackage()); | ||
// Set by electron-forge: | ||
const electronResourcePath = node_process_1.default.resourcesPath; | ||
// process.resourcesPath is set by electron-forge: | ||
const electronResourcePath = process.resourcesPath; | ||
if (electronResourcePath != null) { | ||
@@ -74,0 +91,0 @@ const forgePath = _path.join(electronResourcePath, vendorPackage(), "bin", "exiftool" + ((0, IsWin32_1.isWin32)() ? ".exe" : "")); |
{ | ||
"name": "exiftool-vendored", | ||
"version": "25.1.0", | ||
"version": "25.2.0", | ||
"description": "Efficient, cross-platform access to ExifTool", | ||
@@ -80,8 +80,8 @@ "main": "./dist/ExifTool.js", | ||
"@types/mocha": "^10.0.6", | ||
"@types/node": "^20.11.30", | ||
"@types/node": "^20.12.7", | ||
"@types/progress": "^2.0.7", | ||
"@types/tmp": "^0.2.6", | ||
"@types/xmldom": "^0.1.34", | ||
"@typescript-eslint/eslint-plugin": "^7.4.0", | ||
"@typescript-eslint/parser": "^7.4.0", | ||
"@typescript-eslint/eslint-plugin": "^7.6.0", | ||
"@typescript-eslint/parser": "^7.6.0", | ||
"@xmldom/xmldom": "^0.8.10", | ||
@@ -94,3 +94,3 @@ "chai": "^4.3.10", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-regexp": "^2.4.0", | ||
"eslint-plugin-regexp": "^2.5.0", | ||
"extract-zip": "^2.0.1", | ||
@@ -109,4 +109,4 @@ "geo-tz": "^8.0.2", | ||
"tmp": "^0.2.3", | ||
"typedoc": "^0.25.12", | ||
"typescript": "^5.4.3", | ||
"typedoc": "^0.25.13", | ||
"typescript": "^5.4.5", | ||
"xpath": "^0.0.34" | ||
@@ -123,5 +123,5 @@ }, | ||
"optionalDependencies": { | ||
"exiftool-vendored.exe": "12.80.0", | ||
"exiftool-vendored.pl": "12.80.0" | ||
"exiftool-vendored.exe": "12.82.0", | ||
"exiftool-vendored.pl": "12.82.0" | ||
} | ||
} |
@@ -46,3 +46,17 @@ # exiftool-vendored | ||
npm install --save exiftool-vendored | ||
### Debug logging | ||
If anything doesn't work, the first thing to try is enabling the logger. | ||
You can provide a [Logger implementation](https://photostructure.github.io/batch-cluster.js/interfaces/Logger.html) via [`ExifToolOptions.logger`](https://photostructure.github.io/exiftool-vendored.js/interfaces/ExifToolOptions.html#logger), or set the environment variable `NODE_DEBUG=exiftool-vendored`. [See the debuglog() documentation](https://nodejs.org/docs/latest/api/util.html#utildebuglogsection-callback) for more details. | ||
### Regarding use within Electron | ||
Due to how different every Electron application setup is, and how new versions | ||
frequently have breaking changes, **do not ask for help by opening a github | ||
issue on this project.** | ||
Please seek help via StackOverflow, the Electron discord, or other channels. | ||
### Electron-builder support | ||
@@ -56,2 +70,5 @@ | ||
The default `exiftoolPath` implementation will detect `app.asar` in your `require` | ||
path and replace it with `app.asar.unpacked` automatically. | ||
### Electron-forge support | ||
@@ -61,3 +78,3 @@ | ||
add the following element to your `ForgeConfig.packagerConfig.extraResource` | ||
string array, and things should "just work": | ||
string array, and things should "just work" **for the main process**. | ||
@@ -69,2 +86,10 @@ ```ts | ||
**If your main process forks any node subprocesses, `process.resourcesPath` _will | ||
not be set_ in those subprocesses, and the default `exiftoolPath` won't work.** | ||
If this is your case, you must provide a correct implementation of | ||
[ExifToolOptions.exiftoolPath](https://photostructure.github.io/exiftool-vendored.js/interfaces/ExifToolOptions.html#exiftoolPath), | ||
either by passing through `resourcesPath` via `process.env`, or some other | ||
method. | ||
### Installation notes | ||
@@ -71,0 +96,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
585502
10009
519