@next-core/easyops-runtime 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/websocket/MessageDispatcher.js +147 -0
- package/dist/cjs/websocket/MessageDispatcher.js.map +1 -0
- package/dist/cjs/websocket/MessageService.js +148 -0
- package/dist/cjs/websocket/MessageService.js.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/websocket/MessageDispatcher.js +139 -0
- package/dist/esm/websocket/MessageDispatcher.js.map +1 -0
- package/dist/esm/websocket/MessageService.js +140 -0
- package/dist/esm/websocket/MessageService.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/websocket/MessageDispatcher.d.ts +16 -0
- package/dist/types/websocket/MessageService.d.ts +11 -0
- package/package.json +7 -6
package/dist/cjs/index.js
CHANGED
|
@@ -4,8 +4,9 @@ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWild
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.menu = exports.flowApi = exports.checkPermissions = exports.checkInstalledApps = exports.auth = void 0;
|
|
7
|
+
exports.messageDispatcher = exports.menu = exports.flowApi = exports.checkPermissions = exports.checkInstalledApps = exports.auth = void 0;
|
|
8
8
|
var _checkPermissions2 = require("./checkPermissions.js");
|
|
9
|
+
var _MessageDispatcher = require("./websocket/MessageDispatcher.js");
|
|
9
10
|
var _checkInstalledApps = _interopRequireWildcard(require("./checkInstalledApps.js"));
|
|
10
11
|
exports.checkInstalledApps = _checkInstalledApps;
|
|
11
12
|
var _flowApi = _interopRequireWildcard(require("./flowApi/index.js"));
|
|
@@ -22,4 +23,6 @@ const checkPermissions = Object.freeze({
|
|
|
22
23
|
preCheckPermissionsForBrickOrRoute: _checkPermissions2.preCheckPermissionsForBrickOrRoute
|
|
23
24
|
});
|
|
24
25
|
exports.checkPermissions = checkPermissions;
|
|
26
|
+
const messageDispatcher = new _MessageDispatcher.MessageDispatcher();
|
|
27
|
+
exports.messageDispatcher = messageDispatcher;
|
|
25
28
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_checkPermissions2","require","_checkInstalledApps","_interopRequireWildcard","exports","checkInstalledApps","_flowApi","flowApi","_auth","auth","_menu","menu","checkPermissions","Object","freeze","_checkPermissions","preCheckPermissions","preCheckPermissionsForBrickOrRoute"],"sources":["../../src/index.ts"],"sourcesContent":["// istanbul ignore file\nimport {\n checkPermissions as _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n} from \"./checkPermissions.js\";\n\nexport * as checkInstalledApps from \"./checkInstalledApps.js\";\nexport * as flowApi from \"./flowApi/index.js\";\nexport * as auth from \"./auth.js\";\nexport * as menu from \"./menu/index.js\";\n\nexport const checkPermissions = Object.freeze({\n checkPermissions: _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n});\n"],"mappings":";;;;;;;AACA,IAAAA,kBAAA,GAAAC,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","names":["_checkPermissions2","require","_MessageDispatcher","_checkInstalledApps","_interopRequireWildcard","exports","checkInstalledApps","_flowApi","flowApi","_auth","auth","_menu","menu","checkPermissions","Object","freeze","_checkPermissions","preCheckPermissions","preCheckPermissionsForBrickOrRoute","messageDispatcher","MessageDispatcher"],"sources":["../../src/index.ts"],"sourcesContent":["// istanbul ignore file\nimport {\n checkPermissions as _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n} from \"./checkPermissions.js\";\n\nimport { MessageDispatcher } from \"./websocket/MessageDispatcher.js\";\n\nexport * as checkInstalledApps from \"./checkInstalledApps.js\";\nexport * as flowApi from \"./flowApi/index.js\";\nexport * as auth from \"./auth.js\";\nexport * as menu from \"./menu/index.js\";\n\nexport const checkPermissions = Object.freeze({\n checkPermissions: _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n});\n\nexport const messageDispatcher = new MessageDispatcher();\n"],"mappings":";;;;;;;AACA,IAAAA,kBAAA,GAAAC,OAAA;AAMA,IAAAC,kBAAA,GAAAD,OAAA;AAAqE,IAAAE,mBAAA,GAAAC,uBAAA,CAAAH,OAAA;AAAAI,OAAA,CAAAC,kBAAA,GAAAH,mBAAA;AAAA,IAAAI,QAAA,GAAAH,uBAAA,CAAAH,OAAA;AAAAI,OAAA,CAAAG,OAAA,GAAAD,QAAA;AAAA,IAAAE,KAAA,GAAAL,uBAAA,CAAAH,OAAA;AAAAI,OAAA,CAAAK,IAAA,GAAAD,KAAA;AAAA,IAAAE,KAAA,GAAAP,uBAAA,CAAAH,OAAA;AAAAI,OAAA,CAAAO,IAAA,GAAAD,KAAA;AAPrE;;AAcO,MAAME,gBAAgB,GAAGC,MAAM,CAACC,MAAM,CAAC;EAC5CF,gBAAgB,EAAEG,mCAAiB;EACnCC,mBAAmB,EAAnBA,sCAAmB;EACnBC,kCAAkC,EAAlCA;AACF,CAAC,CAAC;AAACb,OAAA,CAAAQ,gBAAA,GAAAA,gBAAA;AAEI,MAAMM,iBAAiB,GAAG,IAAIC,oCAAiB,CAAC,CAAC;AAACf,OAAA,CAAAc,iBAAA,GAAAA,iBAAA"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.MessageDispatcher = void 0;
|
|
8
|
+
var _classPrivateMethodInitSpec2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateMethodInitSpec"));
|
|
9
|
+
var _classPrivateFieldInitSpec2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateFieldInitSpec"));
|
|
10
|
+
var _classPrivateMethodGet2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateMethodGet"));
|
|
11
|
+
var _classPrivateFieldSet2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateFieldSet"));
|
|
12
|
+
var _classPrivateFieldGet3 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateFieldGet"));
|
|
13
|
+
var _runtime = require("@next-core/runtime");
|
|
14
|
+
var _lodash = require("lodash");
|
|
15
|
+
var _MessageService = require("./MessageService.js");
|
|
16
|
+
var _ms = /*#__PURE__*/new WeakMap();
|
|
17
|
+
var _memoizedChannels = /*#__PURE__*/new WeakMap();
|
|
18
|
+
var _channelPayloads = /*#__PURE__*/new WeakMap();
|
|
19
|
+
var _ms2 = /*#__PURE__*/new WeakMap();
|
|
20
|
+
var _subOrUnsub = /*#__PURE__*/new WeakSet();
|
|
21
|
+
class MessageDispatcher {
|
|
22
|
+
constructor() {
|
|
23
|
+
(0, _classPrivateMethodInitSpec2.default)(this, _subOrUnsub);
|
|
24
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _ms2, {
|
|
25
|
+
get: _get_ms,
|
|
26
|
+
set: void 0
|
|
27
|
+
});
|
|
28
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _ms, {
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _memoizedChannels, {
|
|
33
|
+
writable: true,
|
|
34
|
+
value: {
|
|
35
|
+
sub: new Map(),
|
|
36
|
+
unsub: new Map()
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _channelPayloads, {
|
|
40
|
+
writable: true,
|
|
41
|
+
value: new Map()
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
subscribe(channel, payload) {
|
|
45
|
+
const stringifiedPayload = JSON.stringify(payload);
|
|
46
|
+
return (0, _classPrivateMethodGet2.default)(this, _subOrUnsub, _subOrUnsub2).call(this, "sub", channel, payload, stringifiedPayload);
|
|
47
|
+
}
|
|
48
|
+
unsubscribe(channel) {
|
|
49
|
+
const stringifiedPayload = (0, _classPrivateFieldGet3.default)(this, _channelPayloads).get(channel);
|
|
50
|
+
if (!stringifiedPayload) {
|
|
51
|
+
const msg = `The message channel to unsubscribe "${channel}" is not found`;
|
|
52
|
+
// eslint-disable-next-line no-console
|
|
53
|
+
console.error(msg);
|
|
54
|
+
return Promise.reject(new Error(msg));
|
|
55
|
+
}
|
|
56
|
+
const payload = JSON.parse(stringifiedPayload);
|
|
57
|
+
const result = (0, _classPrivateMethodGet2.default)(this, _subOrUnsub, _subOrUnsub2).call(this, "unsub", channel, payload, stringifiedPayload);
|
|
58
|
+
(0, _classPrivateFieldGet3.default)(this, _memoizedChannels).sub.delete(stringifiedPayload);
|
|
59
|
+
result.then(() => {
|
|
60
|
+
(0, _classPrivateFieldGet3.default)(this, _channelPayloads).delete(channel);
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
onMessage(channel, listener) {
|
|
65
|
+
const stringifiedPayload = (0, _classPrivateFieldGet3.default)(this, _channelPayloads).get(channel);
|
|
66
|
+
if (!stringifiedPayload) {
|
|
67
|
+
// eslint-disable-next-line no-console
|
|
68
|
+
console.error(`Message channel: "${channel}" not found`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
(0, _classPrivateFieldGet3.default)(this, _ms2).onMessage(response => {
|
|
72
|
+
if (response.event === "MESSAGE.PUSH" && matchMessageChannel(stringifiedPayload, response.payload)) {
|
|
73
|
+
listener(response.payload.message);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
onClose(listener) {
|
|
78
|
+
(0, _classPrivateFieldGet3.default)(this, _ms2).onClose(listener);
|
|
79
|
+
}
|
|
80
|
+
reset() {
|
|
81
|
+
var _classPrivateFieldGet2;
|
|
82
|
+
(0, _classPrivateFieldGet3.default)(this, _memoizedChannels).sub.clear();
|
|
83
|
+
(0, _classPrivateFieldGet3.default)(this, _memoizedChannels).unsub.clear();
|
|
84
|
+
(0, _classPrivateFieldGet3.default)(this, _channelPayloads).clear();
|
|
85
|
+
(_classPrivateFieldGet2 = (0, _classPrivateFieldGet3.default)(this, _ms)) === null || _classPrivateFieldGet2 === void 0 ? void 0 : _classPrivateFieldGet2.reset();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.MessageDispatcher = MessageDispatcher;
|
|
89
|
+
function _get_ms() {
|
|
90
|
+
if (!(0, _classPrivateFieldGet3.default)(this, _ms)) {
|
|
91
|
+
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
92
|
+
const url = `${protocol}//${window.location.host}${(0, _runtime.getBasePath)()}api/websocket_service/v1/ws`;
|
|
93
|
+
(0, _classPrivateFieldSet2.default)(this, _ms, new _MessageService.MessageService(url));
|
|
94
|
+
}
|
|
95
|
+
return (0, _classPrivateFieldGet3.default)(this, _ms);
|
|
96
|
+
}
|
|
97
|
+
function _subOrUnsub2(type, channel, payload, stringifiedPayload) {
|
|
98
|
+
const hit = (0, _classPrivateFieldGet3.default)(this, _memoizedChannels)[type].get(stringifiedPayload);
|
|
99
|
+
if (hit) {
|
|
100
|
+
return hit;
|
|
101
|
+
}
|
|
102
|
+
const request = {
|
|
103
|
+
event: type === "sub" ? "TOPIC.SUB" : "TOPIC.UNSUB",
|
|
104
|
+
payload
|
|
105
|
+
};
|
|
106
|
+
const promise = new Promise((resolve, reject) => {
|
|
107
|
+
const identity = getIdentity(payload);
|
|
108
|
+
(0, _classPrivateFieldGet3.default)(this, _ms2).onMessage(response => {
|
|
109
|
+
const isSuccess = response.event === (type === "sub" ? "TOPIC.SUB_SUCCESS" : "TOPIC.UNSUB_SUCCESS");
|
|
110
|
+
const isFailed = response.event === (type === "sub" ? "TOPIC.SUB_FAILED" : "TOPIC.UNSUB_FAILED");
|
|
111
|
+
if ((isSuccess || isFailed) &&
|
|
112
|
+
// Put this after event type checks, to prevent unnecessary
|
|
113
|
+
// JSON stringify.
|
|
114
|
+
identity === getIdentity(response.payload)) {
|
|
115
|
+
(isSuccess ? resolve : reject)(response);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
(0, _classPrivateFieldGet3.default)(this, _ms2).send(request);
|
|
119
|
+
});
|
|
120
|
+
if (type === "sub") {
|
|
121
|
+
(0, _classPrivateFieldGet3.default)(this, _channelPayloads).set(channel, stringifiedPayload);
|
|
122
|
+
}
|
|
123
|
+
(0, _classPrivateFieldGet3.default)(this, _memoizedChannels)[type].set(stringifiedPayload, promise);
|
|
124
|
+
return promise;
|
|
125
|
+
}
|
|
126
|
+
function getIdentity(payload) {
|
|
127
|
+
const {
|
|
128
|
+
system,
|
|
129
|
+
topic
|
|
130
|
+
} = payload;
|
|
131
|
+
return JSON.stringify({
|
|
132
|
+
system,
|
|
133
|
+
topic
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function matchMessageChannel(stringifiedPayload, responsePayload) {
|
|
137
|
+
const payload = JSON.parse(stringifiedPayload);
|
|
138
|
+
return payload.system === responsePayload.system && (
|
|
139
|
+
// Exact match
|
|
140
|
+
payload.topic === responsePayload.topic ||
|
|
141
|
+
// Wildcards match
|
|
142
|
+
// For `ab.cd.*`:
|
|
143
|
+
// - Matches `ab.cd.r` or `ab.cd.x.yz`
|
|
144
|
+
// - DOES NOT match `ab.cd.x/yz` or `ab.x.cd` or `x.ab.cd.yz`
|
|
145
|
+
typeof payload.topic === "string" && payload.topic.includes("*") && new RegExp(`^${payload.topic.replace(/([^*]*)\*([^*]*)/g, (m, p1, p2) => `${(0, _lodash.escapeRegExp)(p1)}[^/]*${(0, _lodash.escapeRegExp)(p2)}`)}$`).test(responsePayload.topic));
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=MessageDispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageDispatcher.js","names":["_runtime","require","_lodash","_MessageService","_ms","WeakMap","_memoizedChannels","_channelPayloads","_ms2","_subOrUnsub","WeakSet","MessageDispatcher","constructor","_classPrivateMethodInitSpec2","default","_classPrivateFieldInitSpec2","get","_get_ms","set","writable","value","sub","Map","unsub","subscribe","channel","payload","stringifiedPayload","JSON","stringify","_classPrivateMethodGet2","_subOrUnsub2","call","unsubscribe","_classPrivateFieldGet3","msg","console","error","Promise","reject","Error","parse","result","delete","then","onMessage","listener","response","event","matchMessageChannel","message","onClose","reset","_classPrivateFieldGet2","clear","exports","protocol","location","url","window","host","getBasePath","_classPrivateFieldSet2","MessageService","type","hit","request","promise","resolve","identity","getIdentity","isSuccess","isFailed","send","system","topic","responsePayload","includes","RegExp","replace","m","p1","p2","escapeRegExp","test"],"sources":["../../../src/websocket/MessageDispatcher.ts"],"sourcesContent":["import { getBasePath } from \"@next-core/runtime\";\nimport { escapeRegExp } from \"lodash\";\nimport {\n MessageService,\n type MessageListener,\n CloseListener,\n} from \"./MessageService.js\";\n\ninterface MessageResponse {\n event:\n | \"TOPIC.SUB_SUCCESS\"\n | \"TOPIC.SUB_FAILED\"\n | \"TOPIC.UNSUB_SUCCESS\"\n | \"TOPIC.UNSUB_FAILED\"\n | \"MESSAGE.PUSH\";\n payload: MessagePayload;\n}\n\ninterface MessagePayload {\n source?: string;\n system: string;\n topic: string;\n message?: unknown;\n}\n\nexport class MessageDispatcher {\n #_ms: MessageService | undefined;\n #memoizedChannels = {\n sub: new Map<string, Promise<unknown>>(),\n unsub: new Map<string, Promise<unknown>>(),\n };\n #channelPayloads = new Map<string, string>();\n\n get #ms(): MessageService {\n if (!this.#_ms) {\n const protocol = location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n const url = `${protocol}//${\n window.location.host\n }${getBasePath()}api/websocket_service/v1/ws`;\n this.#_ms = new MessageService(url);\n }\n return this.#_ms;\n }\n\n subscribe(channel: string, payload: MessagePayload): Promise<unknown> {\n const stringifiedPayload = JSON.stringify(payload);\n return this.#subOrUnsub(\"sub\", channel, payload, stringifiedPayload);\n }\n\n unsubscribe(channel: string): Promise<unknown> {\n const stringifiedPayload = this.#channelPayloads.get(channel);\n if (!stringifiedPayload) {\n const msg = `The message channel to unsubscribe \"${channel}\" is not found`;\n // eslint-disable-next-line no-console\n console.error(msg);\n return Promise.reject(new Error(msg));\n }\n\n const payload = JSON.parse(stringifiedPayload);\n const result = this.#subOrUnsub(\n \"unsub\",\n channel,\n payload,\n stringifiedPayload\n );\n\n this.#memoizedChannels.sub.delete(stringifiedPayload);\n\n result.then(() => {\n this.#channelPayloads.delete(channel);\n });\n\n return result;\n }\n\n onMessage(channel: string, listener: MessageListener): void {\n const stringifiedPayload = this.#channelPayloads.get(channel);\n if (!stringifiedPayload) {\n // eslint-disable-next-line no-console\n console.error(`Message channel: \"${channel}\" not found`);\n return;\n }\n\n this.#ms.onMessage<MessageResponse>((response) => {\n if (\n response.event === \"MESSAGE.PUSH\" &&\n matchMessageChannel(stringifiedPayload, response.payload)\n ) {\n listener(response.payload.message);\n }\n });\n }\n\n onClose(listener: CloseListener): void {\n this.#ms.onClose(listener);\n }\n\n reset(): void {\n this.#memoizedChannels.sub.clear();\n this.#memoizedChannels.unsub.clear();\n this.#channelPayloads.clear();\n this.#_ms?.reset();\n }\n\n #subOrUnsub(\n type: \"sub\" | \"unsub\",\n channel: string,\n payload: MessagePayload,\n stringifiedPayload: string\n ): Promise<unknown> {\n const hit = this.#memoizedChannels[type].get(stringifiedPayload);\n if (hit) {\n return hit;\n }\n const request = {\n event: type === \"sub\" ? \"TOPIC.SUB\" : \"TOPIC.UNSUB\",\n payload,\n };\n const promise = new Promise((resolve, reject) => {\n const identity = getIdentity(payload);\n this.#ms.onMessage<MessageResponse>((response) => {\n const isSuccess =\n response.event ===\n (type === \"sub\" ? \"TOPIC.SUB_SUCCESS\" : \"TOPIC.UNSUB_SUCCESS\");\n const isFailed =\n response.event ===\n (type === \"sub\" ? \"TOPIC.SUB_FAILED\" : \"TOPIC.UNSUB_FAILED\");\n if (\n (isSuccess || isFailed) &&\n // Put this after event type checks, to prevent unnecessary\n // JSON stringify.\n identity === getIdentity(response.payload)\n ) {\n (isSuccess ? resolve : reject)(response);\n }\n });\n this.#ms.send(request);\n });\n\n if (type === \"sub\") {\n this.#channelPayloads.set(channel, stringifiedPayload);\n }\n this.#memoizedChannels[type].set(stringifiedPayload, promise);\n return promise;\n }\n}\n\nfunction getIdentity(payload: MessagePayload) {\n const { system, topic } = payload;\n return JSON.stringify({ system, topic });\n}\n\nfunction matchMessageChannel(\n stringifiedPayload: string,\n responsePayload: MessagePayload\n): boolean {\n const payload = JSON.parse(stringifiedPayload) as MessagePayload;\n return (\n payload.system === responsePayload.system &&\n // Exact match\n (payload.topic === responsePayload.topic ||\n // Wildcards match\n // For `ab.cd.*`:\n // - Matches `ab.cd.r` or `ab.cd.x.yz`\n // - DOES NOT match `ab.cd.x/yz` or `ab.x.cd` or `x.ab.cd.yz`\n (typeof payload.topic === \"string\" &&\n payload.topic.includes(\"*\") &&\n new RegExp(\n `^${payload.topic.replace(\n /([^*]*)\\*([^*]*)/g,\n (m, p1, p2) => `${escapeRegExp(p1)}[^/]*${escapeRegExp(p2)}`\n )}$`\n ).test(responsePayload.topic)))\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.MessageService = void 0;
|
|
8
|
+
var _classPrivateMethodInitSpec2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateMethodInitSpec"));
|
|
9
|
+
var _classPrivateFieldInitSpec2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateFieldInitSpec"));
|
|
10
|
+
var _classPrivateMethodGet2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateMethodGet"));
|
|
11
|
+
var _classPrivateFieldGet3 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateFieldGet"));
|
|
12
|
+
var _classPrivateFieldSet2 = _interopRequireDefault(require("@babel/runtime/helpers/classPrivateFieldSet"));
|
|
13
|
+
const RETRY_TIMEOUT_UNIT = 1000;
|
|
14
|
+
const RETRY_LIMIT = 6;
|
|
15
|
+
var _url = /*#__PURE__*/new WeakMap();
|
|
16
|
+
var _ws = /*#__PURE__*/new WeakMap();
|
|
17
|
+
var _queuedMessages = /*#__PURE__*/new WeakMap();
|
|
18
|
+
var _messageListeners = /*#__PURE__*/new WeakMap();
|
|
19
|
+
var _closeListeners = /*#__PURE__*/new WeakMap();
|
|
20
|
+
var _retryCount = /*#__PURE__*/new WeakMap();
|
|
21
|
+
var _closed = /*#__PURE__*/new WeakMap();
|
|
22
|
+
var _connect = /*#__PURE__*/new WeakSet();
|
|
23
|
+
var _reconnect = /*#__PURE__*/new WeakSet();
|
|
24
|
+
class MessageService {
|
|
25
|
+
constructor(url) {
|
|
26
|
+
(0, _classPrivateMethodInitSpec2.default)(this, _reconnect);
|
|
27
|
+
(0, _classPrivateMethodInitSpec2.default)(this, _connect);
|
|
28
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _url, {
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _ws, {
|
|
33
|
+
writable: true,
|
|
34
|
+
value: void 0
|
|
35
|
+
});
|
|
36
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _queuedMessages, {
|
|
37
|
+
writable: true,
|
|
38
|
+
value: []
|
|
39
|
+
});
|
|
40
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _messageListeners, {
|
|
41
|
+
writable: true,
|
|
42
|
+
value: new Set()
|
|
43
|
+
});
|
|
44
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _closeListeners, {
|
|
45
|
+
writable: true,
|
|
46
|
+
value: new Set()
|
|
47
|
+
});
|
|
48
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _retryCount, {
|
|
49
|
+
writable: true,
|
|
50
|
+
value: 0
|
|
51
|
+
});
|
|
52
|
+
(0, _classPrivateFieldInitSpec2.default)(this, _closed, {
|
|
53
|
+
writable: true,
|
|
54
|
+
value: false
|
|
55
|
+
});
|
|
56
|
+
(0, _classPrivateFieldSet2.default)(this, _url, url);
|
|
57
|
+
}
|
|
58
|
+
send(data) {
|
|
59
|
+
// Connect when data is sent for the first time
|
|
60
|
+
if (!(0, _classPrivateFieldGet3.default)(this, _ws)) {
|
|
61
|
+
(0, _classPrivateFieldSet2.default)(this, _ws, (0, _classPrivateMethodGet2.default)(this, _connect, _connect2).call(this));
|
|
62
|
+
}
|
|
63
|
+
const stringifiedData = JSON.stringify(data);
|
|
64
|
+
if ((0, _classPrivateFieldGet3.default)(this, _ws).readyState === WebSocket.OPEN) {
|
|
65
|
+
(0, _classPrivateFieldGet3.default)(this, _ws).send(stringifiedData);
|
|
66
|
+
} else {
|
|
67
|
+
(0, _classPrivateFieldGet3.default)(this, _queuedMessages).push(stringifiedData);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
onMessage(listener) {
|
|
71
|
+
(0, _classPrivateFieldGet3.default)(this, _messageListeners).add(listener);
|
|
72
|
+
}
|
|
73
|
+
onClose(listener) {
|
|
74
|
+
(0, _classPrivateFieldGet3.default)(this, _closeListeners).add(listener);
|
|
75
|
+
}
|
|
76
|
+
reset() {
|
|
77
|
+
(0, _classPrivateFieldGet3.default)(this, _queuedMessages).length = 0;
|
|
78
|
+
(0, _classPrivateFieldGet3.default)(this, _messageListeners).clear();
|
|
79
|
+
(0, _classPrivateFieldGet3.default)(this, _closeListeners).clear();
|
|
80
|
+
}
|
|
81
|
+
close() {
|
|
82
|
+
var _classPrivateFieldGet2;
|
|
83
|
+
(0, _classPrivateFieldSet2.default)(this, _closed, true);
|
|
84
|
+
if (((_classPrivateFieldGet2 = (0, _classPrivateFieldGet3.default)(this, _ws)) === null || _classPrivateFieldGet2 === void 0 ? void 0 : _classPrivateFieldGet2.readyState) === WebSocket.OPEN) {
|
|
85
|
+
(0, _classPrivateFieldGet3.default)(this, _ws).close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.MessageService = MessageService;
|
|
90
|
+
function _connect2() {
|
|
91
|
+
// eslint-disable-next-line no-console
|
|
92
|
+
console.log("WebSocket connecting ...");
|
|
93
|
+
const ws = new WebSocket((0, _classPrivateFieldGet3.default)(this, _url));
|
|
94
|
+
ws.addEventListener("open", e => {
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
console.log("WebSocket open:", e);
|
|
97
|
+
(0, _classPrivateFieldSet2.default)(this, _retryCount, 0);
|
|
98
|
+
for (const msg of (0, _classPrivateFieldGet3.default)(this, _queuedMessages)) {
|
|
99
|
+
ws.send(msg);
|
|
100
|
+
}
|
|
101
|
+
(0, _classPrivateFieldGet3.default)(this, _queuedMessages).length = 0;
|
|
102
|
+
});
|
|
103
|
+
ws.addEventListener("close", e => {
|
|
104
|
+
if ((0, _classPrivateFieldGet3.default)(this, _closed)) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// eslint-disable-next-line no-console
|
|
108
|
+
console.log("WebSocket close:", e);
|
|
109
|
+
for (const listener of (0, _classPrivateFieldGet3.default)(this, _closeListeners)) {
|
|
110
|
+
listener();
|
|
111
|
+
}
|
|
112
|
+
// Error code 1000 means that the connection was closed normally.
|
|
113
|
+
if (e.code !== 1000) {
|
|
114
|
+
(0, _classPrivateMethodGet2.default)(this, _reconnect, _reconnect2).call(this);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
ws.addEventListener("error", e => {
|
|
118
|
+
// No need to reconnect in error event listener,
|
|
119
|
+
// there will always be a close event along with the error event.
|
|
120
|
+
// eslint-disable-next-line no-console
|
|
121
|
+
console.error("WebSocket error:", e);
|
|
122
|
+
});
|
|
123
|
+
ws.addEventListener("message", e => {
|
|
124
|
+
const response = JSON.parse(e.data);
|
|
125
|
+
for (const listener of (0, _classPrivateFieldGet3.default)(this, _messageListeners)) {
|
|
126
|
+
listener(response);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return ws;
|
|
130
|
+
}
|
|
131
|
+
function _reconnect2() {
|
|
132
|
+
// istanbul ignore next: currently can't mock this
|
|
133
|
+
if ((0, _classPrivateFieldGet3.default)(this, _retryCount) >= RETRY_LIMIT) {
|
|
134
|
+
// eslint-disable-next-line no-console
|
|
135
|
+
console.error("WebSocket connect retry limit exceeded");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// Double the timeout for each retry
|
|
139
|
+
const delay = Math.pow(2, (0, _classPrivateFieldGet3.default)(this, _retryCount)) * RETRY_TIMEOUT_UNIT;
|
|
140
|
+
// eslint-disable-next-line no-console
|
|
141
|
+
console.log("WebSocket will reconnect after %d seconds", delay / 1000);
|
|
142
|
+
setTimeout(() => {
|
|
143
|
+
var _this$retryCount, _this$retryCount2;
|
|
144
|
+
(0, _classPrivateFieldSet2.default)(this, _retryCount, (_this$retryCount = (0, _classPrivateFieldGet3.default)(this, _retryCount), _this$retryCount2 = _this$retryCount++, _this$retryCount)), _this$retryCount2;
|
|
145
|
+
(0, _classPrivateFieldSet2.default)(this, _ws, (0, _classPrivateMethodGet2.default)(this, _connect, _connect2).call(this));
|
|
146
|
+
}, delay);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=MessageService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageService.js","names":["RETRY_TIMEOUT_UNIT","RETRY_LIMIT","_url","WeakMap","_ws","_queuedMessages","_messageListeners","_closeListeners","_retryCount","_closed","_connect","WeakSet","_reconnect","MessageService","constructor","url","_classPrivateMethodInitSpec2","default","_classPrivateFieldInitSpec2","writable","value","Set","_classPrivateFieldSet2","send","data","_classPrivateFieldGet3","_classPrivateMethodGet2","_connect2","call","stringifiedData","JSON","stringify","readyState","WebSocket","OPEN","push","onMessage","listener","add","onClose","reset","length","clear","close","_classPrivateFieldGet2","exports","console","log","ws","addEventListener","e","msg","code","_reconnect2","error","response","parse","delay","Math","pow","setTimeout","_this$retryCount","_this$retryCount2"],"sources":["../../../src/websocket/MessageService.ts"],"sourcesContent":["export type MessageListener<T = unknown> = (response: T) => void;\nexport type CloseListener = () => void;\n\nconst RETRY_TIMEOUT_UNIT = 1000;\nconst RETRY_LIMIT = 6;\n\nexport class MessageService {\n #url: string;\n #ws: WebSocket | undefined;\n #queuedMessages: string[] = [];\n #messageListeners = new Set<MessageListener>();\n #closeListeners = new Set<CloseListener>();\n #retryCount = 0;\n #closed = false;\n\n constructor(url: string) {\n this.#url = url;\n }\n\n #connect(): WebSocket {\n // eslint-disable-next-line no-console\n console.log(\"WebSocket connecting ...\");\n const ws = new WebSocket(this.#url);\n ws.addEventListener(\"open\", (e) => {\n // eslint-disable-next-line no-console\n console.log(\"WebSocket open:\", e);\n this.#retryCount = 0;\n for (const msg of this.#queuedMessages) {\n ws.send(msg);\n }\n this.#queuedMessages.length = 0;\n });\n ws.addEventListener(\"close\", (e) => {\n if (this.#closed) {\n return;\n }\n // eslint-disable-next-line no-console\n console.log(\"WebSocket close:\", e);\n for (const listener of this.#closeListeners) {\n listener();\n }\n // Error code 1000 means that the connection was closed normally.\n if (e.code !== 1000) {\n this.#reconnect();\n }\n });\n ws.addEventListener(\"error\", (e) => {\n // No need to reconnect in error event listener,\n // there will always be a close event along with the error event.\n // eslint-disable-next-line no-console\n console.error(\"WebSocket error:\", e);\n });\n ws.addEventListener(\"message\", (e: MessageEvent<string>) => {\n const response = JSON.parse(e.data);\n for (const listener of this.#messageListeners) {\n listener(response);\n }\n });\n return ws;\n }\n\n #reconnect() {\n // istanbul ignore next: currently can't mock this\n if (this.#retryCount >= RETRY_LIMIT) {\n // eslint-disable-next-line no-console\n console.error(\"WebSocket connect retry limit exceeded\");\n return;\n }\n // Double the timeout for each retry\n const delay = Math.pow(2, this.#retryCount) * RETRY_TIMEOUT_UNIT;\n // eslint-disable-next-line no-console\n console.log(\"WebSocket will reconnect after %d seconds\", delay / 1000);\n setTimeout(() => {\n this.#retryCount++;\n this.#ws = this.#connect();\n }, delay);\n }\n\n send(data: unknown): void {\n // Connect when data is sent for the first time\n if (!this.#ws) {\n this.#ws = this.#connect();\n }\n const stringifiedData = JSON.stringify(data);\n if (this.#ws.readyState === WebSocket.OPEN) {\n this.#ws.send(stringifiedData);\n } else {\n this.#queuedMessages.push(stringifiedData);\n }\n }\n\n onMessage<T = unknown>(listener: MessageListener<T>) {\n this.#messageListeners.add(listener as MessageListener<unknown>);\n }\n\n onClose(listener: CloseListener) {\n this.#closeListeners.add(listener);\n }\n\n reset() {\n this.#queuedMessages.length = 0;\n this.#messageListeners.clear();\n this.#closeListeners.clear();\n }\n\n close() {\n this.#closed = true;\n if (this.#ws?.readyState === WebSocket.OPEN) {\n this.#ws.close();\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// istanbul ignore file
|
|
2
2
|
import { checkPermissions as _checkPermissions, preCheckPermissions, preCheckPermissionsForBrickOrRoute } from "./checkPermissions.js";
|
|
3
|
+
import { MessageDispatcher } from "./websocket/MessageDispatcher.js";
|
|
3
4
|
import * as _checkInstalledApps from "./checkInstalledApps.js";
|
|
4
5
|
export { _checkInstalledApps as checkInstalledApps };
|
|
5
6
|
import * as _flowApi from "./flowApi/index.js";
|
|
@@ -13,4 +14,5 @@ export var checkPermissions = Object.freeze({
|
|
|
13
14
|
preCheckPermissions,
|
|
14
15
|
preCheckPermissionsForBrickOrRoute
|
|
15
16
|
});
|
|
17
|
+
export var messageDispatcher = new MessageDispatcher();
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["checkPermissions","_checkPermissions","preCheckPermissions","preCheckPermissionsForBrickOrRoute","_checkInstalledApps","checkInstalledApps","_flowApi","flowApi","_auth","auth","_menu","menu","Object","freeze"],"sources":["../../src/index.ts"],"sourcesContent":["// istanbul ignore file\nimport {\n checkPermissions as _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n} from \"./checkPermissions.js\";\n\nexport * as checkInstalledApps from \"./checkInstalledApps.js\";\nexport * as flowApi from \"./flowApi/index.js\";\nexport * as auth from \"./auth.js\";\nexport * as menu from \"./menu/index.js\";\n\nexport const checkPermissions = Object.freeze({\n checkPermissions: _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n});\n"],"mappings":"AAAA;AACA,SACEA,gBAAgB,IAAIC,iBAAiB,EACrCC,mBAAmB,EACnBC,kCAAkC,QAC7B,uBAAuB;AAAC,YAAAC,mBAAA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["checkPermissions","_checkPermissions","preCheckPermissions","preCheckPermissionsForBrickOrRoute","MessageDispatcher","_checkInstalledApps","checkInstalledApps","_flowApi","flowApi","_auth","auth","_menu","menu","Object","freeze","messageDispatcher"],"sources":["../../src/index.ts"],"sourcesContent":["// istanbul ignore file\nimport {\n checkPermissions as _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n} from \"./checkPermissions.js\";\n\nimport { MessageDispatcher } from \"./websocket/MessageDispatcher.js\";\n\nexport * as checkInstalledApps from \"./checkInstalledApps.js\";\nexport * as flowApi from \"./flowApi/index.js\";\nexport * as auth from \"./auth.js\";\nexport * as menu from \"./menu/index.js\";\n\nexport const checkPermissions = Object.freeze({\n checkPermissions: _checkPermissions,\n preCheckPermissions,\n preCheckPermissionsForBrickOrRoute,\n});\n\nexport const messageDispatcher = new MessageDispatcher();\n"],"mappings":"AAAA;AACA,SACEA,gBAAgB,IAAIC,iBAAiB,EACrCC,mBAAmB,EACnBC,kCAAkC,QAC7B,uBAAuB;AAE9B,SAASC,iBAAiB,QAAQ,kCAAkC;AAAC,YAAAC,mBAAA,MAEjC,yBAAyB;AAAA,SAAAA,mBAAA,IAAjDC,kBAAkB;AAAA,YAAAC,QAAA,MACL,oBAAoB;AAAA,SAAAA,QAAA,IAAjCC,OAAO;AAAA,YAAAC,KAAA,MACG,WAAW;AAAA,SAAAA,KAAA,IAArBC,IAAI;AAAA,YAAAC,KAAA,MACM,iBAAiB;AAAA,SAAAA,KAAA,IAA3BC,IAAI;AAEhB,OAAO,IAAMZ,gBAAgB,GAAGa,MAAM,CAACC,MAAM,CAAC;EAC5Cd,gBAAgB,EAAEC,iBAAiB;EACnCC,mBAAmB;EACnBC;AACF,CAAC,CAAC;AAEF,OAAO,IAAMY,iBAAiB,GAAG,IAAIX,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import _classPrivateMethodInitSpec from "@babel/runtime/helpers/classPrivateMethodInitSpec";
|
|
2
|
+
import _classPrivateFieldInitSpec from "@babel/runtime/helpers/classPrivateFieldInitSpec";
|
|
3
|
+
import _classPrivateMethodGet from "@babel/runtime/helpers/classPrivateMethodGet";
|
|
4
|
+
import _classPrivateFieldSet from "@babel/runtime/helpers/classPrivateFieldSet";
|
|
5
|
+
import _classPrivateFieldGet from "@babel/runtime/helpers/classPrivateFieldGet";
|
|
6
|
+
import { getBasePath } from "@next-core/runtime";
|
|
7
|
+
import { escapeRegExp } from "lodash";
|
|
8
|
+
import { MessageService } from "./MessageService.js";
|
|
9
|
+
var _ms = /*#__PURE__*/new WeakMap();
|
|
10
|
+
var _memoizedChannels = /*#__PURE__*/new WeakMap();
|
|
11
|
+
var _channelPayloads = /*#__PURE__*/new WeakMap();
|
|
12
|
+
var _ms2 = /*#__PURE__*/new WeakMap();
|
|
13
|
+
var _subOrUnsub = /*#__PURE__*/new WeakSet();
|
|
14
|
+
export class MessageDispatcher {
|
|
15
|
+
constructor() {
|
|
16
|
+
_classPrivateMethodInitSpec(this, _subOrUnsub);
|
|
17
|
+
_classPrivateFieldInitSpec(this, _ms2, {
|
|
18
|
+
get: _get_ms,
|
|
19
|
+
set: void 0
|
|
20
|
+
});
|
|
21
|
+
_classPrivateFieldInitSpec(this, _ms, {
|
|
22
|
+
writable: true,
|
|
23
|
+
value: void 0
|
|
24
|
+
});
|
|
25
|
+
_classPrivateFieldInitSpec(this, _memoizedChannels, {
|
|
26
|
+
writable: true,
|
|
27
|
+
value: {
|
|
28
|
+
sub: new Map(),
|
|
29
|
+
unsub: new Map()
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
_classPrivateFieldInitSpec(this, _channelPayloads, {
|
|
33
|
+
writable: true,
|
|
34
|
+
value: new Map()
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
subscribe(channel, payload) {
|
|
38
|
+
var stringifiedPayload = JSON.stringify(payload);
|
|
39
|
+
return _classPrivateMethodGet(this, _subOrUnsub, _subOrUnsub2).call(this, "sub", channel, payload, stringifiedPayload);
|
|
40
|
+
}
|
|
41
|
+
unsubscribe(channel) {
|
|
42
|
+
var stringifiedPayload = _classPrivateFieldGet(this, _channelPayloads).get(channel);
|
|
43
|
+
if (!stringifiedPayload) {
|
|
44
|
+
var msg = "The message channel to unsubscribe \"".concat(channel, "\" is not found");
|
|
45
|
+
// eslint-disable-next-line no-console
|
|
46
|
+
console.error(msg);
|
|
47
|
+
return Promise.reject(new Error(msg));
|
|
48
|
+
}
|
|
49
|
+
var payload = JSON.parse(stringifiedPayload);
|
|
50
|
+
var result = _classPrivateMethodGet(this, _subOrUnsub, _subOrUnsub2).call(this, "unsub", channel, payload, stringifiedPayload);
|
|
51
|
+
_classPrivateFieldGet(this, _memoizedChannels).sub.delete(stringifiedPayload);
|
|
52
|
+
result.then(() => {
|
|
53
|
+
_classPrivateFieldGet(this, _channelPayloads).delete(channel);
|
|
54
|
+
});
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
onMessage(channel, listener) {
|
|
58
|
+
var stringifiedPayload = _classPrivateFieldGet(this, _channelPayloads).get(channel);
|
|
59
|
+
if (!stringifiedPayload) {
|
|
60
|
+
// eslint-disable-next-line no-console
|
|
61
|
+
console.error("Message channel: \"".concat(channel, "\" not found"));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
_classPrivateFieldGet(this, _ms2).onMessage(response => {
|
|
65
|
+
if (response.event === "MESSAGE.PUSH" && matchMessageChannel(stringifiedPayload, response.payload)) {
|
|
66
|
+
listener(response.payload.message);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
onClose(listener) {
|
|
71
|
+
_classPrivateFieldGet(this, _ms2).onClose(listener);
|
|
72
|
+
}
|
|
73
|
+
reset() {
|
|
74
|
+
var _classPrivateFieldGet2;
|
|
75
|
+
_classPrivateFieldGet(this, _memoizedChannels).sub.clear();
|
|
76
|
+
_classPrivateFieldGet(this, _memoizedChannels).unsub.clear();
|
|
77
|
+
_classPrivateFieldGet(this, _channelPayloads).clear();
|
|
78
|
+
(_classPrivateFieldGet2 = _classPrivateFieldGet(this, _ms)) === null || _classPrivateFieldGet2 === void 0 ? void 0 : _classPrivateFieldGet2.reset();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function _get_ms() {
|
|
82
|
+
if (!_classPrivateFieldGet(this, _ms)) {
|
|
83
|
+
var protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
84
|
+
var url = "".concat(protocol, "//").concat(window.location.host).concat(getBasePath(), "api/websocket_service/v1/ws");
|
|
85
|
+
_classPrivateFieldSet(this, _ms, new MessageService(url));
|
|
86
|
+
}
|
|
87
|
+
return _classPrivateFieldGet(this, _ms);
|
|
88
|
+
}
|
|
89
|
+
function _subOrUnsub2(type, channel, payload, stringifiedPayload) {
|
|
90
|
+
var hit = _classPrivateFieldGet(this, _memoizedChannels)[type].get(stringifiedPayload);
|
|
91
|
+
if (hit) {
|
|
92
|
+
return hit;
|
|
93
|
+
}
|
|
94
|
+
var request = {
|
|
95
|
+
event: type === "sub" ? "TOPIC.SUB" : "TOPIC.UNSUB",
|
|
96
|
+
payload
|
|
97
|
+
};
|
|
98
|
+
var promise = new Promise((resolve, reject) => {
|
|
99
|
+
var identity = getIdentity(payload);
|
|
100
|
+
_classPrivateFieldGet(this, _ms2).onMessage(response => {
|
|
101
|
+
var isSuccess = response.event === (type === "sub" ? "TOPIC.SUB_SUCCESS" : "TOPIC.UNSUB_SUCCESS");
|
|
102
|
+
var isFailed = response.event === (type === "sub" ? "TOPIC.SUB_FAILED" : "TOPIC.UNSUB_FAILED");
|
|
103
|
+
if ((isSuccess || isFailed) &&
|
|
104
|
+
// Put this after event type checks, to prevent unnecessary
|
|
105
|
+
// JSON stringify.
|
|
106
|
+
identity === getIdentity(response.payload)) {
|
|
107
|
+
(isSuccess ? resolve : reject)(response);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
_classPrivateFieldGet(this, _ms2).send(request);
|
|
111
|
+
});
|
|
112
|
+
if (type === "sub") {
|
|
113
|
+
_classPrivateFieldGet(this, _channelPayloads).set(channel, stringifiedPayload);
|
|
114
|
+
}
|
|
115
|
+
_classPrivateFieldGet(this, _memoizedChannels)[type].set(stringifiedPayload, promise);
|
|
116
|
+
return promise;
|
|
117
|
+
}
|
|
118
|
+
function getIdentity(payload) {
|
|
119
|
+
var {
|
|
120
|
+
system,
|
|
121
|
+
topic
|
|
122
|
+
} = payload;
|
|
123
|
+
return JSON.stringify({
|
|
124
|
+
system,
|
|
125
|
+
topic
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function matchMessageChannel(stringifiedPayload, responsePayload) {
|
|
129
|
+
var payload = JSON.parse(stringifiedPayload);
|
|
130
|
+
return payload.system === responsePayload.system && (
|
|
131
|
+
// Exact match
|
|
132
|
+
payload.topic === responsePayload.topic ||
|
|
133
|
+
// Wildcards match
|
|
134
|
+
// For `ab.cd.*`:
|
|
135
|
+
// - Matches `ab.cd.r` or `ab.cd.x.yz`
|
|
136
|
+
// - DOES NOT match `ab.cd.x/yz` or `ab.x.cd` or `x.ab.cd.yz`
|
|
137
|
+
typeof payload.topic === "string" && payload.topic.includes("*") && new RegExp("^".concat(payload.topic.replace(/([^*]*)\*([^*]*)/g, (m, p1, p2) => "".concat(escapeRegExp(p1), "[^/]*").concat(escapeRegExp(p2))), "$")).test(responsePayload.topic));
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=MessageDispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageDispatcher.js","names":["getBasePath","escapeRegExp","MessageService","_ms","WeakMap","_memoizedChannels","_channelPayloads","_ms2","_subOrUnsub","WeakSet","MessageDispatcher","constructor","_classPrivateMethodInitSpec","_classPrivateFieldInitSpec","get","_get_ms","set","writable","value","sub","Map","unsub","subscribe","channel","payload","stringifiedPayload","JSON","stringify","_classPrivateMethodGet","_subOrUnsub2","call","unsubscribe","_classPrivateFieldGet","msg","concat","console","error","Promise","reject","Error","parse","result","delete","then","onMessage","listener","response","event","matchMessageChannel","message","onClose","reset","_classPrivateFieldGet2","clear","protocol","location","url","window","host","_classPrivateFieldSet","type","hit","request","promise","resolve","identity","getIdentity","isSuccess","isFailed","send","system","topic","responsePayload","includes","RegExp","replace","m","p1","p2","test"],"sources":["../../../src/websocket/MessageDispatcher.ts"],"sourcesContent":["import { getBasePath } from \"@next-core/runtime\";\nimport { escapeRegExp } from \"lodash\";\nimport {\n MessageService,\n type MessageListener,\n CloseListener,\n} from \"./MessageService.js\";\n\ninterface MessageResponse {\n event:\n | \"TOPIC.SUB_SUCCESS\"\n | \"TOPIC.SUB_FAILED\"\n | \"TOPIC.UNSUB_SUCCESS\"\n | \"TOPIC.UNSUB_FAILED\"\n | \"MESSAGE.PUSH\";\n payload: MessagePayload;\n}\n\ninterface MessagePayload {\n source?: string;\n system: string;\n topic: string;\n message?: unknown;\n}\n\nexport class MessageDispatcher {\n #_ms: MessageService | undefined;\n #memoizedChannels = {\n sub: new Map<string, Promise<unknown>>(),\n unsub: new Map<string, Promise<unknown>>(),\n };\n #channelPayloads = new Map<string, string>();\n\n get #ms(): MessageService {\n if (!this.#_ms) {\n const protocol = location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n const url = `${protocol}//${\n window.location.host\n }${getBasePath()}api/websocket_service/v1/ws`;\n this.#_ms = new MessageService(url);\n }\n return this.#_ms;\n }\n\n subscribe(channel: string, payload: MessagePayload): Promise<unknown> {\n const stringifiedPayload = JSON.stringify(payload);\n return this.#subOrUnsub(\"sub\", channel, payload, stringifiedPayload);\n }\n\n unsubscribe(channel: string): Promise<unknown> {\n const stringifiedPayload = this.#channelPayloads.get(channel);\n if (!stringifiedPayload) {\n const msg = `The message channel to unsubscribe \"${channel}\" is not found`;\n // eslint-disable-next-line no-console\n console.error(msg);\n return Promise.reject(new Error(msg));\n }\n\n const payload = JSON.parse(stringifiedPayload);\n const result = this.#subOrUnsub(\n \"unsub\",\n channel,\n payload,\n stringifiedPayload\n );\n\n this.#memoizedChannels.sub.delete(stringifiedPayload);\n\n result.then(() => {\n this.#channelPayloads.delete(channel);\n });\n\n return result;\n }\n\n onMessage(channel: string, listener: MessageListener): void {\n const stringifiedPayload = this.#channelPayloads.get(channel);\n if (!stringifiedPayload) {\n // eslint-disable-next-line no-console\n console.error(`Message channel: \"${channel}\" not found`);\n return;\n }\n\n this.#ms.onMessage<MessageResponse>((response) => {\n if (\n response.event === \"MESSAGE.PUSH\" &&\n matchMessageChannel(stringifiedPayload, response.payload)\n ) {\n listener(response.payload.message);\n }\n });\n }\n\n onClose(listener: CloseListener): void {\n this.#ms.onClose(listener);\n }\n\n reset(): void {\n this.#memoizedChannels.sub.clear();\n this.#memoizedChannels.unsub.clear();\n this.#channelPayloads.clear();\n this.#_ms?.reset();\n }\n\n #subOrUnsub(\n type: \"sub\" | \"unsub\",\n channel: string,\n payload: MessagePayload,\n stringifiedPayload: string\n ): Promise<unknown> {\n const hit = this.#memoizedChannels[type].get(stringifiedPayload);\n if (hit) {\n return hit;\n }\n const request = {\n event: type === \"sub\" ? \"TOPIC.SUB\" : \"TOPIC.UNSUB\",\n payload,\n };\n const promise = new Promise((resolve, reject) => {\n const identity = getIdentity(payload);\n this.#ms.onMessage<MessageResponse>((response) => {\n const isSuccess =\n response.event ===\n (type === \"sub\" ? \"TOPIC.SUB_SUCCESS\" : \"TOPIC.UNSUB_SUCCESS\");\n const isFailed =\n response.event ===\n (type === \"sub\" ? \"TOPIC.SUB_FAILED\" : \"TOPIC.UNSUB_FAILED\");\n if (\n (isSuccess || isFailed) &&\n // Put this after event type checks, to prevent unnecessary\n // JSON stringify.\n identity === getIdentity(response.payload)\n ) {\n (isSuccess ? resolve : reject)(response);\n }\n });\n this.#ms.send(request);\n });\n\n if (type === \"sub\") {\n this.#channelPayloads.set(channel, stringifiedPayload);\n }\n this.#memoizedChannels[type].set(stringifiedPayload, promise);\n return promise;\n }\n}\n\nfunction getIdentity(payload: MessagePayload) {\n const { system, topic } = payload;\n return JSON.stringify({ system, topic });\n}\n\nfunction matchMessageChannel(\n stringifiedPayload: string,\n responsePayload: MessagePayload\n): boolean {\n const payload = JSON.parse(stringifiedPayload) as MessagePayload;\n return (\n payload.system === responsePayload.system &&\n // Exact match\n (payload.topic === responsePayload.topic ||\n // Wildcards match\n // For `ab.cd.*`:\n // - Matches `ab.cd.r` or `ab.cd.x.yz`\n // - DOES NOT match `ab.cd.x/yz` or `ab.x.cd` or `x.ab.cd.yz`\n (typeof payload.topic === \"string\" &&\n payload.topic.includes(\"*\") &&\n new RegExp(\n `^${payload.topic.replace(\n /([^*]*)\\*([^*]*)/g,\n (m, p1, p2) => `${escapeRegExp(p1)}[^/]*${escapeRegExp(p2)}`\n )}$`\n ).test(responsePayload.topic)))\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import _classPrivateMethodInitSpec from "@babel/runtime/helpers/classPrivateMethodInitSpec";
|
|
2
|
+
import _classPrivateFieldInitSpec from "@babel/runtime/helpers/classPrivateFieldInitSpec";
|
|
3
|
+
import _classPrivateMethodGet from "@babel/runtime/helpers/classPrivateMethodGet";
|
|
4
|
+
import _classPrivateFieldGet from "@babel/runtime/helpers/classPrivateFieldGet";
|
|
5
|
+
import _classPrivateFieldSet from "@babel/runtime/helpers/classPrivateFieldSet";
|
|
6
|
+
var RETRY_TIMEOUT_UNIT = 1000;
|
|
7
|
+
var RETRY_LIMIT = 6;
|
|
8
|
+
var _url = /*#__PURE__*/new WeakMap();
|
|
9
|
+
var _ws = /*#__PURE__*/new WeakMap();
|
|
10
|
+
var _queuedMessages = /*#__PURE__*/new WeakMap();
|
|
11
|
+
var _messageListeners = /*#__PURE__*/new WeakMap();
|
|
12
|
+
var _closeListeners = /*#__PURE__*/new WeakMap();
|
|
13
|
+
var _retryCount = /*#__PURE__*/new WeakMap();
|
|
14
|
+
var _closed = /*#__PURE__*/new WeakMap();
|
|
15
|
+
var _connect = /*#__PURE__*/new WeakSet();
|
|
16
|
+
var _reconnect = /*#__PURE__*/new WeakSet();
|
|
17
|
+
export class MessageService {
|
|
18
|
+
constructor(url) {
|
|
19
|
+
_classPrivateMethodInitSpec(this, _reconnect);
|
|
20
|
+
_classPrivateMethodInitSpec(this, _connect);
|
|
21
|
+
_classPrivateFieldInitSpec(this, _url, {
|
|
22
|
+
writable: true,
|
|
23
|
+
value: void 0
|
|
24
|
+
});
|
|
25
|
+
_classPrivateFieldInitSpec(this, _ws, {
|
|
26
|
+
writable: true,
|
|
27
|
+
value: void 0
|
|
28
|
+
});
|
|
29
|
+
_classPrivateFieldInitSpec(this, _queuedMessages, {
|
|
30
|
+
writable: true,
|
|
31
|
+
value: []
|
|
32
|
+
});
|
|
33
|
+
_classPrivateFieldInitSpec(this, _messageListeners, {
|
|
34
|
+
writable: true,
|
|
35
|
+
value: new Set()
|
|
36
|
+
});
|
|
37
|
+
_classPrivateFieldInitSpec(this, _closeListeners, {
|
|
38
|
+
writable: true,
|
|
39
|
+
value: new Set()
|
|
40
|
+
});
|
|
41
|
+
_classPrivateFieldInitSpec(this, _retryCount, {
|
|
42
|
+
writable: true,
|
|
43
|
+
value: 0
|
|
44
|
+
});
|
|
45
|
+
_classPrivateFieldInitSpec(this, _closed, {
|
|
46
|
+
writable: true,
|
|
47
|
+
value: false
|
|
48
|
+
});
|
|
49
|
+
_classPrivateFieldSet(this, _url, url);
|
|
50
|
+
}
|
|
51
|
+
send(data) {
|
|
52
|
+
// Connect when data is sent for the first time
|
|
53
|
+
if (!_classPrivateFieldGet(this, _ws)) {
|
|
54
|
+
_classPrivateFieldSet(this, _ws, _classPrivateMethodGet(this, _connect, _connect2).call(this));
|
|
55
|
+
}
|
|
56
|
+
var stringifiedData = JSON.stringify(data);
|
|
57
|
+
if (_classPrivateFieldGet(this, _ws).readyState === WebSocket.OPEN) {
|
|
58
|
+
_classPrivateFieldGet(this, _ws).send(stringifiedData);
|
|
59
|
+
} else {
|
|
60
|
+
_classPrivateFieldGet(this, _queuedMessages).push(stringifiedData);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
onMessage(listener) {
|
|
64
|
+
_classPrivateFieldGet(this, _messageListeners).add(listener);
|
|
65
|
+
}
|
|
66
|
+
onClose(listener) {
|
|
67
|
+
_classPrivateFieldGet(this, _closeListeners).add(listener);
|
|
68
|
+
}
|
|
69
|
+
reset() {
|
|
70
|
+
_classPrivateFieldGet(this, _queuedMessages).length = 0;
|
|
71
|
+
_classPrivateFieldGet(this, _messageListeners).clear();
|
|
72
|
+
_classPrivateFieldGet(this, _closeListeners).clear();
|
|
73
|
+
}
|
|
74
|
+
close() {
|
|
75
|
+
var _classPrivateFieldGet2;
|
|
76
|
+
_classPrivateFieldSet(this, _closed, true);
|
|
77
|
+
if (((_classPrivateFieldGet2 = _classPrivateFieldGet(this, _ws)) === null || _classPrivateFieldGet2 === void 0 ? void 0 : _classPrivateFieldGet2.readyState) === WebSocket.OPEN) {
|
|
78
|
+
_classPrivateFieldGet(this, _ws).close();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function _connect2() {
|
|
83
|
+
// eslint-disable-next-line no-console
|
|
84
|
+
console.log("WebSocket connecting ...");
|
|
85
|
+
var ws = new WebSocket(_classPrivateFieldGet(this, _url));
|
|
86
|
+
ws.addEventListener("open", e => {
|
|
87
|
+
// eslint-disable-next-line no-console
|
|
88
|
+
console.log("WebSocket open:", e);
|
|
89
|
+
_classPrivateFieldSet(this, _retryCount, 0);
|
|
90
|
+
for (var msg of _classPrivateFieldGet(this, _queuedMessages)) {
|
|
91
|
+
ws.send(msg);
|
|
92
|
+
}
|
|
93
|
+
_classPrivateFieldGet(this, _queuedMessages).length = 0;
|
|
94
|
+
});
|
|
95
|
+
ws.addEventListener("close", e => {
|
|
96
|
+
if (_classPrivateFieldGet(this, _closed)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// eslint-disable-next-line no-console
|
|
100
|
+
console.log("WebSocket close:", e);
|
|
101
|
+
for (var listener of _classPrivateFieldGet(this, _closeListeners)) {
|
|
102
|
+
listener();
|
|
103
|
+
}
|
|
104
|
+
// Error code 1000 means that the connection was closed normally.
|
|
105
|
+
if (e.code !== 1000) {
|
|
106
|
+
_classPrivateMethodGet(this, _reconnect, _reconnect2).call(this);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
ws.addEventListener("error", e => {
|
|
110
|
+
// No need to reconnect in error event listener,
|
|
111
|
+
// there will always be a close event along with the error event.
|
|
112
|
+
// eslint-disable-next-line no-console
|
|
113
|
+
console.error("WebSocket error:", e);
|
|
114
|
+
});
|
|
115
|
+
ws.addEventListener("message", e => {
|
|
116
|
+
var response = JSON.parse(e.data);
|
|
117
|
+
for (var listener of _classPrivateFieldGet(this, _messageListeners)) {
|
|
118
|
+
listener(response);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return ws;
|
|
122
|
+
}
|
|
123
|
+
function _reconnect2() {
|
|
124
|
+
// istanbul ignore next: currently can't mock this
|
|
125
|
+
if (_classPrivateFieldGet(this, _retryCount) >= RETRY_LIMIT) {
|
|
126
|
+
// eslint-disable-next-line no-console
|
|
127
|
+
console.error("WebSocket connect retry limit exceeded");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// Double the timeout for each retry
|
|
131
|
+
var delay = Math.pow(2, _classPrivateFieldGet(this, _retryCount)) * RETRY_TIMEOUT_UNIT;
|
|
132
|
+
// eslint-disable-next-line no-console
|
|
133
|
+
console.log("WebSocket will reconnect after %d seconds", delay / 1000);
|
|
134
|
+
setTimeout(() => {
|
|
135
|
+
var _this$retryCount, _this$retryCount2;
|
|
136
|
+
_classPrivateFieldSet(this, _retryCount, (_this$retryCount = _classPrivateFieldGet(this, _retryCount), _this$retryCount2 = _this$retryCount++, _this$retryCount)), _this$retryCount2;
|
|
137
|
+
_classPrivateFieldSet(this, _ws, _classPrivateMethodGet(this, _connect, _connect2).call(this));
|
|
138
|
+
}, delay);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=MessageService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageService.js","names":["RETRY_TIMEOUT_UNIT","RETRY_LIMIT","_url","WeakMap","_ws","_queuedMessages","_messageListeners","_closeListeners","_retryCount","_closed","_connect","WeakSet","_reconnect","MessageService","constructor","url","_classPrivateMethodInitSpec","_classPrivateFieldInitSpec","writable","value","Set","_classPrivateFieldSet","send","data","_classPrivateFieldGet","_classPrivateMethodGet","_connect2","call","stringifiedData","JSON","stringify","readyState","WebSocket","OPEN","push","onMessage","listener","add","onClose","reset","length","clear","close","_classPrivateFieldGet2","console","log","ws","addEventListener","e","msg","code","_reconnect2","error","response","parse","delay","Math","pow","setTimeout","_this$retryCount","_this$retryCount2"],"sources":["../../../src/websocket/MessageService.ts"],"sourcesContent":["export type MessageListener<T = unknown> = (response: T) => void;\nexport type CloseListener = () => void;\n\nconst RETRY_TIMEOUT_UNIT = 1000;\nconst RETRY_LIMIT = 6;\n\nexport class MessageService {\n #url: string;\n #ws: WebSocket | undefined;\n #queuedMessages: string[] = [];\n #messageListeners = new Set<MessageListener>();\n #closeListeners = new Set<CloseListener>();\n #retryCount = 0;\n #closed = false;\n\n constructor(url: string) {\n this.#url = url;\n }\n\n #connect(): WebSocket {\n // eslint-disable-next-line no-console\n console.log(\"WebSocket connecting ...\");\n const ws = new WebSocket(this.#url);\n ws.addEventListener(\"open\", (e) => {\n // eslint-disable-next-line no-console\n console.log(\"WebSocket open:\", e);\n this.#retryCount = 0;\n for (const msg of this.#queuedMessages) {\n ws.send(msg);\n }\n this.#queuedMessages.length = 0;\n });\n ws.addEventListener(\"close\", (e) => {\n if (this.#closed) {\n return;\n }\n // eslint-disable-next-line no-console\n console.log(\"WebSocket close:\", e);\n for (const listener of this.#closeListeners) {\n listener();\n }\n // Error code 1000 means that the connection was closed normally.\n if (e.code !== 1000) {\n this.#reconnect();\n }\n });\n ws.addEventListener(\"error\", (e) => {\n // No need to reconnect in error event listener,\n // there will always be a close event along with the error event.\n // eslint-disable-next-line no-console\n console.error(\"WebSocket error:\", e);\n });\n ws.addEventListener(\"message\", (e: MessageEvent<string>) => {\n const response = JSON.parse(e.data);\n for (const listener of this.#messageListeners) {\n listener(response);\n }\n });\n return ws;\n }\n\n #reconnect() {\n // istanbul ignore next: currently can't mock this\n if (this.#retryCount >= RETRY_LIMIT) {\n // eslint-disable-next-line no-console\n console.error(\"WebSocket connect retry limit exceeded\");\n return;\n }\n // Double the timeout for each retry\n const delay = Math.pow(2, this.#retryCount) * RETRY_TIMEOUT_UNIT;\n // eslint-disable-next-line no-console\n console.log(\"WebSocket will reconnect after %d seconds\", delay / 1000);\n setTimeout(() => {\n this.#retryCount++;\n this.#ws = this.#connect();\n }, delay);\n }\n\n send(data: unknown): void {\n // Connect when data is sent for the first time\n if (!this.#ws) {\n this.#ws = this.#connect();\n }\n const stringifiedData = JSON.stringify(data);\n if (this.#ws.readyState === WebSocket.OPEN) {\n this.#ws.send(stringifiedData);\n } else {\n this.#queuedMessages.push(stringifiedData);\n }\n }\n\n onMessage<T = unknown>(listener: MessageListener<T>) {\n this.#messageListeners.add(listener as MessageListener<unknown>);\n }\n\n onClose(listener: CloseListener) {\n this.#closeListeners.add(listener);\n }\n\n reset() {\n this.#queuedMessages.length = 0;\n this.#messageListeners.clear();\n this.#closeListeners.clear();\n }\n\n close() {\n this.#closed = true;\n if (this.#ws?.readyState === WebSocket.OPEN) {\n this.#ws.close();\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { checkPermissions as _checkPermissions, preCheckPermissions, preCheckPermissionsForBrickOrRoute } from "./checkPermissions.js";
|
|
2
|
+
import { MessageDispatcher } from "./websocket/MessageDispatcher.js";
|
|
2
3
|
export * as checkInstalledApps from "./checkInstalledApps.js";
|
|
3
4
|
export * as flowApi from "./flowApi/index.js";
|
|
4
5
|
export * as auth from "./auth.js";
|
|
@@ -8,3 +9,4 @@ export declare const checkPermissions: Readonly<{
|
|
|
8
9
|
preCheckPermissions: typeof preCheckPermissions;
|
|
9
10
|
preCheckPermissionsForBrickOrRoute: typeof preCheckPermissionsForBrickOrRoute;
|
|
10
11
|
}>;
|
|
12
|
+
export declare const messageDispatcher: MessageDispatcher;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type MessageListener, CloseListener } from "./MessageService.js";
|
|
2
|
+
interface MessagePayload {
|
|
3
|
+
source?: string;
|
|
4
|
+
system: string;
|
|
5
|
+
topic: string;
|
|
6
|
+
message?: unknown;
|
|
7
|
+
}
|
|
8
|
+
export declare class MessageDispatcher {
|
|
9
|
+
#private;
|
|
10
|
+
subscribe(channel: string, payload: MessagePayload): Promise<unknown>;
|
|
11
|
+
unsubscribe(channel: string): Promise<unknown>;
|
|
12
|
+
onMessage(channel: string, listener: MessageListener): void;
|
|
13
|
+
onClose(listener: CloseListener): void;
|
|
14
|
+
reset(): void;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type MessageListener<T = unknown> = (response: T) => void;
|
|
2
|
+
export type CloseListener = () => void;
|
|
3
|
+
export declare class MessageService {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(url: string);
|
|
6
|
+
send(data: unknown): void;
|
|
7
|
+
onMessage<T = unknown>(listener: MessageListener<T>): void;
|
|
8
|
+
onClose(listener: CloseListener): void;
|
|
9
|
+
reset(): void;
|
|
10
|
+
close(): void;
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@next-core/easyops-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"homepage": "https://github.com/easyops-cn/next-core/tree/v3/packages/easyops-runtime",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"repository": {
|
|
@@ -45,15 +45,16 @@
|
|
|
45
45
|
"@next-api-sdk/micro-app-sdk": "^1.2.1",
|
|
46
46
|
"@next-api-sdk/micro-app-standalone-sdk": "^1.1.0",
|
|
47
47
|
"@next-core/http": "^1.0.6",
|
|
48
|
-
"@next-core/runtime": "^1.
|
|
49
|
-
"@next-core/types": "^1.
|
|
50
|
-
"@next-core/utils": "^1.5.
|
|
48
|
+
"@next-core/runtime": "^1.17.0",
|
|
49
|
+
"@next-core/types": "^1.5.0",
|
|
50
|
+
"@next-core/utils": "^1.5.4",
|
|
51
51
|
"js-yaml": "^3.14.1",
|
|
52
52
|
"lodash": "^4.17.21"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@next-core/build-next-libs": "^1.0.5",
|
|
56
|
-
"@next-core/test-next": "^1.0.6"
|
|
56
|
+
"@next-core/test-next": "^1.0.6",
|
|
57
|
+
"jest-websocket-mock": "^2.4.0"
|
|
57
58
|
},
|
|
58
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "1277be9befefadd87cde69797a1786b69f242a4e"
|
|
59
60
|
}
|