runShellScript JavaScript transformer Symlinks

Hey! I am having some issues with the runShellScript.

I figured out to run command from my computer, I need the full path. so node is /usr/local/bin/node - I got that by running which node in the cli.

For another command, npx, get /usr/local/bin/npx but thats a symlink to /usr/local/lib/node_modules/npm/bin/npx-cli.js

You can get this full path with readlink -f which npx

But then I get more errors:

env: node: No such file or directory

But if I run the command in my shell, it works.

Should this follow symlinks? If not, how do I run commands that installed on my machine?

async (clipboardContentString) => {
  const shellScript = `/usr/local/bin/node --version`;

  const shellScriptWrapper = {
    script: shellScript, // mandatory
    launchPath: `/bin/zsh`,
  };

  const result = await runShellScript(shellScriptWrapper);
  return result;
};

easiest just do an

echo $PATH in your Terminal, then use the whole path that is returned from there and provide it with PATH= in the environmentVariables property (probably only a small subset is needed though).
I think for npx you could also just pass PATH=/usr/local/bin/
On my machine I had to use PATH=/usr/local/bin/:/Users/andi/.nvm/versions/node/v14.18.1/bin/ because I'm using nvm

async (clipboardContentString) => {
  const shellScript = `/usr/local/bin/node --version`;
  const yourPATH = `result from echo $PATH prefixed by PATH=`
  const shellScriptWrapper = {
    script: shellScript, // mandatory
    launchPath: `/bin/zsh`,
    environmentVariables: yourPATH
  };

  const result = await runShellScript(shellScriptWrapper);
  return result;
};

Then you don't need to use the full paths to your binaries anymore.

thank you! That did it - I appreciate it. Making a cool paste transformer for TypeScript

1 Like

Nice! What does it transform?

I often have TypeScript that I want to paste into the browser console, so It will just take the TS, strip the types and paste as JS

Ah interesting, basically running tsc on your TypeScript before pasting?

Yep - using SWC because it's much faster and keeps the comments

didn't know about SWC, need to check that out :slight_smile:

Yeah, Generally people use TSC for type checking, and then SWC or ESBuild to do a much faster strip types during dev mode.

SWC is inside Parcel, ESBuild is inside Vite

1 Like

@Andreas_Hegenberg what is the best way to pass the clipboardContentString to a CLI? just via the command? Env? I thought it would be piped in via stdin - but I was wrong

Ha good point. The escaping could be problematic.

Maybe something like

const toTransform = btoa(clipboardContentString);
const shellScript = `echo '${toTransform}' | base64 --decode | npx swc -f "test.ts"`

thanks - ended up being able to use this function:

  function encode(str) {
    return encodeURIComponent(str).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16)}`);
  }

:+1:
I always fall back to base64 if I don't want to think about all the possible ways a unescaped string can break stuff :sweat_smile:

Btw. if you are using this with the "Transform & Replace Selection With Java Script" action - I just found a bug that can crash BTT, at least on Ventura. Will upload a fixed alpha in a few minutes.

Hahah you are too fast - I just came back here to say it's crashing when I try it use from the clipboard manager.

It seems to work fine here now with 3.9991 (get via "Check For Alpha Version Updates", I only tested the base64 variant )

It works! Thanks a ton! GitHub - wesbos/clipboard-ts