UNPKG

3.89 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10var __importDefault = (this && this.__importDefault) || function (mod) {
11 return (mod && mod.__esModule) ? mod : { "default": mod };
12};
13Object.defineProperty(exports, "__esModule", { value: true });
14const debug_1 = __importDefault(require("debug"));
15const defer_1 = require("./utils/defer");
16const debug = debug_1.default('stagehand:command-coordinator');
17/**
18 * Coordinates command/response pairs across a given `MessageEndpoint`, returning
19 * a promise for each outgoing command and dispatching incoming ones to a given
20 * executor.
21 */
22class CommandCoordinator {
23 constructor(endpoint, handleRegistry, executor) {
24 this.endpoint = endpoint;
25 this.handleRegistry = handleRegistry;
26 this.executor = executor;
27 this.nextSeq = 0;
28 this.pendingCommands = new Map();
29 this.endpoint.onMessage(this.messageReceived.bind(this));
30 }
31 sendCommand(name, ...args) {
32 let seq = this.nextSeq++;
33 let dfd = defer_1.defer();
34 let command = { [COMMAND]: seq, name, args: this.handleRegistry.dehydrate(args) };
35 this.pendingCommands.set(seq, dfd);
36 this.sendMessage(command);
37 return dfd.promise;
38 }
39 messageReceived(message) {
40 return __awaiter(this, void 0, void 0, function* () {
41 debug('Message received %o', message);
42 if (this.isResponse(message)) {
43 return this.dispatchResponse(message);
44 }
45 else if (this.isCommand(message)) {
46 return this.dispatchCommand(message);
47 }
48 });
49 }
50 dispatchResponse(response) {
51 let pending = this.pendingDeferred(response);
52 if (pending !== undefined) {
53 if (response.error) {
54 pending.reject(typeof response.value === 'string' ? new Error(response.value) : response.value);
55 }
56 else {
57 pending.resolve(this.handleRegistry.rehydrate(response.value));
58 }
59 }
60 else {
61 debug('Received a response message for an unknown command %o', response);
62 }
63 }
64 dispatchCommand(message) {
65 return __awaiter(this, void 0, void 0, function* () {
66 let response = { [RESPONSE]: message[COMMAND], error: false, value: undefined };
67 let method = this.executor[message.name];
68 try {
69 let result = yield method(...this.handleRegistry.rehydrate(message.args));
70 response.value = this.handleRegistry.dehydrate(result);
71 }
72 catch (error) {
73 response.error = true;
74 response.value = error.message || error;
75 }
76 this.endpoint.sendMessage(response);
77 });
78 }
79 sendMessage(message) {
80 debug('Sending message %o', message);
81 this.endpoint.sendMessage(message);
82 }
83 pendingDeferred(response) {
84 return this.pendingCommands.get(response[RESPONSE]);
85 }
86 isResponse(message) {
87 return message && typeof message[RESPONSE] === 'number';
88 }
89 isCommand(message) {
90 return message && typeof message[COMMAND] === 'number';
91 }
92}
93exports.default = CommandCoordinator;
94const COMMAND = '--stagehand-command';
95const RESPONSE = '--stagehand-response';