@polkadot-api/json-rpc-provider-proxy 0.2.1 → 0.2.3

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.
@@ -0,0 +1,101 @@
1
+ import { jsonRpcMsg } from './json-rpc-message.mjs';
2
+
3
+ const unfollowMethods = new Set(
4
+ ["v1", "unstable"].map((x) => `chainHead_${x}_unfollow`)
5
+ );
6
+ const getProxy = (toConsumer) => {
7
+ let state = {
8
+ type: 1 /* Connecting */,
9
+ pending: []
10
+ };
11
+ const onMsgFromProvider = (msg) => {
12
+ if (state.type === 0 /* Connected */) {
13
+ const parsed = JSON.parse(msg);
14
+ if ("id" in parsed) {
15
+ if (state.onGoingRequests.get(parsed.id)?.type === 0 /* ChainHeadFollow */)
16
+ state.activeChainHeads.add(parsed.result);
17
+ state.onGoingRequests.delete(parsed.id);
18
+ } else {
19
+ const { subscription, result } = parsed.params;
20
+ if (result?.event === "stop")
21
+ state.activeChainHeads.delete(subscription);
22
+ }
23
+ }
24
+ if (state.type !== 2 /* Done */) toConsumer(msg);
25
+ };
26
+ const send = (msg) => {
27
+ if (state.type === 2 /* Done */) return;
28
+ if (state.type === 1 /* Connecting */) {
29
+ state.pending.push(msg);
30
+ return;
31
+ }
32
+ const parsed = JSON.parse(msg);
33
+ if (unfollowMethods.has(parsed.method))
34
+ state.activeChainHeads.delete(parsed.params[0]);
35
+ if ("id" in parsed) {
36
+ const { method, id } = parsed;
37
+ const ongoingMsg = method.startsWith("chainHead") ? method.endsWith("follow") ? {
38
+ type: 0 /* ChainHeadFollow */,
39
+ msg
40
+ } : { type: 1 /* ChainHeadOperation */, id } : { type: 2 /* Other */, msg };
41
+ state.onGoingRequests.set(id, ongoingMsg);
42
+ }
43
+ state.connection.send(msg);
44
+ };
45
+ return {
46
+ send,
47
+ disconnect: () => {
48
+ if (state.type === 2 /* Done */) return;
49
+ if (state.type === 0 /* Connected */) state.connection.disconnect();
50
+ state = { type: 2 /* Done */ };
51
+ },
52
+ connect: (cb) => {
53
+ if (state.type !== 1 /* Connecting */) throw new Error("Nonesense");
54
+ const { pending } = state;
55
+ const onGoingRequests = /* @__PURE__ */ new Map();
56
+ const activeChainHeads = /* @__PURE__ */ new Set();
57
+ const onHalt = () => {
58
+ state = {
59
+ type: 1 /* Connecting */,
60
+ pending: []
61
+ };
62
+ activeChainHeads.forEach((subscription) => {
63
+ onMsgFromProvider(
64
+ jsonRpcMsg({
65
+ params: {
66
+ subscription,
67
+ result: {
68
+ event: "stop",
69
+ internal: true
70
+ }
71
+ }
72
+ })
73
+ );
74
+ });
75
+ activeChainHeads.clear();
76
+ for (const x of onGoingRequests.values()) {
77
+ if (x.type === 1 /* ChainHeadOperation */)
78
+ onMsgFromProvider(
79
+ jsonRpcMsg({
80
+ id: x.id,
81
+ error: { code: -32603, message: "Internal error" },
82
+ internal: true
83
+ })
84
+ );
85
+ else send(x.msg);
86
+ }
87
+ onGoingRequests.clear();
88
+ };
89
+ state = {
90
+ type: 0 /* Connected */,
91
+ connection: cb(onMsgFromProvider, onHalt),
92
+ onGoingRequests,
93
+ activeChainHeads
94
+ };
95
+ pending.forEach(send);
96
+ }
97
+ };
98
+ };
99
+
100
+ export { getProxy };
101
+ //# sourceMappingURL=get-proxy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-proxy.mjs","sources":["../../src/get-proxy.ts"],"sourcesContent":["import { JsonRpcConnection } from \"@polkadot-api/json-rpc-provider\"\nimport { ReconnectableJsonRpcConnection } from \"./internal-types\"\nimport { jsonRpcMsg } from \"./json-rpc-message\"\n\nconst enum State {\n Connected,\n Connecting,\n Done,\n}\n\nconst enum OngoingMsgType {\n ChainHeadFollow,\n ChainHeadOperation,\n Other,\n}\ntype OngoingMsg =\n | {\n type: OngoingMsgType.ChainHeadFollow\n msg: string\n }\n | { type: OngoingMsgType.ChainHeadOperation; id: string }\n | { type: OngoingMsgType.Other; msg: string }\n\nconst unfollowMethods = new Set(\n [\"v1\", \"unstable\"].map((x) => `chainHead_${x}_unfollow`),\n)\n\nexport const getProxy: ReconnectableJsonRpcConnection = (\n toConsumer: (msg: string) => void,\n) => {\n let state:\n | {\n type: State.Connected\n connection: JsonRpcConnection\n onGoingRequests: Map<string, OngoingMsg>\n activeChainHeads: Set<string>\n }\n | { type: State.Connecting; pending: Array<string> }\n | { type: State.Done } = {\n type: State.Connecting,\n pending: [],\n }\n\n const onMsgFromProvider = (msg: string) => {\n if (state.type === State.Connected) {\n const parsed = JSON.parse(msg)\n if (\"id\" in parsed) {\n if (\n state.onGoingRequests.get(parsed.id)?.type ===\n OngoingMsgType.ChainHeadFollow\n )\n state.activeChainHeads.add(parsed.result)\n state.onGoingRequests.delete(parsed.id)\n } else {\n const { subscription, result } = parsed.params\n if (result?.event === \"stop\")\n state.activeChainHeads.delete(subscription)\n }\n }\n // If the state is \"Connecting\", then these are messages\n // sent from the `onHalt` function. So, we mus realy them\n if (state.type !== State.Done) toConsumer(msg)\n }\n\n const send = (msg: string) => {\n if (state.type === State.Done) return\n if (state.type === State.Connecting) {\n state.pending.push(msg)\n return\n }\n const parsed = JSON.parse(msg)\n if (unfollowMethods.has(parsed.method))\n state.activeChainHeads.delete(parsed.params[0])\n\n if (\"id\" in parsed) {\n const { method, id } = parsed as { method: string; id: string }\n const ongoingMsg: OngoingMsg = method.startsWith(\"chainHead\")\n ? method.endsWith(\"follow\")\n ? {\n type: OngoingMsgType.ChainHeadFollow,\n msg,\n }\n : { type: OngoingMsgType.ChainHeadOperation, id }\n : { type: OngoingMsgType.Other, msg }\n state.onGoingRequests.set(id, ongoingMsg)\n }\n\n state.connection.send(msg)\n }\n\n return {\n send,\n disconnect: () => {\n if (state.type === State.Done) return\n if (state.type === State.Connected) state.connection.disconnect()\n state = { type: State.Done }\n },\n connect: (cb) => {\n if (state.type !== State.Connecting) throw new Error(\"Nonesense\")\n\n const { pending } = state\n const onGoingRequests = new Map<string, OngoingMsg>()\n const activeChainHeads = new Set<string>()\n const onHalt = () => {\n state = {\n type: State.Connecting,\n pending: [],\n }\n activeChainHeads.forEach((subscription) => {\n // We don't send the messages directy to the consumer\n // b/c they could have disconnected after receiving one\n // of these messages. The `onMsgFromProvider` fn handles that\n onMsgFromProvider(\n jsonRpcMsg({\n params: {\n subscription,\n result: {\n event: \"stop\",\n internal: true,\n },\n },\n }),\n )\n })\n activeChainHeads.clear()\n for (const x of onGoingRequests.values()) {\n if (x.type === OngoingMsgType.ChainHeadOperation)\n onMsgFromProvider(\n jsonRpcMsg({\n id: x.id,\n error: { code: -32603, message: \"Internal error\" },\n internal: true,\n }),\n )\n else send(x.msg)\n }\n onGoingRequests.clear()\n }\n state = {\n type: State.Connected,\n connection: cb(onMsgFromProvider, onHalt),\n onGoingRequests,\n activeChainHeads,\n }\n pending.forEach(send)\n },\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,95 +1,44 @@
1
- import { getSubscriptionManager } from './subscription-manager/subscription-manager.mjs';
2
- import { jsonRpcMsg } from './json-rpc-message.mjs';
1
+ import { getProxy } from './get-proxy.mjs';
3
2
 
4
3
  const getSyncProvider = (input) => (onMessage) => {
5
- let provider;
6
- let bufferedMessages = [];
7
- const pendingResponses = /* @__PURE__ */ new Set();
8
- const subscriptionManager = getSubscriptionManager(onMessage);
9
- const onMessageProxy = (message) => {
10
- let parsed;
11
- try {
12
- parsed = JSON.parse(message);
13
- } catch (_) {
14
- console.error(`Unable to parse incoming message: ${message}`);
15
- return;
16
- }
17
- if (parsed.id !== void 0) {
18
- pendingResponses.delete(parsed.id);
19
- subscriptionManager.onResponse(parsed);
20
- } else {
21
- subscriptionManager.onNotifiaction(parsed);
22
- }
23
- onMessage(message);
24
- };
25
- const send = (message) => {
26
- if (!provider) return;
27
- const parsed = JSON.parse(message);
28
- subscriptionManager.onSent(parsed);
29
- if (parsed.id) pendingResponses.add(parsed.id);
30
- if (provider instanceof Promise) {
31
- bufferedMessages.push(message);
32
- } else provider.send(message);
33
- };
34
- const onHalt = () => {
35
- bufferedMessages = [];
36
- const pendingResponsesCopy = [...pendingResponses];
37
- pendingResponses.clear();
38
- if (!provider) throw null;
39
- const result = start();
40
- subscriptionManager.onAbort();
41
- pendingResponsesCopy.forEach((id) => {
42
- onMessage(
43
- jsonRpcMsg({
44
- error: { code: -32603, message: "Internal error" },
45
- id
46
- })
47
- );
48
- });
49
- return result;
50
- };
4
+ let proxy = getProxy(onMessage);
51
5
  const start = () => {
52
- const onResolve = (getProvider) => {
53
- let alive = true;
54
- const _onHalt = () => {
55
- if (alive) {
56
- alive = false;
57
- onHalt();
58
- }
59
- };
60
- const _onMessageProxy = (msg) => {
61
- if (alive) onMessageProxy(msg);
62
- };
63
- const result = getProvider(_onMessageProxy, _onHalt);
64
- bufferedMessages.forEach((m) => {
65
- result.send(m);
66
- });
67
- bufferedMessages = [];
68
- return provider = result;
69
- };
70
- provider = input().then(onResolve, withMacroTask(onHalt));
71
- return provider;
72
- };
73
- const disconnect = () => {
74
- if (!provider) return;
75
- const finishIt = (input2) => {
76
- subscriptionManager.onDisconnect();
77
- pendingResponses.clear();
78
- provider = null;
79
- input2?.disconnect();
80
- };
81
- if (provider instanceof Promise) {
82
- provider.then(finishIt, finishIt);
83
- provider = null;
84
- } else finishIt(provider);
6
+ input().then(
7
+ (cb) => {
8
+ if (!proxy) {
9
+ try {
10
+ cb(
11
+ () => {
12
+ },
13
+ () => {
14
+ }
15
+ ).disconnect();
16
+ } catch (_) {
17
+ }
18
+ } else
19
+ proxy.connect(
20
+ (onMsg, onHalt) => cb(onMsg, () => {
21
+ onHalt();
22
+ start();
23
+ })
24
+ );
25
+ },
26
+ () => {
27
+ proxy && setTimeout(start, 0);
28
+ }
29
+ );
85
30
  };
86
31
  start();
87
32
  return {
88
- send,
89
- disconnect
33
+ send: (msg) => {
34
+ proxy?.send(msg);
35
+ },
36
+ disconnect: () => {
37
+ proxy?.disconnect();
38
+ proxy = null;
39
+ }
90
40
  };
91
41
  };
92
- const withMacroTask = (inputFn) => (...args) => new Promise((res) => setTimeout(res, 0)).then(() => inputFn(...args));
93
42
 
94
43
  export { getSyncProvider };
95
44
  //# sourceMappingURL=get-sync-provider.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-sync-provider.mjs","sources":["../../src/get-sync-provider.ts"],"sourcesContent":["import type { RequestId } from \"./internal-types\"\nimport type {\n JsonRpcProvider,\n JsonRpcConnection,\n} from \"@polkadot-api/json-rpc-provider\"\nimport { getSubscriptionManager } from \"./subscription-manager\"\nimport { jsonRpcMsg } from \"./json-rpc-message\"\n\nexport type AsyncJsonRpcProvider = (\n onMessage: (message: string) => void,\n onHalt: () => void,\n) => JsonRpcConnection\n\nexport const getSyncProvider =\n (input: () => Promise<AsyncJsonRpcProvider>): JsonRpcProvider =>\n (onMessage) => {\n // if it's null it means that the consumer has called `disconnect`\n // of it's a Promise it means that it's being respolved, otherwise it's resolved\n let provider: JsonRpcConnection | Promise<JsonRpcConnection> | null\n\n let bufferedMessages: Array<string> = []\n const pendingResponses = new Set<RequestId>()\n const subscriptionManager = getSubscriptionManager(onMessage)\n\n const onMessageProxy = (message: string) => {\n let parsed: any\n try {\n parsed = JSON.parse(message)\n } catch (_) {\n console.error(`Unable to parse incoming message: ${message}`)\n return\n }\n\n if (parsed.id !== undefined) {\n pendingResponses.delete(parsed.id)\n subscriptionManager.onResponse(parsed)\n } else {\n subscriptionManager.onNotifiaction(parsed)\n }\n\n onMessage(message)\n }\n\n const send = (message: string) => {\n if (!provider) return\n\n const parsed = JSON.parse(message)\n subscriptionManager.onSent(parsed)\n if (parsed.id) pendingResponses.add(parsed.id)\n\n if (provider instanceof Promise) {\n bufferedMessages.push(message)\n } else provider.send(message)\n }\n\n const onHalt = (): Promise<JsonRpcConnection> => {\n bufferedMessages = []\n const pendingResponsesCopy = [...pendingResponses]\n pendingResponses.clear()\n\n // it means that the user has disconnected while the\n // provider promise was being rejected. Therefore, we must\n // throw to prevent the Promise from recovering.\n // The rejection will be handled from the teardown logic.\n if (!provider) throw null\n\n // It needs to restart before sending the errored\n // responses/notifications because the consumer may\n // react to those by sending new requests\n const result = start()\n\n subscriptionManager.onAbort()\n pendingResponsesCopy.forEach((id) => {\n onMessage(\n jsonRpcMsg({\n error: { code: -32603, message: \"Internal error\" },\n id,\n }),\n )\n })\n\n return result\n }\n\n const start = (): Promise<JsonRpcConnection> => {\n const onResolve = (getProvider: AsyncJsonRpcProvider) => {\n let alive = true\n const _onHalt = () => {\n if (alive) {\n alive = false\n onHalt()\n }\n }\n\n const _onMessageProxy = (msg: string) => {\n if (alive) onMessageProxy(msg)\n }\n\n const result = getProvider(_onMessageProxy, _onHalt)\n bufferedMessages.forEach((m) => {\n result.send(m)\n })\n bufferedMessages = []\n return (provider = result)\n }\n\n provider = input().then(onResolve, withMacroTask(onHalt))\n return provider\n }\n\n const disconnect = () => {\n if (!provider) return\n\n const finishIt = (input: JsonRpcConnection | null) => {\n subscriptionManager.onDisconnect()\n pendingResponses.clear()\n provider = null\n input?.disconnect()\n }\n\n if (provider instanceof Promise) {\n provider.then(finishIt, finishIt)\n provider = null\n } else finishIt(provider)\n }\n\n start()\n return {\n send,\n disconnect,\n }\n }\n\nconst withMacroTask =\n <Args extends Array<any>, T>(\n inputFn: (...args: Args) => Promise<T>,\n ): ((...args: Args) => Promise<T>) =>\n (...args) =>\n new Promise((res) => setTimeout(res, 0)).then(() => inputFn(...args))\n"],"names":["input"],"mappings":"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"}
1
+ {"version":3,"file":"get-sync-provider.mjs","sources":["../../src/get-sync-provider.ts"],"sourcesContent":["import type { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\nimport { getProxy } from \"./get-proxy\"\nimport { AsyncJsonRpcProvider } from \"./public-types\"\nimport { ConnectableJsonRpcConnection } from \"./internal-types\"\n\nexport const getSyncProvider =\n (input: () => Promise<AsyncJsonRpcProvider>): JsonRpcProvider =>\n (onMessage) => {\n let proxy: ConnectableJsonRpcConnection | null = getProxy(onMessage)\n\n const start = () => {\n input().then(\n (cb) => {\n if (!proxy) {\n try {\n cb(\n () => {},\n () => {},\n ).disconnect()\n } catch (_) {}\n } else\n proxy.connect((onMsg, onHalt) =>\n cb(onMsg, () => {\n onHalt()\n start()\n }),\n )\n },\n () => {\n proxy && setTimeout(start, 0)\n },\n )\n }\n\n start()\n return {\n send: (msg) => {\n proxy?.send(msg)\n },\n disconnect: () => {\n proxy?.disconnect()\n proxy = null\n },\n }\n }\n"],"names":[],"mappings":";;AAKO,MAAM,eACX,GAAA,CAAC,KACD,KAAA,CAAC,SAAc,KAAA;AACb,EAAI,IAAA,KAAA,GAA6C,SAAS,SAAS,CAAA,CAAA;AAEnE,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,KAAA,EAAQ,CAAA,IAAA;AAAA,MACN,CAAC,EAAO,KAAA;AACN,QAAA,IAAI,CAAC,KAAO,EAAA;AACV,UAAI,IAAA;AACF,YAAA,EAAA;AAAA,cACE,MAAM;AAAA,eAAC;AAAA,cACP,MAAM;AAAA,eAAC;AAAA,cACP,UAAW,EAAA,CAAA;AAAA,mBACN,CAAG,EAAA;AAAA,WAAC;AAAA,SACf;AACE,UAAM,KAAA,CAAA,OAAA;AAAA,YAAQ,CAAC,KAAA,EAAO,MACpB,KAAA,EAAA,CAAG,OAAO,MAAM;AACd,cAAO,MAAA,EAAA,CAAA;AACP,cAAM,KAAA,EAAA,CAAA;AAAA,aACP,CAAA;AAAA,WACH,CAAA;AAAA,OACJ;AAAA,MACA,MAAM;AACJ,QAAS,KAAA,IAAA,UAAA,CAAW,OAAO,CAAC,CAAA,CAAA;AAAA,OAC9B;AAAA,KACF,CAAA;AAAA,GACF,CAAA;AAEA,EAAM,KAAA,EAAA,CAAA;AACN,EAAO,OAAA;AAAA,IACL,IAAA,EAAM,CAAC,GAAQ,KAAA;AACb,MAAA,KAAA,EAAO,KAAK,GAAG,CAAA,CAAA;AAAA,KACjB;AAAA,IACA,YAAY,MAAM;AAChB,MAAA,KAAA,EAAO,UAAW,EAAA,CAAA;AAClB,MAAQ,KAAA,GAAA,IAAA,CAAA;AAAA,KACV;AAAA,GACF,CAAA;AACF;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { JsonRpcConnection, JsonRpcProvider } from '@polkadot-api/json-rpc-provider';
2
2
 
3
3
  type AsyncJsonRpcProvider = (onMessage: (message: string) => void, onHalt: () => void) => JsonRpcConnection;
4
+
4
5
  declare const getSyncProvider: (input: () => Promise<AsyncJsonRpcProvider>) => JsonRpcProvider;
5
6
 
6
7
  export { type AsyncJsonRpcProvider, getSyncProvider };
package/dist/index.js CHANGED
@@ -1,199 +1,146 @@
1
1
  'use strict';
2
2
 
3
- var MessageType = /* @__PURE__ */ ((MessageType2) => {
4
- MessageType2[MessageType2["subscribe"] = 0] = "subscribe";
5
- MessageType2[MessageType2["unsubscribe"] = 1] = "unsubscribe";
6
- MessageType2[MessageType2["end"] = 2] = "end";
7
- return MessageType2;
8
- })(MessageType || {});
9
-
10
3
  const jsonRpcMsg = (msg) => JSON.stringify({
11
4
  jsonrpc: "2.0",
12
5
  ...msg
13
6
  });
14
7
 
15
- const [START_METHODS, STOP_METHODS, NOTIFICATION_METHODS] = [
16
- "follow",
17
- "unfollow",
18
- "followEvent"
19
- ].map(
20
- (name) => new Set(
21
- ["v1", "unstable"].map((version) => `chainHead_${version}_${name}`)
22
- )
8
+ const unfollowMethods = new Set(
9
+ ["v1", "unstable"].map((x) => `chainHead_${x}_unfollow`)
23
10
  );
24
- const STOP_EVENT = "stop";
25
- const chainHeadFollow = (onMessage) => {
26
- let notificationMethod = "";
27
- return {
28
- onSent(parsed) {
29
- if (START_METHODS.has(parsed.method)) {
30
- notificationMethod = parsed.method + "Event";
31
- return {
32
- type: MessageType.subscribe,
33
- id: parsed.id,
34
- onRes: (innerParsed) => innerParsed.id === parsed.id ? { id: innerParsed.result } : null
35
- };
36
- }
37
- if (STOP_METHODS.has(parsed.method))
38
- return {
39
- type: MessageType.unsubscribe,
40
- id: Object.values(parsed.params)[0]
41
- };
42
- return null;
43
- },
44
- onNotification(parsed) {
45
- return NOTIFICATION_METHODS.has(parsed.method) && parsed.params.result.event === STOP_EVENT ? {
46
- type: MessageType.end,
47
- id: parsed.params.subscription
48
- } : null;
49
- },
50
- onAbort: (id) => {
51
- onMessage(
52
- jsonRpcMsg({
53
- method: notificationMethod,
54
- params: {
55
- subscription: id,
56
- result: {
57
- event: STOP_EVENT,
58
- eventType: "internal"
59
- }
60
- }
61
- })
62
- );
63
- }
11
+ const getProxy = (toConsumer) => {
12
+ let state = {
13
+ type: 1 /* Connecting */,
14
+ pending: []
64
15
  };
65
- };
66
-
67
- const addSubscription = ({
68
- onSent,
69
- onNotification,
70
- onAbort
71
- }) => {
72
- const preActive = /* @__PURE__ */ new Map();
73
- const active = /* @__PURE__ */ new Set();
74
- const onDisconnect = () => {
75
- preActive.clear();
76
- active.clear();
77
- };
78
- return {
79
- onSent(parsed) {
80
- const result = onSent(parsed);
81
- if (result) {
82
- if (result.type === MessageType.subscribe)
83
- preActive.set(result.id, result.onRes);
84
- else active.delete(result.id);
85
- }
86
- },
87
- onResponse(parsed) {
88
- const match = preActive.get(parsed.id)?.(parsed);
89
- if (match) {
90
- preActive.delete(parsed.id);
91
- active.add(match.id);
16
+ const onMsgFromProvider = (msg) => {
17
+ if (state.type === 0 /* Connected */) {
18
+ const parsed = JSON.parse(msg);
19
+ if ("id" in parsed) {
20
+ if (state.onGoingRequests.get(parsed.id)?.type === 0 /* ChainHeadFollow */)
21
+ state.activeChainHeads.add(parsed.result);
22
+ state.onGoingRequests.delete(parsed.id);
23
+ } else {
24
+ const { subscription, result } = parsed.params;
25
+ if (result?.event === "stop")
26
+ state.activeChainHeads.delete(subscription);
92
27
  }
93
- },
94
- onNotifiaction(parsed) {
95
- const result = onNotification(parsed);
96
- if (result) active.delete(result.id);
97
- },
98
- onDisconnect,
99
- onAbort() {
100
- const activeCopy = [...active];
101
- onDisconnect();
102
- activeCopy.forEach(onAbort);
103
28
  }
29
+ if (state.type !== 2 /* Done */) toConsumer(msg);
104
30
  };
105
- };
106
- const getSubscriptionManager = (onMessage) => addSubscription(chainHeadFollow(onMessage));
107
-
108
- const getSyncProvider = (input) => (onMessage) => {
109
- let provider;
110
- let bufferedMessages = [];
111
- const pendingResponses = /* @__PURE__ */ new Set();
112
- const subscriptionManager = getSubscriptionManager(onMessage);
113
- const onMessageProxy = (message) => {
114
- let parsed;
115
- try {
116
- parsed = JSON.parse(message);
117
- } catch (_) {
118
- console.error(`Unable to parse incoming message: ${message}`);
31
+ const send = (msg) => {
32
+ if (state.type === 2 /* Done */) return;
33
+ if (state.type === 1 /* Connecting */) {
34
+ state.pending.push(msg);
119
35
  return;
120
36
  }
121
- if (parsed.id !== void 0) {
122
- pendingResponses.delete(parsed.id);
123
- subscriptionManager.onResponse(parsed);
124
- } else {
125
- subscriptionManager.onNotifiaction(parsed);
37
+ const parsed = JSON.parse(msg);
38
+ if (unfollowMethods.has(parsed.method))
39
+ state.activeChainHeads.delete(parsed.params[0]);
40
+ if ("id" in parsed) {
41
+ const { method, id } = parsed;
42
+ const ongoingMsg = method.startsWith("chainHead") ? method.endsWith("follow") ? {
43
+ type: 0 /* ChainHeadFollow */,
44
+ msg
45
+ } : { type: 1 /* ChainHeadOperation */, id } : { type: 2 /* Other */, msg };
46
+ state.onGoingRequests.set(id, ongoingMsg);
126
47
  }
127
- onMessage(message);
128
- };
129
- const send = (message) => {
130
- if (!provider) return;
131
- const parsed = JSON.parse(message);
132
- subscriptionManager.onSent(parsed);
133
- if (parsed.id) pendingResponses.add(parsed.id);
134
- if (provider instanceof Promise) {
135
- bufferedMessages.push(message);
136
- } else provider.send(message);
137
- };
138
- const onHalt = () => {
139
- bufferedMessages = [];
140
- const pendingResponsesCopy = [...pendingResponses];
141
- pendingResponses.clear();
142
- if (!provider) throw null;
143
- const result = start();
144
- subscriptionManager.onAbort();
145
- pendingResponsesCopy.forEach((id) => {
146
- onMessage(
147
- jsonRpcMsg({
148
- error: { code: -32603, message: "Internal error" },
149
- id
150
- })
151
- );
152
- });
153
- return result;
48
+ state.connection.send(msg);
154
49
  };
155
- const start = () => {
156
- const onResolve = (getProvider) => {
157
- let alive = true;
158
- const _onHalt = () => {
159
- if (alive) {
160
- alive = false;
161
- onHalt();
50
+ return {
51
+ send,
52
+ disconnect: () => {
53
+ if (state.type === 2 /* Done */) return;
54
+ if (state.type === 0 /* Connected */) state.connection.disconnect();
55
+ state = { type: 2 /* Done */ };
56
+ },
57
+ connect: (cb) => {
58
+ if (state.type !== 1 /* Connecting */) throw new Error("Nonesense");
59
+ const { pending } = state;
60
+ const onGoingRequests = /* @__PURE__ */ new Map();
61
+ const activeChainHeads = /* @__PURE__ */ new Set();
62
+ const onHalt = () => {
63
+ state = {
64
+ type: 1 /* Connecting */,
65
+ pending: []
66
+ };
67
+ activeChainHeads.forEach((subscription) => {
68
+ onMsgFromProvider(
69
+ jsonRpcMsg({
70
+ params: {
71
+ subscription,
72
+ result: {
73
+ event: "stop",
74
+ internal: true
75
+ }
76
+ }
77
+ })
78
+ );
79
+ });
80
+ activeChainHeads.clear();
81
+ for (const x of onGoingRequests.values()) {
82
+ if (x.type === 1 /* ChainHeadOperation */)
83
+ onMsgFromProvider(
84
+ jsonRpcMsg({
85
+ id: x.id,
86
+ error: { code: -32603, message: "Internal error" },
87
+ internal: true
88
+ })
89
+ );
90
+ else send(x.msg);
162
91
  }
92
+ onGoingRequests.clear();
163
93
  };
164
- const _onMessageProxy = (msg) => {
165
- if (alive) onMessageProxy(msg);
94
+ state = {
95
+ type: 0 /* Connected */,
96
+ connection: cb(onMsgFromProvider, onHalt),
97
+ onGoingRequests,
98
+ activeChainHeads
166
99
  };
167
- const result = getProvider(_onMessageProxy, _onHalt);
168
- bufferedMessages.forEach((m) => {
169
- result.send(m);
170
- });
171
- bufferedMessages = [];
172
- return provider = result;
173
- };
174
- provider = input().then(onResolve, withMacroTask(onHalt));
175
- return provider;
100
+ pending.forEach(send);
101
+ }
176
102
  };
177
- const disconnect = () => {
178
- if (!provider) return;
179
- const finishIt = (input2) => {
180
- subscriptionManager.onDisconnect();
181
- pendingResponses.clear();
182
- provider = null;
183
- input2?.disconnect();
184
- };
185
- if (provider instanceof Promise) {
186
- provider.then(finishIt, finishIt);
187
- provider = null;
188
- } else finishIt(provider);
103
+ };
104
+
105
+ const getSyncProvider = (input) => (onMessage) => {
106
+ let proxy = getProxy(onMessage);
107
+ const start = () => {
108
+ input().then(
109
+ (cb) => {
110
+ if (!proxy) {
111
+ try {
112
+ cb(
113
+ () => {
114
+ },
115
+ () => {
116
+ }
117
+ ).disconnect();
118
+ } catch (_) {
119
+ }
120
+ } else
121
+ proxy.connect(
122
+ (onMsg, onHalt) => cb(onMsg, () => {
123
+ onHalt();
124
+ start();
125
+ })
126
+ );
127
+ },
128
+ () => {
129
+ proxy && setTimeout(start, 0);
130
+ }
131
+ );
189
132
  };
190
133
  start();
191
134
  return {
192
- send,
193
- disconnect
135
+ send: (msg) => {
136
+ proxy?.send(msg);
137
+ },
138
+ disconnect: () => {
139
+ proxy?.disconnect();
140
+ proxy = null;
141
+ }
194
142
  };
195
143
  };
196
- const withMacroTask = (inputFn) => (...args) => new Promise((res) => setTimeout(res, 0)).then(() => inputFn(...args));
197
144
 
198
145
  exports.getSyncProvider = getSyncProvider;
199
146
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/internal-types.ts","../src/json-rpc-message.ts","../src/subscription-manager/chainHeadFollow.ts","../src/subscription-manager/subscription-manager.ts","../src/get-sync-provider.ts"],"sourcesContent":["export type RequestId = string | number | null\nexport type SubscriptionId = string | number\nexport type JsonMessage = {\n jsonrpc: \"2.0\"\n method: string\n params: {}\n}\n\nexport const enum MessageType {\n subscribe,\n unsubscribe,\n end,\n}\n\nexport interface SubscriptionLogic {\n onSent: (parsed: any) =>\n | {\n type: MessageType.subscribe\n id: RequestId\n onRes: (parsed: any) => { id: SubscriptionId } | null\n }\n | { type: MessageType.unsubscribe; id: SubscriptionId }\n | null\n onNotification: (\n parsed: any,\n ) => { type: MessageType.end; id: SubscriptionId } | null\n onAbort: (id: SubscriptionId) => void\n}\n","export const jsonRpcMsg = <T extends {}>(msg: T) =>\n JSON.stringify({\n jsonrpc: \"2.0\",\n ...msg,\n })\n","import {\n MessageType,\n SubscriptionId,\n SubscriptionLogic,\n} from \"@/internal-types\"\nimport { jsonRpcMsg } from \"@/json-rpc-message\"\n\nconst [START_METHODS, STOP_METHODS, NOTIFICATION_METHODS] = [\n \"follow\",\n \"unfollow\",\n \"followEvent\",\n].map(\n (name) =>\n new Set(\n [\"v1\", \"unstable\"].map((version) => `chainHead_${version}_${name}`),\n ),\n)\nconst STOP_EVENT = \"stop\"\n\nexport const chainHeadFollow = (\n onMessage: (msg: string) => void,\n): SubscriptionLogic => {\n let notificationMethod = \"\"\n return {\n onSent(parsed) {\n if (START_METHODS.has(parsed.method)) {\n notificationMethod = parsed.method + \"Event\"\n return {\n type: MessageType.subscribe,\n id: parsed.id,\n onRes: (innerParsed) =>\n innerParsed.id === parsed.id ? { id: innerParsed.result } : null,\n }\n }\n\n if (STOP_METHODS.has(parsed.method))\n return {\n type: MessageType.unsubscribe,\n id: Object.values(parsed.params)[0] as string,\n }\n\n return null\n },\n onNotification(parsed) {\n return NOTIFICATION_METHODS.has(parsed.method) &&\n parsed.params.result.event === STOP_EVENT\n ? {\n type: MessageType.end,\n id: parsed.params.subscription as SubscriptionId,\n }\n : null\n },\n onAbort: (id) => {\n onMessage(\n jsonRpcMsg({\n method: notificationMethod,\n params: {\n subscription: id,\n result: {\n event: STOP_EVENT,\n eventType: \"internal\",\n },\n },\n }),\n )\n },\n }\n}\n","import {\n MessageType,\n type RequestId,\n type SubscriptionId,\n type SubscriptionLogic,\n} from \"../internal-types\"\nimport { chainHeadFollow } from \"./chainHeadFollow\"\n\nexport const addSubscription = ({\n onSent,\n onNotification,\n onAbort,\n}: SubscriptionLogic) => {\n const preActive = new Map<\n RequestId,\n (parsed: any) => { id: SubscriptionId } | null\n >()\n const active = new Set<SubscriptionId>()\n\n const onDisconnect = () => {\n preActive.clear()\n active.clear()\n }\n\n return {\n onSent(parsed: any) {\n const result = onSent(parsed)\n if (result) {\n if (result.type === MessageType.subscribe)\n preActive.set(result.id, result.onRes)\n else active.delete(result.id)\n }\n },\n onResponse(parsed: any) {\n const match = preActive.get(parsed.id)?.(parsed)\n if (match) {\n preActive.delete(parsed.id)\n active.add(match.id)\n }\n },\n onNotifiaction(parsed: any) {\n const result = onNotification(parsed)\n if (result) active.delete(result.id)\n },\n onDisconnect,\n onAbort() {\n const activeCopy = [...active]\n onDisconnect()\n activeCopy.forEach(onAbort)\n },\n }\n}\n\nexport const getSubscriptionManager = (onMessage: (msg: string) => void) =>\n addSubscription(chainHeadFollow(onMessage))\n","import type { RequestId } from \"./internal-types\"\nimport type {\n JsonRpcProvider,\n JsonRpcConnection,\n} from \"@polkadot-api/json-rpc-provider\"\nimport { getSubscriptionManager } from \"./subscription-manager\"\nimport { jsonRpcMsg } from \"./json-rpc-message\"\n\nexport type AsyncJsonRpcProvider = (\n onMessage: (message: string) => void,\n onHalt: () => void,\n) => JsonRpcConnection\n\nexport const getSyncProvider =\n (input: () => Promise<AsyncJsonRpcProvider>): JsonRpcProvider =>\n (onMessage) => {\n // if it's null it means that the consumer has called `disconnect`\n // of it's a Promise it means that it's being respolved, otherwise it's resolved\n let provider: JsonRpcConnection | Promise<JsonRpcConnection> | null\n\n let bufferedMessages: Array<string> = []\n const pendingResponses = new Set<RequestId>()\n const subscriptionManager = getSubscriptionManager(onMessage)\n\n const onMessageProxy = (message: string) => {\n let parsed: any\n try {\n parsed = JSON.parse(message)\n } catch (_) {\n console.error(`Unable to parse incoming message: ${message}`)\n return\n }\n\n if (parsed.id !== undefined) {\n pendingResponses.delete(parsed.id)\n subscriptionManager.onResponse(parsed)\n } else {\n subscriptionManager.onNotifiaction(parsed)\n }\n\n onMessage(message)\n }\n\n const send = (message: string) => {\n if (!provider) return\n\n const parsed = JSON.parse(message)\n subscriptionManager.onSent(parsed)\n if (parsed.id) pendingResponses.add(parsed.id)\n\n if (provider instanceof Promise) {\n bufferedMessages.push(message)\n } else provider.send(message)\n }\n\n const onHalt = (): Promise<JsonRpcConnection> => {\n bufferedMessages = []\n const pendingResponsesCopy = [...pendingResponses]\n pendingResponses.clear()\n\n // it means that the user has disconnected while the\n // provider promise was being rejected. Therefore, we must\n // throw to prevent the Promise from recovering.\n // The rejection will be handled from the teardown logic.\n if (!provider) throw null\n\n // It needs to restart before sending the errored\n // responses/notifications because the consumer may\n // react to those by sending new requests\n const result = start()\n\n subscriptionManager.onAbort()\n pendingResponsesCopy.forEach((id) => {\n onMessage(\n jsonRpcMsg({\n error: { code: -32603, message: \"Internal error\" },\n id,\n }),\n )\n })\n\n return result\n }\n\n const start = (): Promise<JsonRpcConnection> => {\n const onResolve = (getProvider: AsyncJsonRpcProvider) => {\n let alive = true\n const _onHalt = () => {\n if (alive) {\n alive = false\n onHalt()\n }\n }\n\n const _onMessageProxy = (msg: string) => {\n if (alive) onMessageProxy(msg)\n }\n\n const result = getProvider(_onMessageProxy, _onHalt)\n bufferedMessages.forEach((m) => {\n result.send(m)\n })\n bufferedMessages = []\n return (provider = result)\n }\n\n provider = input().then(onResolve, withMacroTask(onHalt))\n return provider\n }\n\n const disconnect = () => {\n if (!provider) return\n\n const finishIt = (input: JsonRpcConnection | null) => {\n subscriptionManager.onDisconnect()\n pendingResponses.clear()\n provider = null\n input?.disconnect()\n }\n\n if (provider instanceof Promise) {\n provider.then(finishIt, finishIt)\n provider = null\n } else finishIt(provider)\n }\n\n start()\n return {\n send,\n disconnect,\n }\n }\n\nconst withMacroTask =\n <Args extends Array<any>, T>(\n inputFn: (...args: Args) => Promise<T>,\n ): ((...args: Args) => Promise<T>) =>\n (...args) =>\n new Promise((res) => setTimeout(res, 0)).then(() => inputFn(...args))\n"],"names":["MessageType","input"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/json-rpc-message.ts","../src/get-proxy.ts","../src/get-sync-provider.ts"],"sourcesContent":["export const jsonRpcMsg = <T extends {}>(msg: T) =>\n JSON.stringify({\n jsonrpc: \"2.0\",\n ...msg,\n })\n","import { JsonRpcConnection } from \"@polkadot-api/json-rpc-provider\"\nimport { ReconnectableJsonRpcConnection } from \"./internal-types\"\nimport { jsonRpcMsg } from \"./json-rpc-message\"\n\nconst enum State {\n Connected,\n Connecting,\n Done,\n}\n\nconst enum OngoingMsgType {\n ChainHeadFollow,\n ChainHeadOperation,\n Other,\n}\ntype OngoingMsg =\n | {\n type: OngoingMsgType.ChainHeadFollow\n msg: string\n }\n | { type: OngoingMsgType.ChainHeadOperation; id: string }\n | { type: OngoingMsgType.Other; msg: string }\n\nconst unfollowMethods = new Set(\n [\"v1\", \"unstable\"].map((x) => `chainHead_${x}_unfollow`),\n)\n\nexport const getProxy: ReconnectableJsonRpcConnection = (\n toConsumer: (msg: string) => void,\n) => {\n let state:\n | {\n type: State.Connected\n connection: JsonRpcConnection\n onGoingRequests: Map<string, OngoingMsg>\n activeChainHeads: Set<string>\n }\n | { type: State.Connecting; pending: Array<string> }\n | { type: State.Done } = {\n type: State.Connecting,\n pending: [],\n }\n\n const onMsgFromProvider = (msg: string) => {\n if (state.type === State.Connected) {\n const parsed = JSON.parse(msg)\n if (\"id\" in parsed) {\n if (\n state.onGoingRequests.get(parsed.id)?.type ===\n OngoingMsgType.ChainHeadFollow\n )\n state.activeChainHeads.add(parsed.result)\n state.onGoingRequests.delete(parsed.id)\n } else {\n const { subscription, result } = parsed.params\n if (result?.event === \"stop\")\n state.activeChainHeads.delete(subscription)\n }\n }\n // If the state is \"Connecting\", then these are messages\n // sent from the `onHalt` function. So, we mus realy them\n if (state.type !== State.Done) toConsumer(msg)\n }\n\n const send = (msg: string) => {\n if (state.type === State.Done) return\n if (state.type === State.Connecting) {\n state.pending.push(msg)\n return\n }\n const parsed = JSON.parse(msg)\n if (unfollowMethods.has(parsed.method))\n state.activeChainHeads.delete(parsed.params[0])\n\n if (\"id\" in parsed) {\n const { method, id } = parsed as { method: string; id: string }\n const ongoingMsg: OngoingMsg = method.startsWith(\"chainHead\")\n ? method.endsWith(\"follow\")\n ? {\n type: OngoingMsgType.ChainHeadFollow,\n msg,\n }\n : { type: OngoingMsgType.ChainHeadOperation, id }\n : { type: OngoingMsgType.Other, msg }\n state.onGoingRequests.set(id, ongoingMsg)\n }\n\n state.connection.send(msg)\n }\n\n return {\n send,\n disconnect: () => {\n if (state.type === State.Done) return\n if (state.type === State.Connected) state.connection.disconnect()\n state = { type: State.Done }\n },\n connect: (cb) => {\n if (state.type !== State.Connecting) throw new Error(\"Nonesense\")\n\n const { pending } = state\n const onGoingRequests = new Map<string, OngoingMsg>()\n const activeChainHeads = new Set<string>()\n const onHalt = () => {\n state = {\n type: State.Connecting,\n pending: [],\n }\n activeChainHeads.forEach((subscription) => {\n // We don't send the messages directy to the consumer\n // b/c they could have disconnected after receiving one\n // of these messages. The `onMsgFromProvider` fn handles that\n onMsgFromProvider(\n jsonRpcMsg({\n params: {\n subscription,\n result: {\n event: \"stop\",\n internal: true,\n },\n },\n }),\n )\n })\n activeChainHeads.clear()\n for (const x of onGoingRequests.values()) {\n if (x.type === OngoingMsgType.ChainHeadOperation)\n onMsgFromProvider(\n jsonRpcMsg({\n id: x.id,\n error: { code: -32603, message: \"Internal error\" },\n internal: true,\n }),\n )\n else send(x.msg)\n }\n onGoingRequests.clear()\n }\n state = {\n type: State.Connected,\n connection: cb(onMsgFromProvider, onHalt),\n onGoingRequests,\n activeChainHeads,\n }\n pending.forEach(send)\n },\n }\n}\n","import type { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\nimport { getProxy } from \"./get-proxy\"\nimport { AsyncJsonRpcProvider } from \"./public-types\"\nimport { ConnectableJsonRpcConnection } from \"./internal-types\"\n\nexport const getSyncProvider =\n (input: () => Promise<AsyncJsonRpcProvider>): JsonRpcProvider =>\n (onMessage) => {\n let proxy: ConnectableJsonRpcConnection | null = getProxy(onMessage)\n\n const start = () => {\n input().then(\n (cb) => {\n if (!proxy) {\n try {\n cb(\n () => {},\n () => {},\n ).disconnect()\n } catch (_) {}\n } else\n proxy.connect((onMsg, onHalt) =>\n cb(onMsg, () => {\n onHalt()\n start()\n }),\n )\n },\n () => {\n proxy && setTimeout(start, 0)\n },\n )\n }\n\n start()\n return {\n send: (msg) => {\n proxy?.send(msg)\n },\n disconnect: () => {\n proxy?.disconnect()\n proxy = null\n },\n }\n }\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polkadot-api/json-rpc-provider-proxy",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "author": "Josep M Sobrepere (https://github.com/josepot)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,7 +35,7 @@
35
35
  "dist"
36
36
  ],
37
37
  "devDependencies": {
38
- "@polkadot-api/json-rpc-provider": "0.0.3"
38
+ "@polkadot-api/json-rpc-provider": "0.0.4"
39
39
  },
40
40
  "scripts": {
41
41
  "build-core": "tsc --noEmit && rollup -c ../../../rollup.config.js",
@@ -1,9 +0,0 @@
1
- var MessageType = /* @__PURE__ */ ((MessageType2) => {
2
- MessageType2[MessageType2["subscribe"] = 0] = "subscribe";
3
- MessageType2[MessageType2["unsubscribe"] = 1] = "unsubscribe";
4
- MessageType2[MessageType2["end"] = 2] = "end";
5
- return MessageType2;
6
- })(MessageType || {});
7
-
8
- export { MessageType };
9
- //# sourceMappingURL=internal-types.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"internal-types.mjs","sources":["../../src/internal-types.ts"],"sourcesContent":["export type RequestId = string | number | null\nexport type SubscriptionId = string | number\nexport type JsonMessage = {\n jsonrpc: \"2.0\"\n method: string\n params: {}\n}\n\nexport const enum MessageType {\n subscribe,\n unsubscribe,\n end,\n}\n\nexport interface SubscriptionLogic {\n onSent: (parsed: any) =>\n | {\n type: MessageType.subscribe\n id: RequestId\n onRes: (parsed: any) => { id: SubscriptionId } | null\n }\n | { type: MessageType.unsubscribe; id: SubscriptionId }\n | null\n onNotification: (\n parsed: any,\n ) => { type: MessageType.end; id: SubscriptionId } | null\n onAbort: (id: SubscriptionId) => void\n}\n"],"names":["MessageType"],"mappings":"AAQkB,IAAA,WAAA,qBAAAA,YAAX,KAAA;AACL,EAAAA,YAAA,CAAA,YAAA,CAAA,WAAA,CAAA,GAAA,CAAA,CAAA,GAAA,WAAA,CAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,aAAA,CAAA,GAAA,CAAA,CAAA,GAAA,aAAA,CAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,KAAA,CAAA,GAAA,CAAA,CAAA,GAAA,KAAA,CAAA;AAHgB,EAAAA,OAAAA,YAAAA,CAAAA;AAAA,CAAA,EAAA,WAAA,IAAA,EAAA;;;;"}
@@ -1,57 +0,0 @@
1
- import { MessageType } from '../internal-types.mjs';
2
- import { jsonRpcMsg } from '../json-rpc-message.mjs';
3
-
4
- const [START_METHODS, STOP_METHODS, NOTIFICATION_METHODS] = [
5
- "follow",
6
- "unfollow",
7
- "followEvent"
8
- ].map(
9
- (name) => new Set(
10
- ["v1", "unstable"].map((version) => `chainHead_${version}_${name}`)
11
- )
12
- );
13
- const STOP_EVENT = "stop";
14
- const chainHeadFollow = (onMessage) => {
15
- let notificationMethod = "";
16
- return {
17
- onSent(parsed) {
18
- if (START_METHODS.has(parsed.method)) {
19
- notificationMethod = parsed.method + "Event";
20
- return {
21
- type: MessageType.subscribe,
22
- id: parsed.id,
23
- onRes: (innerParsed) => innerParsed.id === parsed.id ? { id: innerParsed.result } : null
24
- };
25
- }
26
- if (STOP_METHODS.has(parsed.method))
27
- return {
28
- type: MessageType.unsubscribe,
29
- id: Object.values(parsed.params)[0]
30
- };
31
- return null;
32
- },
33
- onNotification(parsed) {
34
- return NOTIFICATION_METHODS.has(parsed.method) && parsed.params.result.event === STOP_EVENT ? {
35
- type: MessageType.end,
36
- id: parsed.params.subscription
37
- } : null;
38
- },
39
- onAbort: (id) => {
40
- onMessage(
41
- jsonRpcMsg({
42
- method: notificationMethod,
43
- params: {
44
- subscription: id,
45
- result: {
46
- event: STOP_EVENT,
47
- eventType: "internal"
48
- }
49
- }
50
- })
51
- );
52
- }
53
- };
54
- };
55
-
56
- export { chainHeadFollow };
57
- //# sourceMappingURL=chainHeadFollow.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chainHeadFollow.mjs","sources":["../../../src/subscription-manager/chainHeadFollow.ts"],"sourcesContent":["import {\n MessageType,\n SubscriptionId,\n SubscriptionLogic,\n} from \"@/internal-types\"\nimport { jsonRpcMsg } from \"@/json-rpc-message\"\n\nconst [START_METHODS, STOP_METHODS, NOTIFICATION_METHODS] = [\n \"follow\",\n \"unfollow\",\n \"followEvent\",\n].map(\n (name) =>\n new Set(\n [\"v1\", \"unstable\"].map((version) => `chainHead_${version}_${name}`),\n ),\n)\nconst STOP_EVENT = \"stop\"\n\nexport const chainHeadFollow = (\n onMessage: (msg: string) => void,\n): SubscriptionLogic => {\n let notificationMethod = \"\"\n return {\n onSent(parsed) {\n if (START_METHODS.has(parsed.method)) {\n notificationMethod = parsed.method + \"Event\"\n return {\n type: MessageType.subscribe,\n id: parsed.id,\n onRes: (innerParsed) =>\n innerParsed.id === parsed.id ? { id: innerParsed.result } : null,\n }\n }\n\n if (STOP_METHODS.has(parsed.method))\n return {\n type: MessageType.unsubscribe,\n id: Object.values(parsed.params)[0] as string,\n }\n\n return null\n },\n onNotification(parsed) {\n return NOTIFICATION_METHODS.has(parsed.method) &&\n parsed.params.result.event === STOP_EVENT\n ? {\n type: MessageType.end,\n id: parsed.params.subscription as SubscriptionId,\n }\n : null\n },\n onAbort: (id) => {\n onMessage(\n jsonRpcMsg({\n method: notificationMethod,\n params: {\n subscription: id,\n result: {\n event: STOP_EVENT,\n eventType: \"internal\",\n },\n },\n }),\n )\n },\n }\n}\n"],"names":[],"mappings":";;;AAOA,MAAM,CAAC,aAAA,EAAe,YAAc,EAAA,oBAAoB,CAAI,GAAA;AAAA,EAC1D,QAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AACF,CAAE,CAAA,GAAA;AAAA,EACA,CAAC,SACC,IAAI,GAAA;AAAA,IACF,CAAC,IAAM,EAAA,UAAU,CAAE,CAAA,GAAA,CAAI,CAAC,OAAA,KAAY,CAAa,UAAA,EAAA,OAAO,CAAI,CAAA,EAAA,IAAI,CAAE,CAAA,CAAA;AAAA,GACpE;AACJ,CAAA,CAAA;AACA,MAAM,UAAa,GAAA,MAAA,CAAA;AAEN,MAAA,eAAA,GAAkB,CAC7B,SACsB,KAAA;AACtB,EAAA,IAAI,kBAAqB,GAAA,EAAA,CAAA;AACzB,EAAO,OAAA;AAAA,IACL,OAAO,MAAQ,EAAA;AACb,MAAA,IAAI,aAAc,CAAA,GAAA,CAAI,MAAO,CAAA,MAAM,CAAG,EAAA;AACpC,QAAA,kBAAA,GAAqB,OAAO,MAAS,GAAA,OAAA,CAAA;AACrC,QAAO,OAAA;AAAA,UACL,MAAM,WAAY,CAAA,SAAA;AAAA,UAClB,IAAI,MAAO,CAAA,EAAA;AAAA,UACX,KAAA,EAAO,CAAC,WAAA,KACN,WAAY,CAAA,EAAA,KAAO,MAAO,CAAA,EAAA,GAAK,EAAE,EAAA,EAAI,WAAY,CAAA,MAAA,EAAW,GAAA,IAAA;AAAA,SAChE,CAAA;AAAA,OACF;AAEA,MAAI,IAAA,YAAA,CAAa,GAAI,CAAA,MAAA,CAAO,MAAM,CAAA;AAChC,QAAO,OAAA;AAAA,UACL,MAAM,WAAY,CAAA,WAAA;AAAA,UAClB,IAAI,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,MAAM,EAAE,CAAC,CAAA;AAAA,SACpC,CAAA;AAEF,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAAA,IACA,eAAe,MAAQ,EAAA;AACrB,MAAO,OAAA,oBAAA,CAAqB,IAAI,MAAO,CAAA,MAAM,KAC3C,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,KAAA,KAAU,UAC7B,GAAA;AAAA,QACE,MAAM,WAAY,CAAA,GAAA;AAAA,QAClB,EAAA,EAAI,OAAO,MAAO,CAAA,YAAA;AAAA,OAEpB,GAAA,IAAA,CAAA;AAAA,KACN;AAAA,IACA,OAAA,EAAS,CAAC,EAAO,KAAA;AACf,MAAA,SAAA;AAAA,QACE,UAAW,CAAA;AAAA,UACT,MAAQ,EAAA,kBAAA;AAAA,UACR,MAAQ,EAAA;AAAA,YACN,YAAc,EAAA,EAAA;AAAA,YACd,MAAQ,EAAA;AAAA,cACN,KAAO,EAAA,UAAA;AAAA,cACP,SAAW,EAAA,UAAA;AAAA,aACb;AAAA,WACF;AAAA,SACD,CAAA;AAAA,OACH,CAAA;AAAA,KACF;AAAA,GACF,CAAA;AACF;;;;"}
@@ -1,46 +0,0 @@
1
- import { MessageType } from '../internal-types.mjs';
2
- import { chainHeadFollow } from './chainHeadFollow.mjs';
3
-
4
- const addSubscription = ({
5
- onSent,
6
- onNotification,
7
- onAbort
8
- }) => {
9
- const preActive = /* @__PURE__ */ new Map();
10
- const active = /* @__PURE__ */ new Set();
11
- const onDisconnect = () => {
12
- preActive.clear();
13
- active.clear();
14
- };
15
- return {
16
- onSent(parsed) {
17
- const result = onSent(parsed);
18
- if (result) {
19
- if (result.type === MessageType.subscribe)
20
- preActive.set(result.id, result.onRes);
21
- else active.delete(result.id);
22
- }
23
- },
24
- onResponse(parsed) {
25
- const match = preActive.get(parsed.id)?.(parsed);
26
- if (match) {
27
- preActive.delete(parsed.id);
28
- active.add(match.id);
29
- }
30
- },
31
- onNotifiaction(parsed) {
32
- const result = onNotification(parsed);
33
- if (result) active.delete(result.id);
34
- },
35
- onDisconnect,
36
- onAbort() {
37
- const activeCopy = [...active];
38
- onDisconnect();
39
- activeCopy.forEach(onAbort);
40
- }
41
- };
42
- };
43
- const getSubscriptionManager = (onMessage) => addSubscription(chainHeadFollow(onMessage));
44
-
45
- export { addSubscription, getSubscriptionManager };
46
- //# sourceMappingURL=subscription-manager.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subscription-manager.mjs","sources":["../../../src/subscription-manager/subscription-manager.ts"],"sourcesContent":["import {\n MessageType,\n type RequestId,\n type SubscriptionId,\n type SubscriptionLogic,\n} from \"../internal-types\"\nimport { chainHeadFollow } from \"./chainHeadFollow\"\n\nexport const addSubscription = ({\n onSent,\n onNotification,\n onAbort,\n}: SubscriptionLogic) => {\n const preActive = new Map<\n RequestId,\n (parsed: any) => { id: SubscriptionId } | null\n >()\n const active = new Set<SubscriptionId>()\n\n const onDisconnect = () => {\n preActive.clear()\n active.clear()\n }\n\n return {\n onSent(parsed: any) {\n const result = onSent(parsed)\n if (result) {\n if (result.type === MessageType.subscribe)\n preActive.set(result.id, result.onRes)\n else active.delete(result.id)\n }\n },\n onResponse(parsed: any) {\n const match = preActive.get(parsed.id)?.(parsed)\n if (match) {\n preActive.delete(parsed.id)\n active.add(match.id)\n }\n },\n onNotifiaction(parsed: any) {\n const result = onNotification(parsed)\n if (result) active.delete(result.id)\n },\n onDisconnect,\n onAbort() {\n const activeCopy = [...active]\n onDisconnect()\n activeCopy.forEach(onAbort)\n },\n }\n}\n\nexport const getSubscriptionManager = (onMessage: (msg: string) => void) =>\n addSubscription(chainHeadFollow(onMessage))\n"],"names":[],"mappings":";;;AAQO,MAAM,kBAAkB,CAAC;AAAA,EAC9B,MAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AACF,CAAyB,KAAA;AACvB,EAAM,MAAA,SAAA,uBAAgB,GAGpB,EAAA,CAAA;AACF,EAAM,MAAA,MAAA,uBAAa,GAAoB,EAAA,CAAA;AAEvC,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,SAAA,CAAU,KAAM,EAAA,CAAA;AAChB,IAAA,MAAA,CAAO,KAAM,EAAA,CAAA;AAAA,GACf,CAAA;AAEA,EAAO,OAAA;AAAA,IACL,OAAO,MAAa,EAAA;AAClB,MAAM,MAAA,MAAA,GAAS,OAAO,MAAM,CAAA,CAAA;AAC5B,MAAA,IAAI,MAAQ,EAAA;AACV,QAAI,IAAA,MAAA,CAAO,SAAS,WAAY,CAAA,SAAA;AAC9B,UAAA,SAAA,CAAU,GAAI,CAAA,MAAA,CAAO,EAAI,EAAA,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,aAClC,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAAA,OAC9B;AAAA,KACF;AAAA,IACA,WAAW,MAAa,EAAA;AACtB,MAAA,MAAM,QAAQ,SAAU,CAAA,GAAA,CAAI,MAAO,CAAA,EAAE,IAAI,MAAM,CAAA,CAAA;AAC/C,MAAA,IAAI,KAAO,EAAA;AACT,QAAU,SAAA,CAAA,MAAA,CAAO,OAAO,EAAE,CAAA,CAAA;AAC1B,QAAO,MAAA,CAAA,GAAA,CAAI,MAAM,EAAE,CAAA,CAAA;AAAA,OACrB;AAAA,KACF;AAAA,IACA,eAAe,MAAa,EAAA;AAC1B,MAAM,MAAA,MAAA,GAAS,eAAe,MAAM,CAAA,CAAA;AACpC,MAAA,IAAI,MAAQ,EAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAAA,KACrC;AAAA,IACA,YAAA;AAAA,IACA,OAAU,GAAA;AACR,MAAM,MAAA,UAAA,GAAa,CAAC,GAAG,MAAM,CAAA,CAAA;AAC7B,MAAa,YAAA,EAAA,CAAA;AACb,MAAA,UAAA,CAAW,QAAQ,OAAO,CAAA,CAAA;AAAA,KAC5B;AAAA,GACF,CAAA;AACF,EAAA;AAEO,MAAM,yBAAyB,CAAC,SAAA,KACrC,eAAgB,CAAA,eAAA,CAAgB,SAAS,CAAC;;;;"}