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

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
+ onGoingRequests.values().forEach((x) => {
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 onGoingRequests.values().forEach((x) => {\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
- };
11
+ const getProxy = (toConsumer) => {
12
+ let state = {
13
+ type: 1 /* Connecting */,
14
+ pending: []
15
+ };
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);
36
27
  }
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
28
  }
29
+ if (state.type !== 2 /* Done */) toConsumer(msg);
64
30
  };
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();
31
+ const send = (msg) => {
32
+ if (state.type === 2 /* Done */) return;
33
+ if (state.type === 1 /* Connecting */) {
34
+ state.pending.push(msg);
35
+ return;
36
+ }
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);
47
+ }
48
+ state.connection.send(msg);
77
49
  };
78
50
  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);
92
- }
93
- },
94
- onNotifiaction(parsed) {
95
- const result = onNotification(parsed);
96
- if (result) active.delete(result.id);
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 */ };
97
56
  },
98
- onDisconnect,
99
- onAbort() {
100
- const activeCopy = [...active];
101
- onDisconnect();
102
- activeCopy.forEach(onAbort);
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
+ onGoingRequests.values().forEach((x) => {
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);
91
+ });
92
+ onGoingRequests.clear();
93
+ };
94
+ state = {
95
+ type: 0 /* Connected */,
96
+ connection: cb(onMsgFromProvider, onHalt),
97
+ onGoingRequests,
98
+ activeChainHeads
99
+ };
100
+ pending.forEach(send);
103
101
  }
104
102
  };
105
103
  };
106
- const getSubscriptionManager = (onMessage) => addSubscription(chainHeadFollow(onMessage));
107
104
 
108
105
  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}`);
119
- return;
120
- }
121
- if (parsed.id !== void 0) {
122
- pendingResponses.delete(parsed.id);
123
- subscriptionManager.onResponse(parsed);
124
- } else {
125
- subscriptionManager.onNotifiaction(parsed);
126
- }
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;
154
- };
106
+ let proxy = getProxy(onMessage);
155
107
  const start = () => {
156
- const onResolve = (getProvider) => {
157
- let alive = true;
158
- const _onHalt = () => {
159
- if (alive) {
160
- alive = false;
161
- onHalt();
162
- }
163
- };
164
- const _onMessageProxy = (msg) => {
165
- if (alive) onMessageProxy(msg);
166
- };
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;
176
- };
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);
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 onGoingRequests.values().forEach((x) => {\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.2",
4
4
  "author": "Josep M Sobrepere (https://github.com/josepot)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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;;;;"}