- Notifications
You must be signed in to change notification settings - Fork1
License
potsbo/jxa-graphql
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Access AppleScript supported apps via GraphQL interface.
The motivation is easier software development with AppleScript supported apps.
We have several obstacles to develop real world application with AppleScript.
- need to write long scripts to avoid N+1 problem
- need to write complex
whose
clauses
Because of these, we had to write a dedicated script for one task, which often becomes less reusable.With JXA GraphQL, it becomes much easier to achieve fast AppleScript access.
In theory, it is possible to maintain performant generic reusable AppleScript/JXA code.But in reality, because it lacks built-in type system and well written documents, it is not realistic to ensure the code works as expected.
It's been tried to introduce type safety to JXA.As far as I'm aware of,@jxa/sdef-to-dts is the best example of this approach, which offers a great way to convertsdef
files into TypeScript type definitions.Although this library is very effective, because we have to pass JXA as string, we need to make sure that the JXA we are trying execute can be encoded into string, which can easily become tricky.To address this issue, JXA GraphQL uses GraphQL as a strict but flexible boudary between application code and JXA code.
server
command starts a new GraphQL server.WithApollo Sandbox
, or any other preferred tools, you can run GraphQL queries to get data from applications.
$ npx jxa-graphql serve --helpjxa-graphql serve <appPath>start a GraphQL server for the given ApplicationPositionals: appPath Application path [string] [required]Options: --help Show help [boolean] --version Show version number [boolean] -p, --port port number of the GraphQL server [number] [default: 4000]
$ npx jxa-graphql serve /Applications/Google\ Chrome.app🚀 Server ready at http://localhost:4000/# in another shell$ curl 'http://localhost:4000/' \ -H 'content-type: application/json' \ --data-raw '{"query":"query { application { name } }","variables":{}}' | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed100 107 100 50 100 57 548 625 --:--:-- --:--:-- --:--:-- 1371{ "data": { "application": { "name": "Google Chrome" } }}
You can integratejxa-graphql
into any application.
import{graphql}from"graphql";import{makeExecutableSchema}from"@graphql-tools/schema";import{runJXACode}from"@jxa/run";import{buildRootValue,buildSchema}from"jxa-graphql";(async()=>{// build schema from AppleScript `sdef` fileconsttypeDefs=awaitbuildSchema("/Applications/Google Chrome.app");// build rootValue, which can compile GraphQL queries into jxa codeconstrootValue=buildRootValue("Google Chrome",runJXACode);constsource=` query { application { name } } `;// compile typeDef and resolvers into executable schemaconstschema=makeExecutableSchema({ typeDefs,resolvers:{Query:rootValue}});// executeconst{ data}=awaitgraphql({ schema, source});console.log(JSON.stringify(data));// prints {"application":{"name":"Google Chrome"}}})();
To be written
Becausejxa-graphql
implementsGraphQL Cursor Connections Specification, you can access only s
query {application {windows(first:42,after:1234) {pageInfo {hasNextPagehasPreviousPagestartCursorendCursor }edges {cursornode {name } } } }}
To be written
To be written
To be written
To be written
To be written
To be written
JXA GraphQL is a GraphQL wrapper forJavaScript for Automation (JXA).
compile graphql query into javascript
query {application {calendars(first:3,whose: {field:"writable",value:"true" }) {edges {node {name } } } }}
functionpascalCase(s){return(s.match(/[a-zA-Z0-9]+/g)||[]).map((w)=>`${w[0].toUpperCase()}${w.slice(1)}`).join("");}functionextractId(obj){constspec=Automation.getDisplayString(obj);return(spec?.split("byId").reverse()[0].match(/^\\(\"(.+)\"\\)$/)?.reverse()[0]??null);}functionpaginate(nodes,{ first, after},getId){constafterIndex=after===undefined ?undefined :nodes.findIndex((n)=>getId(n)===after);if(afterIndex===-1){return[];}conststart=afterIndex===undefined ?0 :afterIndex+1;constend=first!==undefined ?start+first :undefined;returnnodes.slice(start,end);}constapp=Application("Calendar");JSON.stringify({result:{calendars:(()=>{constallNodes=app.calendars.whose({writable:{_equals:true}})();constnodes=paginate(allNodes,{first:3},extractId);return{edges:nodes.map((elm)=>{return{node:{name:elm.name()}};}),};})(),},});
Since AppleScript specification is hard to grasp and different applications require different features,it is impossible to support every functionalities that is potentially required in the future.This is why JXA Graphql follows these development policy described below.
Or in other words, 100% test coverage.
It is ok to write code thatthrow
s when the input is formed in unwanted way.Test First principle make it easier to refactor anytime.
This library is still in experiment and a lot of its design can be subject to change anytime.Because of this fact, sophisticated architecture should not be required.This implement it and consider better design later.
When new tag pushed, GitHub Actions automatically create GitHub Releases and runnpm publish
$ npm version <newversion>$ git push origin <newversion>
About
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.