From 19f628ec50f5049302734768e9cd7f045faa0b09 Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Mon, 17 Jan 2022 23:49:35 +0100 Subject: [PATCH] add typescript definitions --- .github/workflows/simulator_types.yml | 23 ++++++++++ README.md | 18 ++++++++ create-xdc.sh | 2 +- webxdc.d.ts | 64 +++++++++++++++++++++++++++ webxdc.js | 6 ++- 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/simulator_types.yml create mode 100644 webxdc.d.ts diff --git a/.github/workflows/simulator_types.yml b/.github/workflows/simulator_types.yml new file mode 100644 index 0000000..2e18373 --- /dev/null +++ b/.github/workflows/simulator_types.yml @@ -0,0 +1,23 @@ +name: Are types and sim in sync? + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14.x + uses: actions/setup-node@v1 + with: + node-version: 14.x + - name: install typescript + run: | + npm i -g typescript + - name: check if simulator (webxdc.js) and types (webxdc.d.ts) are in sync + run: | + tsc --noEmit --allowJs webxdc.js diff --git a/README.md b/README.md index 4474f3c..59bf9e4 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,21 @@ and send it to your friends :) note, that the api is not yet complete, this is just a, maybe already useful, proof-of-concept for now. + + +## use type-checking and completion + +If you are using vscode you can have autocompletion and type-checking even without using typescript. + +just add these two lines to your javascript source files: +```js +//@ts-check +/** @typedef {import('./webxdc').WEBxDC} WEBxDC */ +``` + +Without vscode you need to install typescript and then run the check manually. +```sh +npm -g typescript +tsc --noEmit --allowJs webxdc.js # to check if types and simulator are in sync +tsc --noEmit --allowJs your_js_file.js +``` \ No newline at end of file diff --git a/create-xdc.sh b/create-xdc.sh index d060cd8..39665cc 100755 --- a/create-xdc.sh +++ b/create-xdc.sh @@ -14,7 +14,7 @@ case "$1" in esac rm "$PACKAGE_NAME.xdc" 2> /dev/null -zip -9 --recurse-paths "$PACKAGE_NAME.xdc" * --exclude README.md webxdc.js "*.sh" "*.xdc" +zip -9 --recurse-paths "$PACKAGE_NAME.xdc" * --exclude README.md webxdc.js webxdc.d.ts "*.sh" "*.xdc" echo "success, archive contents:" unzip -l "$PACKAGE_NAME.xdc" diff --git a/webxdc.d.ts b/webxdc.d.ts new file mode 100644 index 0000000..9921a29 --- /dev/null +++ b/webxdc.d.ts @@ -0,0 +1,64 @@ +//@ts-check + +type SendingStateUpdate = { + /** the payload, deserialized json: + * any javascript primitive, array or object. */ + payload: T; + /** optional, short, informational message that will be added to the chat, + * eg. "Alice voted" or "Bob scored 123 in MyGame"; + * usually only one line of text is shown, + * use this option sparingly to not spam the chat. */ + info?: string; + /** optional, short text, shown beside app icon; + * it is recommended to use some aggregated value, + * eg. "8 votes", "Highscore: 123" */ + summary?: string; +}; + +type RecievedStateUpdate = { + /** the payload, deserialized json */ + payload: T; +}; + +interface WEBxDC { + /** Returns the peer's own address. + * This is esp. useful if you want to differ between different peers - just send the address along with the payload, + * and, if needed, compare the payload addresses against selfAddr() later on. */ + selfAddr(): string; + /** Returns the peer's own name. This is name chosen by the user in their settings, if there is nothing set, that defaults to the peer's address. */ + selfName(): string; + /** + * set a listener for new state updates + * note that own state updates, that you send with {@link sendStateUpdate}, also trigger this method + * */ + setUpdateListener(cb: (stateUpdate: RecievedStateUpdate) => void): void; + /** + * In case your Webxdc was just started, + * you may want to reconstruct the state from the last run - and also incorporate updates that may have arrived while the app was not running. + */ + getAllUpdates(): RecievedStateUpdate[]; + /** + * Webxdc apps are usually shared in a chat and run independently on each peer. To get a shared state, the peers use sendUpdate() to send updates to each other. + * @param description short, human-readable description what this update is about. this is shown eg. as a fallback text in an email program. + */ + sendUpdate(update: SendingStateUpdate, description: string): void; +} + +////////// ANCHOR: global +declare global { + interface Window { + webxdc: WEBxDC; + } +} +////////// ANCHOR_END: global + +export { SendingStateUpdate, RecievedStateUpdate, WEBxDC }; + +/* Types for the Simulator */ +declare global { + interface Window { + addXdcPeer: () => void; + clearXdcStorage: () => void; + alterXdcApp: () => void; + } +} diff --git a/webxdc.js b/webxdc.js index 67894b9..0f1446f 100644 --- a/webxdc.js +++ b/webxdc.js @@ -1,6 +1,8 @@ // debug friend: document.writeln(JSON.stringify(value)); +//@ts-check +/** @type {import('./webxdc').WEBxDC} */ window.webxdc = (() => { - var updateListener = () => {}; + var updateListener = (_) => {}; var updatesKey = "__xdcUpdatesKey__"; window.addEventListener('storage', (event) => { if (event.key == null) { @@ -52,7 +54,7 @@ window.addXdcPeer = () => { window.open(url); // update next peer ID - params.set("next_peer", peerId + 1); + params.set("next_peer", String(peerId + 1)); window.location.hash = "#" + params.toString(); }