@devvit/realtime 0.11.18-next-2025-06-25-22-59-20-64e5118a3.0 → 0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0

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.
@@ -1,4 +1,4 @@
1
- import type { JSONValue } from '@devvit/shared-types/json.js';
1
+ import type { JSONValue } from '@devvit/shared';
2
2
  export declare class RealtimeClient {
3
3
  #private;
4
4
  constructor();
@@ -1 +1 @@
1
- {"version":3,"file":"RealtimeClient.d.ts","sourceRoot":"","sources":["../src/RealtimeClient.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,qBAAa,cAAc;;;IAOnB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAI3D;AAED,eAAO,MAAM,QAAQ,gBAAuB,CAAC"}
1
+ {"version":3,"file":"RealtimeClient.d.ts","sourceRoot":"","sources":["../src/RealtimeClient.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,qBAAa,cAAc;;;IAOnB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAI3D;AAED,eAAO,MAAM,QAAQ,gBAAuB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { connectRealtime } from './realtime.js';
2
+ //# sourceMappingURL=index-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-browser.d.ts","sourceRoot":"","sources":["../src/index-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1 @@
1
+ export { connectRealtime } from './realtime.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devvit/realtime",
3
- "version": "0.11.18-next-2025-06-25-22-59-20-64e5118a3.0",
3
+ "version": "0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0",
4
4
  "license": "BSD-3-Clause",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,22 +21,25 @@
21
21
  },
22
22
  "types": "./index.d.ts",
23
23
  "dependencies": {
24
- "@devvit/protos": "0.11.18-next-2025-06-25-22-59-20-64e5118a3.0",
25
- "@devvit/shared-types": "0.11.18-next-2025-06-25-22-59-20-64e5118a3.0"
24
+ "@devvit/protos": "0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0",
25
+ "@devvit/shared": "0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0"
26
26
  },
27
27
  "peerDependencies": {
28
+ "@devvit/client": "*",
28
29
  "@devvit/server": "*"
29
30
  },
30
31
  "devDependencies": {
31
- "@devvit/repo-tools": "0.11.18-next-2025-06-25-22-59-20-64e5118a3.0",
32
- "@devvit/server": "0.11.18-next-2025-06-25-22-59-20-64e5118a3.0",
33
- "@devvit/tsconfig": "0.11.18-next-2025-06-25-22-59-20-64e5118a3.0",
32
+ "@devvit/client": "0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0",
33
+ "@devvit/repo-tools": "0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0",
34
+ "@devvit/server": "0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0",
35
+ "@devvit/tsconfig": "0.11.18-next-2025-06-26-15-24-44-27ef5bd97.0",
34
36
  "eslint": "9.11.1",
35
- "typescript": "5.8.3"
37
+ "typescript": "5.8.3",
38
+ "vitest": "1.6.1"
36
39
  },
37
40
  "publishConfig": {
38
41
  "directory": "dist"
39
42
  },
40
43
  "source": "./src/index.ts",
41
- "gitHead": "3e476a3aada9d043a65593a9234d4b46a7da686a"
44
+ "gitHead": "41b71a78b0e3b443876a98578293ea445f7bda7e"
42
45
  }
package/realtime.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import type { JSONValue } from '@devvit/shared';
2
+ type ConnectRealtimeOptions = {
3
+ channel: string;
4
+ onConnect?: (channel: string) => void;
5
+ onDisconnect?: (channel: string) => void;
6
+ onMessage: (data: JSONValue) => void;
7
+ };
8
+ /**
9
+ * Connects to a realtime channel for receiving messages.
10
+ *
11
+ * @param opts - Connection options including channel name and callbacks
12
+ * @returns A Connection object with a disconnect method
13
+ */
14
+ export declare const connectRealtime: (opts: Readonly<ConnectRealtimeOptions>) => Promise<Connection>;
15
+ /**
16
+ * Clears all connections. Used for testing purposes.
17
+ * @internal
18
+ */
19
+ export declare const __clearConnections: () => void;
20
+ declare class Connection {
21
+ #private;
22
+ constructor(opts: Readonly<ConnectRealtimeOptions>);
23
+ /**
24
+ * Disconnects from the realtime channel.
25
+ *
26
+ * This works by sending a list of all channels we want to remain subscribed to,
27
+ * excluding the channel we want to disconnect from. The effect handler compares this
28
+ * new list with existing subscriptions and triggers disconnect for any channel
29
+ * that's no longer in the list.
30
+ */
31
+ disconnect(): Promise<void>;
32
+ onMessage: (ev: MessageEvent) => void;
33
+ }
34
+ export {};
35
+ //# sourceMappingURL=realtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,KAAK,sBAAsB,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC,CAAC;AAQF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,QAAQ,CAAC,sBAAsB,CAAC,KACrC,OAAO,CAAC,UAAU,CAepB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,IAErC,CAAC;AAEF,cAAM,UAAU;;gBAGF,IAAI,EAAE,QAAQ,CAAC,sBAAsB,CAAC;IAIlD;;;;;;;OAOG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC,SAAS,GAAI,IAAI,YAAY,KAAG,IAAI,CAgClC;CACH"}
package/realtime.js ADDED
@@ -0,0 +1,101 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _Connection_opts;
13
+ import { emitEffect } from '@devvit/client';
14
+ const connectionsByChannel = new Map();
15
+ /* TODO: Clean up this API. Now that realtime has been removed from the
16
+ * EFFECTS_WITH_RESPONSE list, we probably don't need to await emitEffect.
17
+ */
18
+ /**
19
+ * Connects to a realtime channel for receiving messages.
20
+ *
21
+ * @param opts - Connection options including channel name and callbacks
22
+ * @returns A Connection object with a disconnect method
23
+ */
24
+ export const connectRealtime = async (opts) => {
25
+ if (connectionsByChannel.has(opts.channel)) {
26
+ return connectionsByChannel.get(opts.channel);
27
+ }
28
+ const connection = new Connection(opts);
29
+ connectionsByChannel.set(opts.channel, connection);
30
+ addEventListener('message', connection.onMessage);
31
+ await emitEffect({
32
+ realtimeSubscriptions: { subscriptionIds: [...connectionsByChannel.keys()] },
33
+ type: 0,
34
+ });
35
+ return connection;
36
+ };
37
+ /**
38
+ * Clears all connections. Used for testing purposes.
39
+ * @internal
40
+ */
41
+ export const __clearConnections = () => {
42
+ connectionsByChannel.clear();
43
+ };
44
+ class Connection {
45
+ constructor(opts) {
46
+ _Connection_opts.set(this, void 0);
47
+ this.onMessage = (ev) => {
48
+ const { type, data } = ev.data;
49
+ if (type !== 'devvit-message') {
50
+ return;
51
+ }
52
+ if (!data.realtimeEvent) {
53
+ return;
54
+ }
55
+ const { status, event } = data.realtimeEvent;
56
+ if (!event?.channel.endsWith(__classPrivateFieldGet(this, _Connection_opts, "f").channel)) {
57
+ return;
58
+ }
59
+ // Normalize the channel name (remove namespacing)
60
+ event.channel = __classPrivateFieldGet(this, _Connection_opts, "f").channel;
61
+ if (status === 0) {
62
+ __classPrivateFieldGet(this, _Connection_opts, "f").onConnect?.(__classPrivateFieldGet(this, _Connection_opts, "f").channel);
63
+ }
64
+ else if (status === 1) {
65
+ __classPrivateFieldGet(this, _Connection_opts, "f").onDisconnect?.(__classPrivateFieldGet(this, _Connection_opts, "f").channel);
66
+ }
67
+ else if (event.data) {
68
+ __classPrivateFieldGet(this, _Connection_opts, "f").onMessage(event.data.msg);
69
+ }
70
+ else {
71
+ console.error('[realtime] Received event without data:', {
72
+ channel: __classPrivateFieldGet(this, _Connection_opts, "f").channel,
73
+ event,
74
+ });
75
+ }
76
+ };
77
+ __classPrivateFieldSet(this, _Connection_opts, opts, "f");
78
+ }
79
+ /**
80
+ * Disconnects from the realtime channel.
81
+ *
82
+ * This works by sending a list of all channels we want to remain subscribed to,
83
+ * excluding the channel we want to disconnect from. The effect handler compares this
84
+ * new list with existing subscriptions and triggers disconnect for any channel
85
+ * that's no longer in the list.
86
+ */
87
+ async disconnect() {
88
+ const connection = connectionsByChannel.get(__classPrivateFieldGet(this, _Connection_opts, "f").channel);
89
+ if (!connection) {
90
+ return;
91
+ }
92
+ // Get all current subscriptions except the one we're disconnecting
93
+ const remainingChannels = [...connectionsByChannel.keys()].filter((ch) => ch !== __classPrivateFieldGet(this, _Connection_opts, "f").channel);
94
+ await emitEffect({
95
+ realtimeSubscriptions: { subscriptionIds: remainingChannels },
96
+ type: 0,
97
+ });
98
+ connectionsByChannel.delete(__classPrivateFieldGet(this, _Connection_opts, "f").channel);
99
+ }
100
+ }
101
+ _Connection_opts = new WeakMap();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.test.d.ts","sourceRoot":"","sources":["../src/realtime.test.ts"],"names":[],"mappings":""}