UNPKG

@wishcore/wish-sdk

Version:

Wish API for node. Used for building Wish Apps.

224 lines 9.33 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.App = void 0; const net_1 = require("net"); const protocol_1 = require("./protocol"); const events_1 = require("events"); const peer_1 = require("./peer"); const BSON = new (require('bson-buffer'))(); class App extends events_1.EventEmitter { constructor(opts) { super(); this.opts = opts; this.host = '127.0.0.1'; this.port = 9094; // Extended frame format support this.supportsExtendedFrames = true; // Re-enabled - let's fix the issues this.maxFrameSize = 4 * 1024 * 1024; // 4MB default this.negotiatedExtended = false; this.requestMap = {}; this.id = 0; this.peers = {}; this.state = 'connecting'; this.host = opts.coreHost || '127.0.0.1'; this.port = opts.corePort; this.name = opts.name; this.protocols = opts.protocols || []; this.connect(); } send(peer, frame) { return __awaiter(this, void 0, void 0, function* () { return this.requestAsync('services.send', [peer, frame]); }); } /** * Enable or disable extended frame format support * @param enabled Whether to support extended frames * @param maxSize Maximum frame size in bytes (default 4MB) */ setExtendedFrameSupport(enabled, maxSize = 4 * 1024 * 1024) { this.supportsExtendedFrames = enabled; this.maxFrameSize = maxSize; } requestAsync(op, args) { return new Promise((resolve, reject) => { this.requestMap[++this.id] = (msg) => { if (msg.err) { return reject(msg.data); } resolve(msg.data); }; this.tcp.write(this.createFrame({ op, args, id: this.id })); }); } request(op, args, cb) { if (typeof cb !== 'function') { return new Promise((resolve, reject) => { this.requestMap[++this.id] = (msg) => { if (msg.err) { return reject(msg.data); } resolve(msg.data); }; this.tcp.write(this.createFrame({ op, args, id: this.id })); }); } this.requestMap[++this.id] = (msg) => { cb(!!msg.err, msg.data); }; this.tcp.write(this.createFrame({ op, args, id: this.id })); return this.id; } requestBare(op, args, cb) { this.requestMap[++this.id] = cb; this.tcp.write(this.createFrame({ op, args, id: this.id })); return this.id; } connect() { return __awaiter(this, void 0, void 0, function* () { this.tcp = new net_1.Socket(); this.protocol = new protocol_1.SocketProtocol(this.tcp); this.waitFrame(); this.tcp.connect(this.port, this.host, () => { const wsid = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'); wsid.write(this.name, 0); this.tcp.write(this.createLoginFrame({ wsid, name: this.name, protocols: this.protocols, permissions: [] })); }); this.tcp.on('close', function () { console.log('Connection closed'); }); }); } /** Cancel and/or terminate request by id */ cancel(requestId) { delete this.requestMap[requestId]; } waitFrame() { return __awaiter(this, void 0, void 0, function* () { if (this.supportsExtendedFrames) { // In extended mode, first read 1 byte to check frame version this.protocol.expect(1, (error, versionData) => { if (error) { return console.log('Failed waiting for frame version', error); } const versionByte = versionData.readUInt8(0); const version = (versionByte >> 4); if (version >= 2) { // Extended frame format - read remaining 4 bytes of header this.protocol.expect(4, (error, lengthData) => { if (error) { return console.log('Failed waiting for extended frame length', error); } const len = lengthData.readUInt32BE(0); if (len > this.maxFrameSize) { console.error(`Frame too large: ${len} bytes (max ${this.maxFrameSize})`); return this.waitFrame(); } this.protocol.expect(len, (error, data) => { this.waitFrame(); this.handleFrameData(data); }); }); } else { // Legacy frame format - read remaining 1 byte to complete 2-byte header this.protocol.expect(1, (error, lengthData) => { if (error) { return console.log('Failed waiting for legacy frame length', error); } const len = (versionByte << 8) | lengthData.readUInt8(0); this.protocol.expect(len, (error, data) => { this.waitFrame(); this.handleFrameData(data); }); }); } }); } else { // Legacy mode - always expect 2-byte header this.protocol.expect(2, (error, data) => { if (error) { return console.log('Failed waiting for frame header', error); } const len = data.readInt16BE(0); this.protocol.expect(len, (error, data) => { this.waitFrame(); this.handleFrameData(data); }); }); } }); } handleFrameData(data) { const msg = BSON.deserialize(data); if (msg.signal === 'ready') { if (this.state === 'connecting') { this.tcp.write(this.createFrame({ ready: true })); this.state = 'connected'; this.emit('ready', true); } return; } if (msg.type === 'frame') { this.emit('frame', peer_1.Peer.from(msg.peer), msg.data); return; } if (msg.type === 'peer') { const peer = peer_1.Peer.from(msg.peer); const url = peer.toUrl(); this.peers[url] = peer; if (peer.online) { this.emit('online', peer); } else { this.emit('offline', peer); } return; } if (msg.err || msg.sig || msg.ack) { const id = msg.err || msg.sig || msg.ack; if (this.requestMap[id]) { this.requestMap[id](msg); if (!msg.sig) { delete this.requestMap[id]; } } return; } console.log('msg', msg); } createFrame(data) { const body = BSON.serialize(data); if (this.supportsExtendedFrames && body.length > 32768) { // Use extended frame format (5-byte header) const header = Buffer.alloc(5); header.writeUInt8(0x20, 0); // Version 2, no flags header.writeUInt32BE(body.length, 1); return Buffer.concat([header, body]); } else { // Use legacy frame format (2-byte header) if (body.length > 65535) { throw new Error(`Frame too large for legacy format: ${body.length} bytes (max 65535)`); } const header = Buffer.alloc(2); header.writeInt16BE(body.length, 0); return Buffer.concat([header, body]); } } createLoginFrame(data) { // Use extended app protocol version if supported const protocolByte = this.supportsExtendedFrames ? 0x2A : 0x19; return Buffer.concat([Buffer.from(['W'.charCodeAt(0), '.'.charCodeAt(0), protocolByte]), this.createFrame(data)]); } } exports.App = App; //# sourceMappingURL=sdk.js.map