diff --git a/desktop/examples/headless-tic-tac-toe/consts.js b/desktop/examples/headless-tic-tac-toe/consts.js new file mode 100644 index 000000000..b56e29835 --- /dev/null +++ b/desktop/examples/headless-tic-tac-toe/consts.js @@ -0,0 +1,11 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +module.exports.ticTacToePluginId = 'ReactNativeTicTacToe'; +module.exports.player = 'O'; diff --git a/desktop/examples/headless-tic-tac-toe/flipperClient.js b/desktop/examples/headless-tic-tac-toe/flipperClient.js new file mode 100644 index 000000000..fe57f2db3 --- /dev/null +++ b/desktop/examples/headless-tic-tac-toe/flipperClient.js @@ -0,0 +1,77 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const WebSocket = require('ws'); +const EventEmitter = require('events'); + +class FlipperServerClient { + messageId = 0; + wsClient = new WebSocket('ws://localhost:52342?server_companion=true'); + execReqs = new Map(); + eventBus = new EventEmitter(); + + async init() { + await new Promise((resolve) => this.wsClient.on('open', resolve)); + + this.wsClient.on('message', (data) => { + const {event, payload} = JSON.parse(data); + + switch (event) { + case 'exec-response': + case 'exec-response-error': { + const req = this.execReqs.get(payload.id); + + if (!req) { + console.warn('Unknown exec request'); + return; + } + + this.execReqs.delete(payload.id); + + if (event === 'exec-response') { + req.resolve(payload.data); + } else { + req.reject(payload.data); + } + return; + } + case 'companion-event': { + this.eventBus.emit(payload.event, payload.data); + } + } + }); + } + + exec(command, args) { + return new Promise((resolve, reject) => { + const id = this.messageId++; + + this.wsClient.send( + JSON.stringify({ + event: 'exec', + payload: { + id, + command, + args, + }, + }), + ); + + this.execReqs.set(id, {resolve, reject}); + }); + } + + on(eventName, cb) { + this.eventBus.on(eventName, cb); + } +} + +module.exports = { + FlipperServerClient, +}; diff --git a/desktop/examples/headless-tic-tac-toe/index.js b/desktop/examples/headless-tic-tac-toe/index.js new file mode 100644 index 000000000..86757606c --- /dev/null +++ b/desktop/examples/headless-tic-tac-toe/index.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const main = async () => { + // TODO: Implement me +}; + +main().catch(console.error); diff --git a/desktop/examples/headless-tic-tac-toe/package.json b/desktop/examples/headless-tic-tac-toe/package.json new file mode 100644 index 000000000..bb4315f87 --- /dev/null +++ b/desktop/examples/headless-tic-tac-toe/package.json @@ -0,0 +1,12 @@ +{ + "name": "flipper-headless-tic-tac-toe", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "ws": "^8.6.0" + } +} diff --git a/desktop/examples/headless-tic-tac-toe/yarn.lock b/desktop/examples/headless-tic-tac-toe/yarn.lock new file mode 100644 index 000000000..22ba9dc32 --- /dev/null +++ b/desktop/examples/headless-tic-tac-toe/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ws@^8.6.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.6.0.tgz#e5e9f1d9e7ff88083d0c0dd8281ea662a42c9c23" + integrity sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==