index.js 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546
  1. (function() {
  2. var nodeEnv = typeof require !== 'undefined' && typeof process !== 'undefined';
  3. var __module = nodeEnv ? module : {exports:{}};
  4. var __filename = 'preview-scripts/__node_modules/tsrpc-base-client/index.js';
  5. var __require = nodeEnv ? function (request) {
  6. return cc.require(request);
  7. } : function (request) {
  8. return __quick_compile_project__.require(request, __filename);
  9. };
  10. function __define (exports, require, module) {
  11. if (!nodeEnv) {__quick_compile_project__.registerModule(__filename, module);}/*!
  12. * TSRPC Base Client v2.1.15
  13. * -----------------------------------------
  14. * Copyright (c) Kingworks Corporation.
  15. * MIT License
  16. * https://github.com/k8w/tsrpc-base-client
  17. */
  18. 'use strict';
  19. Object.defineProperty(exports, '__esModule', { value: true });
  20. require('k8w-extend-native');
  21. var tslib = require('tslib');
  22. var tsbuffer = require('tsbuffer');
  23. var tsrpcProto = require('tsrpc-proto');
  24. var tsbufferSchema = require('tsbuffer-schema');
  25. /**
  26. * An auto-increment counter
  27. */
  28. var Counter = /** @class */ (function () {
  29. function Counter(min, max) {
  30. if (min === void 0) { min = 1; }
  31. if (max === void 0) { max = Number.MAX_SAFE_INTEGER; }
  32. this._min = min;
  33. this._max = max;
  34. this._last = max;
  35. }
  36. /**
  37. * Reset the counter, makes `getNext()` restart from `0`
  38. */
  39. Counter.prototype.reset = function () {
  40. this._last = this._max;
  41. };
  42. /**
  43. * Get next counter value, and auto increment `1`
  44. * @param notInc - Just get the next possible value, not actually increasing the sequence
  45. */
  46. Counter.prototype.getNext = function (notInc) {
  47. return this._last >= this._max ? (this._last = this._min) : (notInc ? this._last : ++this._last);
  48. };
  49. Object.defineProperty(Counter.prototype, "last", {
  50. /**
  51. * Last return of `getNext()`
  52. */
  53. get: function () {
  54. return this._last;
  55. },
  56. enumerable: false,
  57. configurable: true
  58. });
  59. return Counter;
  60. }());
  61. /**
  62. * A `Flow` is consists of many `FlowNode`, which is function with the same input and output (like pipeline).
  63. *
  64. * @remarks
  65. * `Flow` is like a hook or event, executed at a specific time.
  66. * The difference to event is it can be used to **interrupt** an action, by return `undefined` or `null` in a node.
  67. */
  68. var Flow = /** @class */ (function () {
  69. function Flow() {
  70. /**
  71. * All node functions, if you want to adjust the sort you can modify this.
  72. */
  73. this.nodes = [];
  74. /**
  75. * Event when error throwed from a `FlowNode` function.
  76. * By default, it does nothing except print a `Uncaught FlowError` error log.
  77. * @param e
  78. * @param last
  79. * @param input
  80. * @param logger
  81. */
  82. this.onError = function (e, last, input, logger) {
  83. logger === null || logger === void 0 ? void 0 : logger.error('Uncaught FlowError:', e);
  84. };
  85. }
  86. /**
  87. * Execute all node function one by one, the previous output is the next input,
  88. * until the last output would be return to the caller.
  89. *
  90. * @remarks
  91. * If any node function return `null | undefined`, or throws an error,
  92. * the latter node functions would not be executed.
  93. * And it would return `null | undefined` immediately to the caller,
  94. * which tell the caller it means a interruption,
  95. * to let the caller stop latter behaviours.
  96. *
  97. * @param input The input of the first `FlowNode`
  98. * @param logger Logger to print log, `undefined` means to hide all log.
  99. * @returns
  100. */
  101. Flow.prototype.exec = function (input, logger) {
  102. return tslib.__awaiter(this, void 0, void 0, function () {
  103. var res, i, e_1;
  104. return tslib.__generator(this, function (_a) {
  105. switch (_a.label) {
  106. case 0:
  107. res = input;
  108. i = 0;
  109. _a.label = 1;
  110. case 1:
  111. if (!(i < this.nodes.length)) return [3 /*break*/, 7];
  112. _a.label = 2;
  113. case 2:
  114. _a.trys.push([2, 4, , 5]);
  115. return [4 /*yield*/, this.nodes[i](res)];
  116. case 3:
  117. res = _a.sent();
  118. return [3 /*break*/, 5];
  119. case 4:
  120. e_1 = _a.sent();
  121. this.onError(e_1, res, input, logger);
  122. return [2 /*return*/, undefined];
  123. case 5:
  124. // Return 非true 表示不继续后续流程 立即中止
  125. if (res === null || res === undefined) {
  126. return [2 /*return*/, res];
  127. }
  128. _a.label = 6;
  129. case 6:
  130. ++i;
  131. return [3 /*break*/, 1];
  132. case 7: return [2 /*return*/, res];
  133. }
  134. });
  135. });
  136. };
  137. /**
  138. * Append a node function to the last
  139. * @param node
  140. * @returns
  141. */
  142. Flow.prototype.push = function (node) {
  143. this.nodes.push(node);
  144. return node;
  145. };
  146. /**
  147. * Remove a node function
  148. * @param node
  149. * @returns
  150. */
  151. Flow.prototype.remove = function (node) {
  152. return this.nodes.remove(function (v) { return v === node; });
  153. };
  154. return Flow;
  155. }());
  156. function getCustomObjectIdTypes(classObjectId) {
  157. var output = {};
  158. // string
  159. if (classObjectId === String) {
  160. output['?mongodb/ObjectId'] = {
  161. type: tsbufferSchema.SchemaType.Custom,
  162. validate: function (value) {
  163. if (typeof value !== 'string') {
  164. return { isSucc: false, errMsg: "Expected type to be `string`, actually `".concat(typeof value, "`.") };
  165. }
  166. if (!/^[0-9a-fA-F]{24}$/.test(value)) {
  167. return { isSucc: false, errMsg: 'ObjectId must be a string of 24 hex characters' };
  168. }
  169. return { isSucc: true };
  170. },
  171. encode: function (value) {
  172. return new Uint8Array(Array.from({ length: 12 }, function (_, i) { return Number.parseInt('0x' + value.substr(i * 2, 2)); }));
  173. },
  174. decode: function (buf) {
  175. return Array.from(buf, function (v) {
  176. var str = v.toString(16);
  177. if (str.length === 1) {
  178. str = '0' + str;
  179. }
  180. return str;
  181. }).join('');
  182. }
  183. };
  184. }
  185. // ObjectId
  186. else {
  187. output['?mongodb/ObjectId'] = {
  188. type: tsbufferSchema.SchemaType.Custom,
  189. validate: function (value) { return (value instanceof classObjectId) ?
  190. { isSucc: true } :
  191. { isSucc: false, errMsg: "Expected to be instance of `ObjectId`, actually not." }; },
  192. encode: function (value) { return new Uint8Array(value.id); },
  193. decode: function (buf) { return new classObjectId(buf); },
  194. decodeJSON: function (json) { return new classObjectId(json); }
  195. };
  196. }
  197. output['?mongodb/ObjectID'] = output['?mongodb/ObjectId'];
  198. output['?bson/ObjectId'] = output['?mongodb/ObjectId'];
  199. output['?bson/ObjectID'] = output['?mongodb/ObjectId'];
  200. return output;
  201. }
  202. /**
  203. * A manager for TSRPC receiving messages
  204. */
  205. var MsgHandlerManager = /** @class */ (function () {
  206. function MsgHandlerManager() {
  207. this._handlers = {};
  208. }
  209. /**
  210. * Execute all handlers parallelly
  211. * @returns handlers count
  212. */
  213. MsgHandlerManager.prototype.forEachHandler = function (msgName, logger) {
  214. var args = [];
  215. for (var _i = 2; _i < arguments.length; _i++) {
  216. args[_i - 2] = arguments[_i];
  217. }
  218. var handlers = this._handlers[msgName];
  219. if (!handlers) {
  220. return [];
  221. }
  222. var output = [];
  223. for (var _a = 0, handlers_1 = handlers; _a < handlers_1.length; _a++) {
  224. var handler = handlers_1[_a];
  225. try {
  226. output.push(handler.apply(void 0, args));
  227. }
  228. catch (e) {
  229. logger === null || logger === void 0 ? void 0 : logger.error('[MsgHandlerError]', e);
  230. }
  231. }
  232. return output;
  233. };
  234. /**
  235. * Add message handler, duplicate handlers to the same `msgName` would be ignored.
  236. * @param msgName
  237. * @param handler
  238. * @returns
  239. */
  240. MsgHandlerManager.prototype.addHandler = function (msgName, handler) {
  241. var handlers = this._handlers[msgName];
  242. // 初始化Handlers
  243. if (!handlers) {
  244. handlers = this._handlers[msgName] = [];
  245. }
  246. // 防止重复监听
  247. else if (handlers.some(function (v) { return v === handler; })) {
  248. return;
  249. }
  250. handlers.push(handler);
  251. };
  252. /**
  253. * Remove handler from the specific `msgName`
  254. * @param msgName
  255. * @param handler
  256. * @returns
  257. */
  258. MsgHandlerManager.prototype.removeHandler = function (msgName, handler) {
  259. var handlers = this._handlers[msgName];
  260. if (!handlers) {
  261. return;
  262. }
  263. handlers.removeOne(function (v) { return v === handler; });
  264. };
  265. /**
  266. * Remove all handlers for the specific `msgName`
  267. * @param msgName
  268. */
  269. MsgHandlerManager.prototype.removeAllHandlers = function (msgName) {
  270. this._handlers[msgName] = undefined;
  271. };
  272. return MsgHandlerManager;
  273. }());
  274. /** A utility for generate `ServiceMap` */
  275. var ServiceMapUtil = /** @class */ (function () {
  276. function ServiceMapUtil() {
  277. }
  278. ServiceMapUtil.getServiceMap = function (proto) {
  279. var map = {
  280. id2Service: {},
  281. apiName2Service: {},
  282. msgName2Service: {}
  283. };
  284. for (var _i = 0, _a = proto.services; _i < _a.length; _i++) {
  285. var v = _a[_i];
  286. var match = v.name.match(/(.+\/)?([^\/]+)$/);
  287. var path = match[1] || '';
  288. var name_1 = match[2];
  289. if (v.type === 'api') {
  290. var svc = tslib.__assign(tslib.__assign({}, v), { reqSchemaId: "".concat(path, "Ptl").concat(name_1, "/Req").concat(name_1), resSchemaId: "".concat(path, "Ptl").concat(name_1, "/Res").concat(name_1) });
  291. map.apiName2Service[v.name] = svc;
  292. map.id2Service[v.id] = svc;
  293. }
  294. else {
  295. var svc = tslib.__assign(tslib.__assign({}, v), { msgSchemaId: "".concat(path, "Msg").concat(name_1, "/Msg").concat(name_1) });
  296. map.msgName2Service[v.name] = svc;
  297. map.id2Service[v.id] = svc;
  298. }
  299. }
  300. return map;
  301. };
  302. return ServiceMapUtil;
  303. }());
  304. var TransportDataUtil = /** @class */ (function () {
  305. function TransportDataUtil() {
  306. }
  307. Object.defineProperty(TransportDataUtil, "tsbuffer", {
  308. get: function () {
  309. if (!this._tsbuffer) {
  310. this._tsbuffer = new tsbuffer.TSBuffer(tsrpcProto.TransportDataProto);
  311. }
  312. return this._tsbuffer;
  313. },
  314. enumerable: false,
  315. configurable: true
  316. });
  317. TransportDataUtil.encodeClientMsg = function (tsbuffer, service, msg, type, connType) {
  318. if (type === 'buffer') {
  319. var op = tsbuffer.encode(msg, service.msgSchemaId);
  320. if (!op.isSucc) {
  321. return op;
  322. }
  323. var serverInputData = {
  324. serviceId: service.id,
  325. buffer: op.buf
  326. };
  327. var opOut = this.tsbuffer.encode(serverInputData, 'ServerInputData');
  328. return opOut.isSucc ? { isSucc: true, output: opOut.buf } : { isSucc: false, errMsg: opOut.errMsg };
  329. }
  330. else {
  331. var op = tsbuffer.encodeJSON(msg, service.msgSchemaId);
  332. if (!op.isSucc) {
  333. return op;
  334. }
  335. var json = connType === 'SHORT' ? op.json : [service.name, op.json];
  336. return { isSucc: true, output: type === 'json' ? json : JSON.stringify(json) };
  337. }
  338. };
  339. TransportDataUtil.encodeApiReq = function (tsbuffer, service, req, type, sn) {
  340. if (type === 'buffer') {
  341. var op = tsbuffer.encode(req, service.reqSchemaId);
  342. if (!op.isSucc) {
  343. return op;
  344. }
  345. var serverInputData = {
  346. serviceId: service.id,
  347. buffer: op.buf,
  348. sn: sn
  349. };
  350. var opOut = this.tsbuffer.encode(serverInputData, 'ServerInputData');
  351. return opOut.isSucc ? { isSucc: true, output: opOut.buf } : { isSucc: false, errMsg: opOut.errMsg };
  352. }
  353. else {
  354. var op = tsbuffer.encodeJSON(req, service.reqSchemaId);
  355. if (!op.isSucc) {
  356. return op;
  357. }
  358. var json = sn === undefined ? op.json : [service.name, op.json, sn];
  359. return { isSucc: true, output: type === 'json' ? json : JSON.stringify(json) };
  360. }
  361. };
  362. TransportDataUtil.encodeServerMsg = function (tsbuffer, service, msg, type, connType) {
  363. if (type === 'buffer') {
  364. var op = tsbuffer.encode(msg, service.msgSchemaId);
  365. if (!op.isSucc) {
  366. return op;
  367. }
  368. var serverOutputData = {
  369. serviceId: service.id,
  370. buffer: op.buf
  371. };
  372. var opOut = this.tsbuffer.encode(serverOutputData, 'ServerOutputData');
  373. return opOut.isSucc ? { isSucc: true, output: opOut.buf } : { isSucc: false, errMsg: opOut.errMsg };
  374. }
  375. else {
  376. var op = tsbuffer.encodeJSON(msg, service.msgSchemaId);
  377. if (!op.isSucc) {
  378. return op;
  379. }
  380. var json = connType === 'SHORT' ? op.json : [service.name, op.json];
  381. return { isSucc: true, output: type === 'json' ? json : JSON.stringify(json) };
  382. }
  383. };
  384. TransportDataUtil.parseServerOutout = function (tsbuffer, serviceMap, data, serviceId) {
  385. if (data instanceof Uint8Array) {
  386. var opServerOutputData = this.tsbuffer.decode(data, 'ServerOutputData');
  387. if (!opServerOutputData.isSucc) {
  388. return opServerOutputData;
  389. }
  390. var serverOutputData = opServerOutputData.value;
  391. serviceId = serviceId !== null && serviceId !== void 0 ? serviceId : serverOutputData.serviceId;
  392. if (serviceId === undefined) {
  393. return { isSucc: false, errMsg: "Missing 'serviceId' in ServerOutput" };
  394. }
  395. var service = serviceMap.id2Service[serviceId];
  396. if (!service) {
  397. return { isSucc: false, errMsg: "Invalid service ID: ".concat(serviceId, " (from ServerOutput)") };
  398. }
  399. if (service.type === 'msg') {
  400. if (!serverOutputData.buffer) {
  401. return { isSucc: false, errMsg: 'Empty msg buffer (from ServerOutput)' };
  402. }
  403. var opMsg = tsbuffer.decode(serverOutputData.buffer, service.msgSchemaId);
  404. if (!opMsg.isSucc) {
  405. return opMsg;
  406. }
  407. return {
  408. isSucc: true,
  409. result: {
  410. type: 'msg',
  411. service: service,
  412. msg: opMsg.value
  413. }
  414. };
  415. }
  416. else {
  417. if (serverOutputData.error) {
  418. return {
  419. isSucc: true,
  420. result: {
  421. type: 'api',
  422. service: service,
  423. sn: serverOutputData.sn,
  424. ret: {
  425. isSucc: false,
  426. err: new tsrpcProto.TsrpcError(serverOutputData.error)
  427. }
  428. }
  429. };
  430. }
  431. else {
  432. if (!serverOutputData.buffer) {
  433. return { isSucc: false, errMsg: 'Empty API res buffer (from ServerOutput)' };
  434. }
  435. var opRes = tsbuffer.decode(serverOutputData.buffer, service.resSchemaId);
  436. if (!opRes.isSucc) {
  437. return opRes;
  438. }
  439. return {
  440. isSucc: true,
  441. result: {
  442. type: 'api',
  443. service: service,
  444. sn: serverOutputData.sn,
  445. ret: {
  446. isSucc: true,
  447. res: opRes.value,
  448. }
  449. }
  450. };
  451. }
  452. }
  453. }
  454. else {
  455. var json = void 0;
  456. if (typeof data === 'string') {
  457. try {
  458. json = JSON.parse(data);
  459. }
  460. catch (e) {
  461. return { isSucc: false, errMsg: "Invalid input JSON: ".concat(e.message) };
  462. }
  463. }
  464. else {
  465. json = data;
  466. }
  467. var body = void 0;
  468. var sn = void 0;
  469. var service = void 0;
  470. if (serviceId == undefined) {
  471. if (!Array.isArray(json)) {
  472. return { isSucc: false, errMsg: "Invalid server output format" };
  473. }
  474. var serviceName = json[0];
  475. body = json[1];
  476. sn = json[2];
  477. // 有 SN 是 Api,没 SN 是 Msg
  478. service = sn ? serviceMap.apiName2Service[serviceName] : serviceMap.msgName2Service[serviceName];
  479. if (!service) {
  480. return { isSucc: false, errMsg: "Invalid service name: ".concat(serviceName, " (from ServerOutputData)") };
  481. }
  482. }
  483. else {
  484. service = serviceMap.id2Service[serviceId];
  485. if (!service) {
  486. return { isSucc: false, errMsg: "Invalid service ID: ".concat(serviceId) };
  487. }
  488. body = json;
  489. }
  490. if (service.type === 'api') {
  491. if (body.isSucc && 'res' in body) {
  492. var op = tsbuffer.decodeJSON(body.res, service.resSchemaId);
  493. if (!op.isSucc) {
  494. return op;
  495. }
  496. body.res = op.value;
  497. }
  498. else if (body.err) {
  499. body.err = new tsrpcProto.TsrpcError(body.err);
  500. }
  501. else {
  502. return { isSucc: false, errMsg: "Invalid server output format" };
  503. }
  504. return {
  505. isSucc: true,
  506. result: {
  507. type: 'api',
  508. service: service,
  509. sn: sn,
  510. ret: body
  511. }
  512. };
  513. }
  514. else {
  515. var op = tsbuffer.decodeJSON(body, service.msgSchemaId);
  516. if (!op.isSucc) {
  517. return op;
  518. }
  519. return {
  520. isSucc: true,
  521. result: {
  522. type: 'msg',
  523. service: service,
  524. msg: op.value
  525. }
  526. };
  527. }
  528. }
  529. };
  530. // 心跳包(Ping & Pong),所有开头为 0 的 Buffer,均为控制指令
  531. TransportDataUtil.HeartbeatPacket = new Uint8Array([0]);
  532. return TransportDataUtil;
  533. }());
  534. /**
  535. * An abstract base class for TSRPC Client,
  536. * which includes some common buffer process flows.
  537. *
  538. * @remarks
  539. * You can implement a client on a specific transportation protocol (like HTTP, WebSocket, QUIP) by extend this.
  540. *
  541. * @typeParam ServiceType - `ServiceType` from generated `proto.ts`
  542. *
  543. * @see
  544. * {@link https://github.com/k8w/tsrpc}
  545. * {@link https://github.com/k8w/tsrpc-browser}
  546. * {@link https://github.com/k8w/tsrpc-miniapp}
  547. */
  548. var BaseClient = /** @class */ (function () {
  549. function BaseClient(proto, options) {
  550. this._msgHandlers = new MsgHandlerManager();
  551. /**
  552. * {@link Flow} to process `callApi`, `sendMsg`, buffer input/output, etc...
  553. */
  554. this.flows = {
  555. // callApi
  556. preCallApiFlow: new Flow(),
  557. preApiReturnFlow: new Flow(),
  558. postApiReturnFlow: new Flow(),
  559. // sendMsg
  560. preSendMsgFlow: new Flow(),
  561. postSendMsgFlow: new Flow(),
  562. preRecvMsgFlow: new Flow(),
  563. postRecvMsgFlow: new Flow(),
  564. // buffer
  565. preSendDataFlow: new Flow(),
  566. preRecvDataFlow: new Flow(),
  567. /**
  568. * @deprecated Please use `preSendDataFlow` instead
  569. */
  570. preSendBufferFlow: new Flow(),
  571. /**
  572. * @deprecated Please use `preRecvDataFlow` instead
  573. */
  574. preRecvBufferFlow: new Flow(),
  575. // Connection Flows (Only for WebSocket)
  576. /** Before connect to WebSocket server */
  577. preConnectFlow: new Flow(),
  578. /** After WebSocket connect successfully */
  579. postConnectFlow: new Flow(),
  580. /** After WebSocket disconnected (from connected status) */
  581. postDisconnectFlow: new Flow(),
  582. };
  583. this._apiSnCounter = new Counter(1);
  584. /**
  585. * Pending API Requests
  586. */
  587. this._pendingApis = [];
  588. /** @deprecated Please use `_onRecvData` instead */
  589. this._onRecvBuf = this._onRecvData;
  590. this.options = options;
  591. this.serviceMap = ServiceMapUtil.getServiceMap(proto);
  592. this.dataType = this.options.json ? 'text' : 'buffer';
  593. var types = tslib.__assign({}, proto.types);
  594. // Custom ObjectId handler
  595. if (options.customObjectIdClass) {
  596. types = tslib.__assign(tslib.__assign({}, types), getCustomObjectIdTypes(options.customObjectIdClass));
  597. }
  598. this.tsbuffer = new tsbuffer.TSBuffer(types);
  599. this.logger = this.options.logger;
  600. if (this.logger) {
  601. this.logger = tsrpcProto.setLogLevel(this.logger, this.options.logLevel);
  602. }
  603. }
  604. Object.defineProperty(BaseClient.prototype, "lastSN", {
  605. /**
  606. * The `SN` number of the last `callApi()`,
  607. * which can be passed to `abort()` to abort an API request.
  608. * @example
  609. * ```ts
  610. * client.callApi('xxx', { value: 'xxx' })
  611. * .then(ret=>{ console.log('succ', ret) });
  612. * let lastSN = client.lastSN;
  613. * client.abort(lastSN);
  614. * ```
  615. */
  616. get: function () {
  617. return this._apiSnCounter.last;
  618. },
  619. enumerable: false,
  620. configurable: true
  621. });
  622. Object.defineProperty(BaseClient.prototype, "nextSN", {
  623. /**
  624. * The `SN` number of the next `callApi()`,
  625. * which can be passed to `abort()` to abort an API request.
  626. * @example
  627. * ```ts
  628. * let nextSN = client.nextSN;
  629. * client.callApi('xxx', { value: 'xxx' })
  630. * ```
  631. */
  632. get: function () {
  633. return this._apiSnCounter.getNext(true);
  634. },
  635. enumerable: false,
  636. configurable: true
  637. });
  638. /**
  639. * Send request and wait for the return
  640. * @param apiName
  641. * @param req - Request body
  642. * @param options - Transport options
  643. * @returns return a `ApiReturn`, all error (network error, business error, code exception...) is unified as `TsrpcError`.
  644. * The promise is never rejected, so you just need to process all error in one place.
  645. */
  646. BaseClient.prototype.callApi = function (apiName, req, options) {
  647. if (options === void 0) { options = {}; }
  648. return tslib.__awaiter(this, void 0, void 0, function () {
  649. var sn, pendingItem, promise;
  650. var _this = this;
  651. return tslib.__generator(this, function (_a) {
  652. sn = this._apiSnCounter.getNext();
  653. pendingItem = {
  654. sn: sn,
  655. abortKey: options.abortKey,
  656. service: this.serviceMap.apiName2Service[apiName]
  657. };
  658. this._pendingApis.push(pendingItem);
  659. promise = new Promise(function (rs) { return tslib.__awaiter(_this, void 0, void 0, function () {
  660. var pre, ret, preReturn;
  661. var _a, _b;
  662. return tslib.__generator(this, function (_c) {
  663. switch (_c.label) {
  664. case 0: return [4 /*yield*/, this.flows.preCallApiFlow.exec({
  665. apiName: apiName,
  666. req: req,
  667. options: options
  668. }, this.logger)];
  669. case 1:
  670. pre = _c.sent();
  671. if (!pre || pendingItem.isAborted) {
  672. this.abort(pendingItem.sn);
  673. return [2 /*return*/];
  674. }
  675. if (!pre.return) return [3 /*break*/, 2];
  676. ret = pre.return;
  677. return [3 /*break*/, 4];
  678. case 2: return [4 /*yield*/, this._doCallApi(pre.apiName, pre.req, pre.options, pendingItem)];
  679. case 3:
  680. // do call means it will send buffer via network
  681. ret = _c.sent();
  682. _c.label = 4;
  683. case 4:
  684. if (pendingItem.isAborted) {
  685. return [2 /*return*/];
  686. }
  687. // Log Original Return
  688. if (ret.isSucc) {
  689. this.options.logApi && ((_a = this.logger) === null || _a === void 0 ? void 0 : _a.log("[ApiRes] #".concat(pendingItem.sn, " ").concat(apiName), ret.res));
  690. }
  691. else {
  692. this.options.logApi && ((_b = this.logger) === null || _b === void 0 ? void 0 : _b[ret.err.type === tsrpcProto.TsrpcError.Type.ApiError ? 'log' : 'error']("[ApiErr] #".concat(pendingItem.sn, " ").concat(apiName), ret.err));
  693. }
  694. return [4 /*yield*/, this.flows.preApiReturnFlow.exec(tslib.__assign(tslib.__assign({}, pre), { return: ret }), this.logger)];
  695. case 5:
  696. preReturn = _c.sent();
  697. if (!preReturn) {
  698. this.abort(pendingItem.sn);
  699. return [2 /*return*/];
  700. }
  701. rs(preReturn.return);
  702. // Post Flow
  703. this.flows.postApiReturnFlow.exec(preReturn, this.logger);
  704. return [2 /*return*/];
  705. }
  706. });
  707. }); });
  708. // Finally clear pendings
  709. promise.catch().then(function () {
  710. _this._pendingApis.removeOne(function (v) { return v.sn === pendingItem.sn; });
  711. });
  712. return [2 /*return*/, promise];
  713. });
  714. });
  715. };
  716. BaseClient.prototype._doCallApi = function (apiName, req, options, pendingItem) {
  717. var _a;
  718. if (options === void 0) { options = {}; }
  719. return tslib.__awaiter(this, void 0, void 0, function () {
  720. var promise;
  721. var _this = this;
  722. return tslib.__generator(this, function (_b) {
  723. this.options.logApi && ((_a = this.logger) === null || _a === void 0 ? void 0 : _a.log("[ApiReq] #".concat(pendingItem.sn), apiName, req));
  724. promise = new Promise(function (rs) { return tslib.__awaiter(_this, void 0, void 0, function () {
  725. var service, opEncode, promiseReturn, promiseSend, opSend, ret;
  726. var _a;
  727. return tslib.__generator(this, function (_b) {
  728. switch (_b.label) {
  729. case 0:
  730. service = this.serviceMap.apiName2Service[apiName];
  731. if (!service) {
  732. rs({
  733. isSucc: false,
  734. err: new tsrpcProto.TsrpcError('Invalid api name: ' + apiName, {
  735. code: 'INVALID_API_NAME',
  736. type: tsrpcProto.TsrpcErrorType.ClientError
  737. })
  738. });
  739. return [2 /*return*/];
  740. }
  741. pendingItem.service = service;
  742. opEncode = TransportDataUtil.encodeApiReq(this.tsbuffer, service, req, this.dataType, this.type === 'LONG' ? pendingItem.sn : undefined);
  743. if (!opEncode.isSucc) {
  744. rs({
  745. isSucc: false, err: new tsrpcProto.TsrpcError(opEncode.errMsg, {
  746. type: tsrpcProto.TsrpcErrorType.ClientError,
  747. code: 'INPUT_DATA_ERR'
  748. })
  749. });
  750. return [2 /*return*/];
  751. }
  752. promiseReturn = this._waitApiReturn(pendingItem, (_a = options.timeout) !== null && _a !== void 0 ? _a : this.options.timeout);
  753. promiseSend = this.sendData(opEncode.output, options, service.id, pendingItem);
  754. return [4 /*yield*/, promiseSend];
  755. case 1:
  756. opSend = _b.sent();
  757. if (opSend.err) {
  758. rs({
  759. isSucc: false,
  760. err: opSend.err
  761. });
  762. return [2 /*return*/];
  763. }
  764. return [4 /*yield*/, promiseReturn];
  765. case 2:
  766. ret = _b.sent();
  767. if (pendingItem.isAborted) {
  768. return [2 /*return*/];
  769. }
  770. rs(ret);
  771. return [2 /*return*/];
  772. }
  773. });
  774. }); });
  775. return [2 /*return*/, promise];
  776. });
  777. });
  778. };
  779. /**
  780. * Send message, without response, not ensuring the server is received and processed correctly.
  781. * @param msgName
  782. * @param msg - Message body
  783. * @param options - Transport options
  784. * @returns If the promise is resolved, it means the request is sent to system kernel successfully.
  785. * Notice that not means the server received and processed the message correctly.
  786. */
  787. BaseClient.prototype.sendMsg = function (msgName, msg, options) {
  788. var _this = this;
  789. if (options === void 0) { options = {}; }
  790. var promise = new Promise(function (rs) { return tslib.__awaiter(_this, void 0, void 0, function () {
  791. var pre, service, opEncode, promiseSend, opSend;
  792. var _a, _b;
  793. return tslib.__generator(this, function (_c) {
  794. switch (_c.label) {
  795. case 0: return [4 /*yield*/, this.flows.preSendMsgFlow.exec({
  796. msgName: msgName,
  797. msg: msg,
  798. options: options
  799. }, this.logger)];
  800. case 1:
  801. pre = _c.sent();
  802. if (!pre) {
  803. return [2 /*return*/];
  804. }
  805. // The msg is not prevented by pre flow
  806. this.options.logMsg && ((_a = this.logger) === null || _a === void 0 ? void 0 : _a.log("[SendMsg]", msgName, msg));
  807. service = this.serviceMap.msgName2Service[msgName];
  808. if (!service) {
  809. (_b = this.logger) === null || _b === void 0 ? void 0 : _b.error('Invalid msg name: ' + msgName);
  810. rs({
  811. isSucc: false,
  812. err: new tsrpcProto.TsrpcError('Invalid msg name: ' + msgName, {
  813. code: 'INVALID_MSG_NAME',
  814. type: tsrpcProto.TsrpcErrorType.ClientError
  815. })
  816. });
  817. return [2 /*return*/];
  818. }
  819. opEncode = TransportDataUtil.encodeClientMsg(this.tsbuffer, service, msg, this.dataType, this.type);
  820. if (!opEncode.isSucc) {
  821. rs({
  822. isSucc: false,
  823. err: new tsrpcProto.TsrpcError(opEncode.errMsg, {
  824. type: tsrpcProto.TsrpcErrorType.ClientError,
  825. code: 'ENCODE_MSG_ERR'
  826. })
  827. });
  828. return [2 /*return*/];
  829. }
  830. promiseSend = this.sendData(opEncode.output, options, service.id);
  831. return [4 /*yield*/, promiseSend];
  832. case 2:
  833. opSend = _c.sent();
  834. if (opSend.err) {
  835. rs({
  836. isSucc: false,
  837. err: opSend.err
  838. });
  839. return [2 /*return*/];
  840. }
  841. rs({ isSucc: true });
  842. // Post Flow
  843. this.flows.postSendMsgFlow.exec(pre, this.logger);
  844. return [2 /*return*/];
  845. }
  846. });
  847. }); });
  848. promise.then(function (v) {
  849. var _a;
  850. if (!v.isSucc) {
  851. ((_a = _this.logger) !== null && _a !== void 0 ? _a : console).error('[SendMsgErr]', v.err);
  852. }
  853. });
  854. return promise;
  855. };
  856. /**
  857. * Add a message handler,
  858. * duplicate handlers to the same `msgName` would be ignored.
  859. * @param msgName
  860. * @param handler
  861. * @returns
  862. */
  863. // listenMsg<T extends keyof ServiceType['msg']>(msgName: T, handler: ClientMsgHandler<ServiceType, T, this>): ClientMsgHandler<ServiceType, T, this>;
  864. // listenMsg(msgName: RegExp, handler: ClientMsgHandler<ServiceType, keyof ServiceType['msg'], this>): ClientMsgHandler<ServiceType, keyof ServiceType['msg'], this>;
  865. // listenMsg(msgName: string | RegExp, handler: ClientMsgHandler<ServiceType, string, this>): ClientMsgHandler<ServiceType, string, this> {
  866. BaseClient.prototype.listenMsg = function (msgName, handler) {
  867. var _this = this;
  868. if (msgName instanceof RegExp) {
  869. Object.keys(this.serviceMap.msgName2Service).filter(function (k) { return msgName.test(k); }).forEach(function (k) {
  870. _this._msgHandlers.addHandler(k, handler);
  871. });
  872. }
  873. else {
  874. this._msgHandlers.addHandler(msgName, handler);
  875. }
  876. return handler;
  877. };
  878. /**
  879. * Remove a message handler
  880. */
  881. BaseClient.prototype.unlistenMsg = function (msgName, handler) {
  882. var _this = this;
  883. if (msgName instanceof RegExp) {
  884. Object.keys(this.serviceMap.msgName2Service).filter(function (k) { return msgName.test(k); }).forEach(function (k) {
  885. _this._msgHandlers.removeHandler(k, handler);
  886. });
  887. }
  888. else {
  889. this._msgHandlers.removeHandler(msgName, handler);
  890. }
  891. };
  892. /**
  893. * Remove all handlers from a message
  894. */
  895. BaseClient.prototype.unlistenMsgAll = function (msgName) {
  896. var _this = this;
  897. if (msgName instanceof RegExp) {
  898. Object.keys(this.serviceMap.msgName2Service).filter(function (k) { return msgName.test(k); }).forEach(function (k) {
  899. _this._msgHandlers.removeAllHandlers(k);
  900. });
  901. }
  902. else {
  903. this._msgHandlers.removeAllHandlers(msgName);
  904. }
  905. };
  906. /**
  907. * Abort a pending API request, it makes the promise returned by `callApi()` neither resolved nor rejected forever.
  908. * @param sn - Every api request has a unique `sn` number, you can get it by `this.lastSN`
  909. */
  910. BaseClient.prototype.abort = function (sn) {
  911. var _a, _b;
  912. // Find
  913. var index = this._pendingApis.findIndex(function (v) { return v.sn === sn; });
  914. if (index === -1) {
  915. return;
  916. }
  917. var pendingItem = this._pendingApis[index];
  918. // Clear
  919. this._pendingApis.splice(index, 1);
  920. pendingItem.onReturn = undefined;
  921. pendingItem.isAborted = true;
  922. // Log
  923. (_a = this.logger) === null || _a === void 0 ? void 0 : _a.log("[ApiAbort] #".concat(pendingItem.sn, " ").concat(pendingItem.service.name));
  924. // onAbort
  925. (_b = pendingItem.onAbort) === null || _b === void 0 ? void 0 : _b.call(pendingItem);
  926. };
  927. /**
  928. * Abort all API requests that has the `abortKey`.
  929. * It makes the promise returned by `callApi` neither resolved nor rejected forever.
  930. * @param abortKey - The `abortKey` of options when `callApi()`, see {@link TransportOptions.abortKey}.
  931. * @example
  932. * ```ts
  933. * // Send API request many times
  934. * client.callApi('SendData', { data: 'AAA' }, { abortKey: 'Session#123' });
  935. * client.callApi('SendData', { data: 'BBB' }, { abortKey: 'Session#123' });
  936. * client.callApi('SendData', { data: 'CCC' }, { abortKey: 'Session#123' });
  937. *
  938. * // And abort the at once
  939. * client.abortByKey('Session#123');
  940. * ```
  941. */
  942. BaseClient.prototype.abortByKey = function (abortKey) {
  943. var _this = this;
  944. this._pendingApis.filter(function (v) { return v.abortKey === abortKey; }).forEach(function (v) { _this.abort(v.sn); });
  945. };
  946. /**
  947. * Abort all pending API requests.
  948. * It makes the promise returned by `callApi` neither resolved nor rejected forever.
  949. */
  950. BaseClient.prototype.abortAll = function () {
  951. var _this = this;
  952. this._pendingApis.slice().forEach(function (v) { return _this.abort(v.sn); });
  953. };
  954. /**
  955. * Send data (binary or text)
  956. * @remarks
  957. * Long connection: wait res by listenning `conn.onmessage`
  958. * Short connection: wait res by waitting response
  959. * @param data
  960. * @param options
  961. * @param sn
  962. */
  963. BaseClient.prototype.sendData = function (data, options, serviceId, pendingApiItem) {
  964. var _a, _b, _c;
  965. return tslib.__awaiter(this, void 0, void 0, function () {
  966. var pre, preBuf;
  967. return tslib.__generator(this, function (_d) {
  968. switch (_d.label) {
  969. case 0: return [4 /*yield*/, this.flows.preSendDataFlow.exec({ data: data, sn: pendingApiItem === null || pendingApiItem === void 0 ? void 0 : pendingApiItem.sn }, this.logger)];
  970. case 1:
  971. pre = _d.sent();
  972. if (!pre) {
  973. return [2 /*return*/, new Promise(function (rs) { })];
  974. }
  975. data = pre.data;
  976. if (!(data instanceof Uint8Array)) return [3 /*break*/, 3];
  977. return [4 /*yield*/, this.flows.preSendBufferFlow.exec({ buf: data, sn: pendingApiItem === null || pendingApiItem === void 0 ? void 0 : pendingApiItem.sn }, this.logger)];
  978. case 2:
  979. preBuf = _d.sent();
  980. if (!preBuf) {
  981. return [2 /*return*/, new Promise(function (rs) { })];
  982. }
  983. data = preBuf.buf;
  984. _d.label = 3;
  985. case 3:
  986. // debugBuf log
  987. if (this.options.debugBuf) {
  988. if (typeof data === 'string') {
  989. (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('[SendText]' + (pendingApiItem ? (' #' + pendingApiItem.sn) : '') + " length=".concat(data.length), data);
  990. }
  991. else if (data instanceof Uint8Array) {
  992. (_b = this.logger) === null || _b === void 0 ? void 0 : _b.debug('[SendBuf]' + (pendingApiItem ? (' #' + pendingApiItem.sn) : '') + " length=".concat(data.length), data);
  993. }
  994. else {
  995. (_c = this.logger) === null || _c === void 0 ? void 0 : _c.debug('[SendJSON]' + (pendingApiItem ? (' #' + pendingApiItem.sn) : ''), data);
  996. }
  997. }
  998. return [2 /*return*/, this._sendData(data, options, serviceId, pendingApiItem)];
  999. }
  1000. });
  1001. });
  1002. };
  1003. // 信道可传输二进制或字符串
  1004. BaseClient.prototype._onRecvData = function (data, pendingApiItem) {
  1005. var _a, _b, _c, _d, _e, _f, _g, _h, _j;
  1006. return tslib.__awaiter(this, void 0, void 0, function () {
  1007. var sn, pre, pre_1, opParsed, parsed, pre_2;
  1008. return tslib.__generator(this, function (_k) {
  1009. switch (_k.label) {
  1010. case 0:
  1011. sn = pendingApiItem === null || pendingApiItem === void 0 ? void 0 : pendingApiItem.sn;
  1012. return [4 /*yield*/, this.flows.preRecvDataFlow.exec({ data: data, sn: sn }, this.logger)];
  1013. case 1:
  1014. pre = _k.sent();
  1015. if (!pre) {
  1016. return [2 /*return*/];
  1017. }
  1018. data = pre.data;
  1019. if (!(typeof data === 'string')) return [3 /*break*/, 2];
  1020. this.options.debugBuf && ((_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('[RecvText]' + (sn ? (' #' + sn) : ''), data));
  1021. return [3 /*break*/, 5];
  1022. case 2:
  1023. if (!(data instanceof Uint8Array)) return [3 /*break*/, 4];
  1024. this.options.debugBuf && ((_b = this.logger) === null || _b === void 0 ? void 0 : _b.debug('[RecvBuf]' + (sn ? (' #' + sn) : ''), 'length=' + data.length, data));
  1025. return [4 /*yield*/, this.flows.preRecvBufferFlow.exec({ buf: data, sn: sn }, this.logger)];
  1026. case 3:
  1027. pre_1 = _k.sent();
  1028. if (!pre_1) {
  1029. return [2 /*return*/];
  1030. }
  1031. data = pre_1.buf;
  1032. return [3 /*break*/, 5];
  1033. case 4:
  1034. this.options.debugBuf && ((_c = this.logger) === null || _c === void 0 ? void 0 : _c.debug('[RecvJSON]' + (sn ? (' #' + sn) : ''), data));
  1035. _k.label = 5;
  1036. case 5:
  1037. opParsed = TransportDataUtil.parseServerOutout(this.tsbuffer, this.serviceMap, data, pendingApiItem === null || pendingApiItem === void 0 ? void 0 : pendingApiItem.service.id);
  1038. if (!opParsed.isSucc) {
  1039. (_d = this.logger) === null || _d === void 0 ? void 0 : _d.error('ParseServerOutputError: ' + opParsed.errMsg);
  1040. if (data instanceof Uint8Array) {
  1041. (_e = this.logger) === null || _e === void 0 ? void 0 : _e.error('Please check the version of serviceProto between server and client');
  1042. }
  1043. if (pendingApiItem) {
  1044. (_f = pendingApiItem.onReturn) === null || _f === void 0 ? void 0 : _f.call(pendingApiItem, {
  1045. isSucc: false,
  1046. err: new tsrpcProto.TsrpcError('Parse server output error', { type: tsrpcProto.TsrpcErrorType.ServerError })
  1047. });
  1048. }
  1049. return [2 /*return*/];
  1050. }
  1051. parsed = opParsed.result;
  1052. if (!(parsed.type === 'api')) return [3 /*break*/, 6];
  1053. sn = sn !== null && sn !== void 0 ? sn : parsed.sn;
  1054. // call ApiReturn listeners
  1055. (_h = (_g = this._pendingApis.find(function (v) { return v.sn === sn; })) === null || _g === void 0 ? void 0 : _g.onReturn) === null || _h === void 0 ? void 0 : _h.call(_g, parsed.ret);
  1056. return [3 /*break*/, 9];
  1057. case 6:
  1058. if (!(parsed.type === 'msg')) return [3 /*break*/, 9];
  1059. this.options.logMsg && ((_j = this.logger) === null || _j === void 0 ? void 0 : _j.log("[RecvMsg] ".concat(parsed.service.name), parsed.msg));
  1060. return [4 /*yield*/, this.flows.preRecvMsgFlow.exec({ msgName: parsed.service.name, msg: parsed.msg }, this.logger)];
  1061. case 7:
  1062. pre_2 = _k.sent();
  1063. if (!pre_2) {
  1064. return [2 /*return*/];
  1065. }
  1066. this._msgHandlers.forEachHandler(pre_2.msgName, this.logger, pre_2.msg, pre_2.msgName);
  1067. // Post Flow
  1068. return [4 /*yield*/, this.flows.postRecvMsgFlow.exec(pre_2, this.logger)];
  1069. case 8:
  1070. // Post Flow
  1071. _k.sent();
  1072. _k.label = 9;
  1073. case 9: return [2 /*return*/];
  1074. }
  1075. });
  1076. });
  1077. };
  1078. /**
  1079. * @param sn
  1080. * @param timeout
  1081. * @returns `undefined` 代表 canceled
  1082. */
  1083. BaseClient.prototype._waitApiReturn = function (pendingItem, timeout) {
  1084. return tslib.__awaiter(this, void 0, void 0, function () {
  1085. var _this = this;
  1086. return tslib.__generator(this, function (_a) {
  1087. return [2 /*return*/, new Promise(function (rs) {
  1088. // Timeout
  1089. var timer;
  1090. if (timeout) {
  1091. timer = setTimeout(function () {
  1092. timer = undefined;
  1093. _this._pendingApis.removeOne(function (v) { return v.sn === pendingItem.sn; });
  1094. rs({
  1095. isSucc: false,
  1096. err: new tsrpcProto.TsrpcError('Request Timeout', {
  1097. type: tsrpcProto.TsrpcErrorType.NetworkError,
  1098. code: 'TIMEOUT'
  1099. })
  1100. });
  1101. }, timeout);
  1102. }
  1103. // Listener (trigger by `this._onRecvBuf`)
  1104. pendingItem.onReturn = function (ret) {
  1105. if (timer) {
  1106. clearTimeout(timer);
  1107. timer = undefined;
  1108. }
  1109. _this._pendingApis.removeOne(function (v) { return v.sn === pendingItem.sn; });
  1110. rs(ret);
  1111. };
  1112. })];
  1113. });
  1114. });
  1115. };
  1116. return BaseClient;
  1117. }());
  1118. var defaultBaseClientOptions = {
  1119. logLevel: 'debug',
  1120. logApi: true,
  1121. logMsg: true,
  1122. json: false,
  1123. timeout: 15000,
  1124. debugBuf: false
  1125. };
  1126. /**
  1127. * Base HTTP Client
  1128. */
  1129. var BaseHttpClient = /** @class */ (function (_super) {
  1130. tslib.__extends(BaseHttpClient, _super);
  1131. function BaseHttpClient(proto, http, options) {
  1132. var _this = this;
  1133. var _a;
  1134. _this = _super.call(this, proto, tslib.__assign(tslib.__assign({}, defaultBaseHttpClientOptions), options)) || this;
  1135. _this.type = 'SHORT';
  1136. _this._http = http;
  1137. _this._jsonServer = _this.options.server + (_this.options.server.endsWith('/') ? '' : '/');
  1138. (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.log('TSRPC HTTP Client :', _this.options.server);
  1139. return _this;
  1140. }
  1141. BaseHttpClient.prototype._sendData = function (data, options, serviceId, pendingApiItem) {
  1142. return tslib.__awaiter(this, void 0, void 0, function () {
  1143. var promise;
  1144. var _this = this;
  1145. return tslib.__generator(this, function (_a) {
  1146. promise = (function () { return tslib.__awaiter(_this, void 0, void 0, function () {
  1147. var service, urlSearch, url, _a, fetchPromise, abort, fetchRes;
  1148. return tslib.__generator(this, function (_b) {
  1149. switch (_b.label) {
  1150. case 0:
  1151. service = this.serviceMap.id2Service[serviceId];
  1152. urlSearch = service.type === 'msg' ? '?type=msg' : '';
  1153. url = typeof data === 'string' ? (this._jsonServer + service.name + urlSearch) : this.options.server;
  1154. _a = this._http.fetch({
  1155. url: url,
  1156. data: data,
  1157. method: 'POST',
  1158. timeout: options.timeout || this.options.timeout,
  1159. headers: { 'Content-Type': typeof data === 'string' ? 'application/json' : 'application/octet-stream' },
  1160. transportOptions: options,
  1161. responseType: typeof data === 'string' ? 'text' : 'arraybuffer',
  1162. }), fetchPromise = _a.promise, abort = _a.abort;
  1163. if (pendingApiItem) {
  1164. pendingApiItem.onAbort = function () {
  1165. abort();
  1166. };
  1167. }
  1168. // Aborted
  1169. if (pendingApiItem === null || pendingApiItem === void 0 ? void 0 : pendingApiItem.isAborted) {
  1170. return [2 /*return*/, new Promise(function (rs) { })];
  1171. }
  1172. return [4 /*yield*/, fetchPromise];
  1173. case 1:
  1174. fetchRes = _b.sent();
  1175. if (!fetchRes.isSucc) {
  1176. return [2 /*return*/, { err: fetchRes.err }];
  1177. }
  1178. return [2 /*return*/, { res: fetchRes.res }];
  1179. }
  1180. });
  1181. }); })();
  1182. promise.then(function (v) {
  1183. // Msg 不需要 onRecvData
  1184. if (pendingApiItem && v.res) {
  1185. _this._onRecvData(v.res, pendingApiItem);
  1186. }
  1187. });
  1188. // Finally
  1189. promise.catch(function (e) { }).then(function () {
  1190. if (pendingApiItem) {
  1191. pendingApiItem.onAbort = undefined;
  1192. }
  1193. });
  1194. return [2 /*return*/, promise];
  1195. });
  1196. });
  1197. };
  1198. return BaseHttpClient;
  1199. }(BaseClient));
  1200. var defaultBaseHttpClientOptions = tslib.__assign(tslib.__assign({}, defaultBaseClientOptions), { server: 'http://localhost:3000',
  1201. // logger: new TerminalColorLogger(),
  1202. jsonPrune: true });
  1203. /**
  1204. * WebSocket Client for TSRPC.
  1205. * It uses native `WebSocket` of browser.
  1206. * @typeParam ServiceType - `ServiceType` from generated `proto.ts`
  1207. */
  1208. var BaseWsClient = /** @class */ (function (_super) {
  1209. tslib.__extends(BaseWsClient, _super);
  1210. function BaseWsClient(proto, wsp, options) {
  1211. var _this = this;
  1212. var _a;
  1213. _this = _super.call(this, proto, tslib.__assign(tslib.__assign({}, defaultBaseWsClientOptions), options)) || this;
  1214. _this.type = 'LONG';
  1215. _this._onWsOpen = function () {
  1216. var _a;
  1217. if (!_this._connecting) {
  1218. return;
  1219. }
  1220. _this._status = exports.WsClientStatus.Opened;
  1221. _this._connecting.rs({ isSucc: true });
  1222. _this._connecting = undefined;
  1223. (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.log('WebSocket connection to server successful');
  1224. _this.flows.postConnectFlow.exec({}, _this.logger);
  1225. // First heartbeat
  1226. if (_this.options.heartbeat) {
  1227. _this._heartbeat();
  1228. }
  1229. };
  1230. _this._onWsClose = function (code, reason) {
  1231. var _a, _b, _c;
  1232. // 防止重复执行
  1233. if (_this._status === exports.WsClientStatus.Closed) {
  1234. return;
  1235. }
  1236. var isManual = !!_this._rsDisconnecting;
  1237. var isConnectedBefore = _this.isConnected || isManual;
  1238. _this._status = exports.WsClientStatus.Closed;
  1239. // 连接中,返回连接失败
  1240. if (_this._connecting) {
  1241. _this._connecting.rs({
  1242. isSucc: false,
  1243. errMsg: "Failed to connect to WebSocket server: ".concat(_this.options.server)
  1244. });
  1245. _this._connecting = undefined;
  1246. (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error("Failed to connect to WebSocket server: ".concat(_this.options.server));
  1247. }
  1248. // Clear heartbeat
  1249. if (_this._pendingHeartbeat) {
  1250. clearTimeout(_this._pendingHeartbeat.timeoutTimer);
  1251. _this._pendingHeartbeat = undefined;
  1252. }
  1253. if (_this._nextHeartbeatTimer) {
  1254. clearTimeout(_this._nextHeartbeatTimer);
  1255. }
  1256. // disconnect中,返回成功
  1257. if (_this._rsDisconnecting) {
  1258. _this._rsDisconnecting();
  1259. _this._rsDisconnecting = undefined;
  1260. (_b = _this.logger) === null || _b === void 0 ? void 0 : _b.log('Disconnected succ', "code=".concat(code, " reason=").concat(reason));
  1261. }
  1262. // 非 disconnect 中,从连接中意外断开
  1263. else if (isConnectedBefore) {
  1264. (_c = _this.logger) === null || _c === void 0 ? void 0 : _c.log("Lost connection to ".concat(_this.options.server), "code=".concat(code, " reason=").concat(reason));
  1265. }
  1266. // postDisconnectFlow,仅从连接状态断开时触发
  1267. if (isConnectedBefore) {
  1268. _this.flows.postDisconnectFlow.exec({
  1269. reason: reason,
  1270. isManual: isManual
  1271. }, _this.logger);
  1272. }
  1273. // 对所有请求中的 API 报错
  1274. _this._pendingApis.slice().forEach(function (v) {
  1275. var _a;
  1276. (_a = v.onReturn) === null || _a === void 0 ? void 0 : _a.call(v, {
  1277. isSucc: false,
  1278. err: new tsrpcProto.TsrpcError(reason || 'Lost connection to server', { type: tsrpcProto.TsrpcErrorType.NetworkError, code: 'LOST_CONN' })
  1279. });
  1280. });
  1281. };
  1282. _this._onWsError = function (e) {
  1283. var _a, _b;
  1284. (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error('[WebSocket Error]', e);
  1285. // 连接中,返回连接失败
  1286. if (_this._connecting) {
  1287. _this._connecting.rs({
  1288. isSucc: false,
  1289. errMsg: "Failed to connect to WebSocket server: ".concat(_this.options.server)
  1290. });
  1291. _this._connecting = undefined;
  1292. (_b = _this.logger) === null || _b === void 0 ? void 0 : _b.error("Failed to connect to WebSocket server: ".concat(_this.options.server));
  1293. }
  1294. };
  1295. _this._onWsMessage = function (data) {
  1296. if (_this._status !== exports.WsClientStatus.Opened) {
  1297. return;
  1298. }
  1299. // 心跳包回包
  1300. if (data instanceof Uint8Array && data.length === TransportDataUtil.HeartbeatPacket.length && data.every(function (v, i) { return v === TransportDataUtil.HeartbeatPacket[i]; })) {
  1301. _this._onHeartbeatAnswer(data);
  1302. return;
  1303. }
  1304. _this._onRecvData(data);
  1305. };
  1306. // #region Heartbeat
  1307. /**
  1308. * Last latency time (ms) of heartbeat test
  1309. */
  1310. _this.lastHeartbeatLatency = 0;
  1311. // #endregion
  1312. _this._status = exports.WsClientStatus.Closed;
  1313. _this._wsp = wsp;
  1314. wsp.options = {
  1315. onOpen: _this._onWsOpen,
  1316. onClose: _this._onWsClose,
  1317. onError: _this._onWsError,
  1318. onMessage: _this._onWsMessage,
  1319. logger: _this.logger
  1320. };
  1321. (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.log('TSRPC WebSocket Client :', _this.options.server);
  1322. return _this;
  1323. }
  1324. BaseWsClient.prototype._sendData = function (data) {
  1325. return tslib.__awaiter(this, void 0, void 0, function () {
  1326. var _this = this;
  1327. return tslib.__generator(this, function (_a) {
  1328. return [2 /*return*/, new Promise(function (rs) { return tslib.__awaiter(_this, void 0, void 0, function () {
  1329. return tslib.__generator(this, function (_a) {
  1330. if (!this.isConnected) {
  1331. rs({
  1332. err: new tsrpcProto.TsrpcError('WebSocket is not connected', {
  1333. code: 'WS_NOT_OPEN',
  1334. type: tsrpcProto.TsrpcError.Type.ClientError
  1335. })
  1336. });
  1337. return [2 /*return*/];
  1338. }
  1339. // Do Send
  1340. rs(this._wsp.send(data));
  1341. return [2 /*return*/];
  1342. });
  1343. }); })];
  1344. });
  1345. });
  1346. };
  1347. /**
  1348. * Send a heartbeat packet
  1349. */
  1350. BaseWsClient.prototype._heartbeat = function () {
  1351. var _this = this;
  1352. var _a;
  1353. if (this._pendingHeartbeat || this._status !== exports.WsClientStatus.Opened || !this.options.heartbeat) {
  1354. return;
  1355. }
  1356. this._pendingHeartbeat = {
  1357. startTime: Date.now(),
  1358. timeoutTimer: setTimeout(function () {
  1359. var _a;
  1360. _this._pendingHeartbeat = undefined;
  1361. // heartbeat timeout, disconnect if still connected
  1362. (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.error('[Heartbeat] Heartbeat timeout, the connection disconnected automatically.');
  1363. _this._wsClose(3000, 'Heartbeat timeout');
  1364. _this._wsp.options.onClose(3000, 'Heartbeat timeout');
  1365. }, this.options.heartbeat.timeout)
  1366. };
  1367. this.options.debugBuf && ((_a = this.logger) === null || _a === void 0 ? void 0 : _a.log('[Heartbeat] Send ping', TransportDataUtil.HeartbeatPacket));
  1368. this._sendData(TransportDataUtil.HeartbeatPacket);
  1369. };
  1370. BaseWsClient.prototype._onHeartbeatAnswer = function (data) {
  1371. var _this = this;
  1372. var _a;
  1373. if (!this._pendingHeartbeat || this._status !== exports.WsClientStatus.Opened || !this.options.heartbeat) {
  1374. return;
  1375. }
  1376. // heartbeat succ
  1377. this.lastHeartbeatLatency = Date.now() - this._pendingHeartbeat.startTime;
  1378. this.options.debugBuf && ((_a = this.logger) === null || _a === void 0 ? void 0 : _a.log("[Heartbeat] Recv pong, latency=".concat(this.lastHeartbeatLatency, "ms"), data));
  1379. clearTimeout(this._pendingHeartbeat.timeoutTimer);
  1380. this._pendingHeartbeat = undefined;
  1381. // next heartbeat timer
  1382. this._nextHeartbeatTimer = setTimeout(function () {
  1383. _this._heartbeat();
  1384. }, this.options.heartbeat.interval);
  1385. };
  1386. Object.defineProperty(BaseWsClient.prototype, "status", {
  1387. get: function () {
  1388. return this._status;
  1389. },
  1390. enumerable: false,
  1391. configurable: true
  1392. });
  1393. Object.defineProperty(BaseWsClient.prototype, "isConnected", {
  1394. get: function () {
  1395. return this._status === exports.WsClientStatus.Opened;
  1396. },
  1397. enumerable: false,
  1398. configurable: true
  1399. });
  1400. /**
  1401. * Start connecting, you must connect first before `callApi()` and `sendMsg()`.
  1402. * @throws never
  1403. */
  1404. BaseWsClient.prototype.connect = function () {
  1405. var _a, _b;
  1406. return tslib.__awaiter(this, void 0, void 0, function () {
  1407. var pre, promiseConnect;
  1408. var _this = this;
  1409. return tslib.__generator(this, function (_c) {
  1410. switch (_c.label) {
  1411. case 0:
  1412. // 已连接成功
  1413. if (this.isConnected) {
  1414. return [2 /*return*/, { isSucc: true }];
  1415. }
  1416. // 已连接中
  1417. if (this._connecting) {
  1418. return [2 /*return*/, this._connecting.promise];
  1419. }
  1420. return [4 /*yield*/, this.flows.preConnectFlow.exec({}, this.logger)];
  1421. case 1:
  1422. pre = _c.sent();
  1423. // Pre return
  1424. if (pre === null || pre === void 0 ? void 0 : pre.return) {
  1425. return [2 /*return*/, pre.return];
  1426. }
  1427. // Canceled
  1428. if (!pre) {
  1429. return [2 /*return*/, new Promise(function (rs) { })];
  1430. }
  1431. try {
  1432. this._wsp.connect(this.options.server, [this.options.json ? 'text' : 'buffer']);
  1433. }
  1434. catch (e) {
  1435. (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error(e);
  1436. return [2 /*return*/, { isSucc: false, errMsg: e.message }];
  1437. }
  1438. this._status = exports.WsClientStatus.Opening;
  1439. (_b = this.logger) === null || _b === void 0 ? void 0 : _b.log("Start connecting ".concat(this.options.server, "..."));
  1440. this._connecting = {};
  1441. promiseConnect = new Promise(function (rs) {
  1442. _this._connecting.rs = rs;
  1443. });
  1444. this._connecting.promise = promiseConnect;
  1445. return [2 /*return*/, promiseConnect];
  1446. }
  1447. });
  1448. });
  1449. };
  1450. /**
  1451. * Disconnect immediately
  1452. * @throws never
  1453. */
  1454. BaseWsClient.prototype.disconnect = function (code, reason) {
  1455. var _a;
  1456. return tslib.__awaiter(this, void 0, void 0, function () {
  1457. var isClosed;
  1458. var _this = this;
  1459. return tslib.__generator(this, function (_b) {
  1460. if (this._status === exports.WsClientStatus.Closed) {
  1461. return [2 /*return*/];
  1462. }
  1463. this._status = exports.WsClientStatus.Closing;
  1464. (_a = this.logger) === null || _a === void 0 ? void 0 : _a.log('Start disconnecting...');
  1465. isClosed = false;
  1466. return [2 /*return*/, Promise.race([
  1467. // 正常等待 onClose 关闭
  1468. new Promise(function (rs) {
  1469. _this._rsDisconnecting = function () {
  1470. if (isClosed) {
  1471. return;
  1472. }
  1473. isClosed = true;
  1474. rs();
  1475. };
  1476. _this._wsClose(code !== null && code !== void 0 ? code : 1000, reason !== null && reason !== void 0 ? reason : '');
  1477. }),
  1478. // 超时保护,1 秒未收到关闭请求的,直接 onClose 掉
  1479. new Promise(function (rs) {
  1480. setTimeout(function () {
  1481. if (isClosed) {
  1482. return;
  1483. }
  1484. isClosed = true;
  1485. _this._onWsClose(1005, 'Connection closed, but not received ws.onClose event.');
  1486. }, 1000);
  1487. })
  1488. ])];
  1489. });
  1490. });
  1491. };
  1492. BaseWsClient.prototype._wsClose = function (code, reason) {
  1493. var _a;
  1494. try {
  1495. this._wsp.close(code !== null && code !== void 0 ? code : 1000, reason !== null && reason !== void 0 ? reason : '');
  1496. }
  1497. catch (e) {
  1498. (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error('[WsCloseError]', e);
  1499. }
  1500. };
  1501. return BaseWsClient;
  1502. }(BaseClient));
  1503. var defaultBaseWsClientOptions = tslib.__assign(tslib.__assign({}, defaultBaseClientOptions), { server: 'ws://localhost:3000' });
  1504. exports.WsClientStatus = void 0;
  1505. (function (WsClientStatus) {
  1506. WsClientStatus["Opening"] = "OPENING";
  1507. WsClientStatus["Opened"] = "OPENED";
  1508. WsClientStatus["Closing"] = "CLOSING";
  1509. WsClientStatus["Closed"] = "CLOSED";
  1510. })(exports.WsClientStatus || (exports.WsClientStatus = {}));
  1511. exports.BaseClient = BaseClient;
  1512. exports.BaseHttpClient = BaseHttpClient;
  1513. exports.BaseWsClient = BaseWsClient;
  1514. exports.Counter = Counter;
  1515. exports.Flow = Flow;
  1516. exports.MsgHandlerManager = MsgHandlerManager;
  1517. exports.ServiceMapUtil = ServiceMapUtil;
  1518. exports.TransportDataUtil = TransportDataUtil;
  1519. exports.defaultBaseClientOptions = defaultBaseClientOptions;
  1520. exports.defaultBaseHttpClientOptions = defaultBaseHttpClientOptions;
  1521. exports.defaultBaseWsClientOptions = defaultBaseWsClientOptions;
  1522. exports.getCustomObjectIdTypes = getCustomObjectIdTypes;
  1523. }
  1524. if (nodeEnv) {
  1525. __define(__module.exports, __require, __module);
  1526. }
  1527. else {
  1528. __quick_compile_project__.registerModuleFunc(__filename, function () {
  1529. __define(__module.exports, __require, __module);
  1530. });
  1531. }
  1532. })();