npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-jxa

v2.1.2

Published

Use CommonJS node modules (and your favorite JS editor) for your JXA (Javascript for OSX automation) scripts.

Downloads

43

Readme

node-jxa

Build Status npm version downloads github

Use your favorite node.js modules, or your own local modules, in your JXA (OSX Javascript automation) scripts. Based on this awesome tip from the JXA Cookbook.

What is JXA?

It's OS X automation, using Javascript.

Applescript has long been the scripting language provided by Apple for automating and integrating apps on Mac OS X. The Internet is replete with Q & A, tips and examples of how to use Applescript to automate various menial tasks, like:

  • Archiving anything to Evernote
  • Capturing an email or Evernote link to your task manager (e.g. OmniFocus)
  • Capture your Safari reading list to your task manager

Since OS X 10.10 (Yosemite), Javascript (called Javascript for Automation, or JXA) is also supported for app automation. This is great news, especially for Javascript developers who want to automate workflows on their Mac.

What is node-jxa?

Based on this awesome tip, node-jxa allows you to use commonJS modules in your JXA scripts. You can require modules installed from npm, or your own local modules:

const _ = require( 'lodash' ); // from npm
const myModule = require( './my-module' );  // local modules too

ES6 module syntax (import from) isn't currently supported, so stick with require(), and use module.exports in your own local modules.

You can also use your favorite Javascript editor instead of the OS X Script Editor, and use workflow that is much more familiar to JS developers (vs. compiling .js files to .scpt binary format).

So long as your editor can launch a shebang'd script, you can run or debug JXA while you edit.

Installation and usage

You'll likely want to install node-jxa globally:

yarn global add node-jxa # or the npm equivalent: npm install -g node-jxa

This will install node-jxa and make it available in your PATH env var.

.. then you can (optionally) use a shebang at the top of your JXA script:

#! /usr/bin/env node-jxa

// ... rest of script

and make your script executable:

chmod u+x my-jxa-script.js

.. so you can run it from the command line (or, using your favorite script launcher, keyboard shortcuts, etc).

./my-jxa-script.js

You can of course use the node-jxa command on the command line; simply provide the jxa script as the first argument:

node-jxa ./my-jxa-script.js

Node.js engine and JXA runtime

Note that your installed node.js engine is only used by node-jxa to bundle up your module dependencies, and to decorate your script with a couple of needed additions (using the Browserify API). The resulting code is then piped to osascript, and your OS X JavaScriptCore (modified for OSA integration) is used to execute it. Node.js is not ultimately used to execute your script.

ES6+ syntax support

Fortunately the supported ES syntax and features is quite modern (depending on your OS X version). As long as your installed node.js engine is recent enough for Browserify to bundle your code, you should be able to use just about any modern ES syntax you like (except for ES6 module syntax, i.e. import from). To see what's supported, check what version of Safari you have, then find its column at the Kangax compatibility site.

Note: the Kangax table has a column for JXA, but it doesn't appear to be current.

Project structure and availability of node modules

All modules you require in your scripts must be installed (i.e. in the node_modules dir) to be available, so Browserify can bundle them into your script.

I suggest managing your node-jxa scripts like any node.js project, with a package.json specifying the needed module dependencies. Simply use yarn or npm to add and remove the libraries you need.

Note that Browserify won't automatically package modules for which the required path is computed at runtime. For example, let myNeededModulePath = './my/needed/module' ; let myModule = require( myNeededModulePath ); will leave the module out and it won't work. This can happen within modules you're getting from npm. Browserify has techniques for handling this, but node-jxa doesn't currently employ them.

Using Applescript libraries

You can use your Applescript libraries in your JXA scripts using the Library global function, like so:

let myAsLib = Library( 'myApplescriptLibary' ) // skip the .scpt suffix

All top-level Applescript routines and handlers in the library will be available as functions on the imported object.

Library files must be located in your Script Libraries folder or in your OSA_LIBRARY_PATH (the latter as of OS X 10.11) to be used in this way.

This works with JXA libraries too - you can use Library() to import .scpt scripts compiled from Javascript. But since node-jxa allows you to require() from your local js files, it's much better to use your js libraries like local node.js modules, using module.exports.

There are several other globals added by the JXA runtime; they are detailed by Apple, here.

Scripting Dictionaries

With node-jxa you can use your favorite JS editor for writing and managing your JXA code, but the OS X Script is still useful for viewing the Scripting Dictionaries for your scriptable apps. Essentially, this is the documentation for the API exposed by the apps' developers. Look for Open Dictionary... on the File Menu, and be sure to select JavaScript in the language selector at the top.

Be prepared for some weirdness

Some things are weird, including but not limited to:

  • trying to console.log a JXA application object will probably crash the process.
  • Element Arrays (arrays provided directly by Applications ( or filtering via whose() ) are weird. A simple trick like array.map( el => el ) will give you a real JS array.
  • property access for JXA objects is expensive. If you're doing many reads, your script can take a long time and may even time out. A caching strategy can help.

Debugging

You can debug your JXA scripts using Safari dev tools. To debug, enable JSContexts support in Safari, then simply include the debugger; command in your script. When you run the script it'll stop and open at that spot in the Safari debugger (from here, you can add additional breakpoints in Safari's debugger).

If you add the --debug (or -d) switch to the node-jxa, command (including in your shebangs), Browserify will include sourcemaps in the bundled code, for a cleaner debugging experience that is more focused on your own code.

Sourcemaps will also be included if the environment variable NODE_DEBUG_JXA is set to true or 1, regardless of whether the --debug or -d switches are used.

Depending on your Mac, you might never notice a difference in performance when including sourcemaps. You'll definitely see more of a performance hit from requiring many large or spurious libraries, regardless of sourcemaps.

Other JXA resources

Note that there are many more resources available for Applescript on the interwebs (or even from Apple) than there is for JXA. When googling for an example or recipe, you'll probably find much more help by looking an Applescript that does what you want, and then converting to Javascript yourself. You can temporarily use an Applescript library if the conversion eludes you for a time.