Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

License

NotificationsYou must be signed in to change notification settings

potsbo/jxa-graphql

Repository files navigation

npm versionTestcodecovLicense: MIT

JXA GraphQL

Access AppleScript supported apps via GraphQL interface.

Motivation

The motivation is easier software development with AppleScript supported apps.

Performance - fetch only what we want

We have several obstacles to develop real world application with AppleScript.

  • need to write long scripts to avoid N+1 problem
  • need to write complexwhose 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.

Safety - GraphQL as a boundary

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.

Usage

serve

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]

Example

$ 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"    }  }}

jxa-graphql as a library

You can integratejxa-graphql into any application.

Example

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"}}})();

Features

To be written

Pagination

Becausejxa-graphql implementsGraphQL Cursor Connections Specification, you can access only s

query {application {windows(first:42,after:1234) {pageInfo {hasNextPagehasPreviousPagestartCursorendCursor      }edges {cursornode {name        }      }    }  }}

Fragment

To be written

Inline Fragment

To be written

Mutation (To be implemented)

To be written

Enum

To be written

Schema Override

To be written

whose / byId

To be written

How it works

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()}};}),};})(),},});

Development

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.

Test First

Or in other words, 100% test coverage.

YAGNI

It is ok to write code thatthrows when the input is formed in unwanted way.Test First principle make it easier to refactor anytime.

Done Is Better Than Perfect

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.

Release

When new tag pushed, GitHub Actions automatically create GitHub Releases and runnpm publish

Command to run

$ npm version <newversion>$ git push origin <newversion>

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp