@wishcore/wish-sdk
Version:
Wish API for node. Used for building Wish Apps.
224 lines • 9.33 kB
JavaScript
"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