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

osa

v2.5.0

Published

node.js module for interfacing with OSX 10.10 Javascript OSA Scripting

Downloads

110

Readme

node-osa

Node.js module for running Open Scripting Architecture code in OSX 10.10+

##Overview

OSA allows for advanced interaction between applications on OSX. In the past, it has largely been implemented using AppleScript. Beginning in OSX 10.10 Yosemite, Apple has opened up this platform for development in Javascript. This has been regarded as the best thing ever, by me.

node-osa creates the illusion of being able to call OSA scripts naturally from node. As a pleasant side-effect, it also allows for easy OSA development with compile-to-js tools such as Babel or CoffeeScript.

##Installation

npm install osa

##Use

var osa = require('osa');

//function to be executed on the osa side
function osaFunction(arg [, moreArgs...]) { ... }

//called when the osa function completes
function callback(err, result, log) { ... }

osa(osaFunction, arg [, moreArgs...], callback);

##Testing

npm test
npm run demo
npm run cover
npm run lint

##Limitations

  • As it is executing in an entirely different environment, the context of the passed osaFunction is completely ignored. It cannot behave like a closure or modify any external variables.
  • As JSON is used as the transport mechanism, only Objects, Arrays, Numbers, Strings, true, false, and null can be passed back and forth between the two environments. That is to say, you cannot pass a node library or class to OSA, and you cannot return an OSA object to node, even as a placeholder.
  • You cannot use node builtins or npm modules on the osa side.
  • Currently no streaming is used for the JSON parsing. Sending or returning very large values (on the order of megabytes) may cause memory problems.
  • The OSA javascript environment is entirely syncronous. Functions like setTimeout are not available. Any asynchronous behavior will need to be conducted on the node side.
  • As each call spawns off a new process and spins up a new environment, calls take a while. On a 2014 Macbook Air, calls take around 50ms. Of course this is all asynchronous from Node's point of view, but making many calls in series may take quite a while.

That said, all of these limitations are problems with the OSA environment, not with this module. None of these could be improved by using AppleScript instead. This module will likely meet many needs of simple node OSX utilities. It's an awesome way to combine the power of a platform like node with the unique abilities that OSA offers.

##Example

This is a basic script that prompts the user for some information, and passes it back to node.

This example is contained in demo/demo.js and you can run it yourself with npm run demo.

First, we will write our function that will be evaluated in the OSA environment. Notice that it gets automatic access to the Application object (as well as Library, Path, ObjectSpecifier, delay, ObjC, Ref, and $).

var promptForHandle = function (service, defaultHandle, done) {
	var app = Application.currentApplication();
	var prompt = 'What is your ' + service + ' handle?';
	var promptArguments = {
		withTitle: 'Hello, world!',
		defaultAnswer: defaultHandle
	};
	var result;

	app.includeStandardAdditions = true;

	result = app.displayDialog(prompt, promptArguments);

	return {service: service, text: result.textReturned};
};

Next, we will write the function than handles the callback from the OSA call. Notice that it takes 3 arguments:

  • err - an Error if one is triggered in the osa world, or something goes wrong with the call
  • result - the return value of the function passed to osa
  • log - a \n-delimited String of all console.log statements executed in the osa function
responseHandler = function (err, result, log) {
	var stringToPrint;

	if (err) {
		console.error(err)
	} else {
		stringToPrint = 'Your ' + result.service + ' handle is ' + result.text;
		console.log(stringToPrint);
	}
};

Then, we will actually make the osa call. This will call promptForHandle, with 2 arguments, 'twitter' and '@brandonhorst'. Whatever it returns will be passed to responseHandler.

osa = require('osa');

osa(promptForHandle, 'twitter', '@brandonhorst', responseHandler);

When we run it:

$ npm run demo
	*A textbox should appear, prompting for input. If we accept the default...*
Your twitter handle is @brandonhorst

##Implementation

  • When its exported function is called, the module generates a string of javascript code. This code is a string representation of osaFunction, self-executed with args and a final callback.
  • This string of javascript is executed using the osascript utility. Returned value is passed back to node in JSON via stdout.
  • The module parses the JSON, and passes it to the original done callback.

##How Come the OSA Side Isn't Passed a Callback?

In 0.x, the OSA function was passed a callback that it could call. However, as it turns out, Apple's OSA Javascript isn't really designed to work asynchronously. Its API calls are syncronous and it does not have functions like setTimeout. Because of this, a callback seems unnecessary. If you do need one for some reason, please open an issue.