Open basert opened 1 year ago
Thanks for filing @basert - this seems like a great idea. I'm slating it for review.
Just as a hint, here is what I do to wrap calls to op-js in a Promise-wrapped Worker thread: op-cli-worker.js:
'use strict';
const {
parentPort, workerData,
} = require('node:worker_threads');
const [fName, args] = workerData;
const opJs = require('@1password/op-js');
// Resolve string in the form of 'vault.list' to the actual function
const theFunction = fName.split('.').reduce((o, i) => o[i], opJs);
if (typeof theFunction !== 'function') {
parentPort.postMessage({error: new Error(`Function ${fName} not found`)});
}
try {
const result = theFunction(...args);
parentPort.postMessage({result});
} catch (error) {
parentPort.postMessage({error});
}
And in your application:
function wrapOpJs(f, ...args) {
return new Promise((resolve, reject) => {
const worker = new worker_threads.Worker(`${__dirname}/op-cli-worker.js`, {
workerData: [f, args],
env: worker_threads.SHARE_ENV,
});
worker.on('message', ({error, result}) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
worker.on('error', cause => {
reject(new Error('1password worker failed', cause));
});
worker.on('exit', code => {
if (code !== 0) {
reject(new Error(`Worker stopped with exit code ${code}`));
}
});
});
}
Instead of the usual
require('@1password/op-js').item.edit(item.id, fields, flags)
I do:
await wrapOpJs('item.edit', item.id, fields, flags);
[edit: Put the worker code in a separate file as the original way using a stringified function had some weird side-effects]
Summary
Currently all calls to the op-cli are using
spawnSync
to block until op-cli has a result. This causes issues when you don't want to block the event loop. Is there planned support for async execution (withPromise
as result)?Proposed solution
Add an async version of https://github.com/1Password/op-js/blob/main/src/cli.ts#L255, using
spawn
and returning an Promise. Provide an async package of https://github.com/1Password/op-js/blob/main/src/index.ts that returns a Promise instead.