@devvit/public-api 0.10.23-next-2024-06-13-b4fe6dd97.0 → 0.10.23-next-2024-06-13-8c5a69306.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,7 +20,7 @@ export declare class RenderContext implements EffectEmitter {
20
20
  next: number;
21
21
  })[];
22
22
  _hooks: {
23
- [key: string]: Hook;
23
+ [hookID: string]: Hook;
24
24
  };
25
25
  _prevHookId: string;
26
26
  _effects: {
@@ -49,6 +49,9 @@ export declare class RenderContext implements EffectEmitter {
49
49
  constructor(request: UIRequest, meta: Metadata);
50
50
  /** The state delta new to this render. */
51
51
  get _changedState(): BlocksState;
52
+ get hooks(): {
53
+ readonly [hookID: string]: Hook;
54
+ };
52
55
  /** The complete render state. */
53
56
  get _state(): BlocksState;
54
57
  /** Replacing state resets the delta for the next render. */
@@ -58,6 +61,7 @@ export declare class RenderContext implements EffectEmitter {
58
61
  addUndeliveredEventHandler(id: string, handler: EventHandler): void;
59
62
  addGlobalUndeliveredEventHandler(id: string, handler: EventHandler): void;
60
63
  getHook(ref: HookRef): Hook;
64
+ /** Catches events with no active handler and routes to the corresponding hook to detach/unsubscribe/etc **/
61
65
  static addGlobalUndeliveredEventHandler(id: string, handler: EventHandler): void;
62
66
  handleUndeliveredEvent(ev: UIEvent): Promise<Effect[] | void>;
63
67
  emitEffect(dedupeKey: string, effect: Effect): void;
@@ -1 +1 @@
1
- {"version":3,"file":"RenderContext.d.ts","sourceRoot":"","sources":["../../../../../src/devvit/internals/blocks/handler/RenderContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExF;;;;;;;;;GASG;AACH,qBAAa,aAAc,YAAW,aAAa;;IACjD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAElC,SAAS,EAAE,CAAC,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAM;IACnD,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAM;IACrC,WAAW,EAAE,MAAM,CAAM;IACzB,QAAQ,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IACzC,QAAQ,EAAE;QAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAM;IAC1C,qDAAqD;IACrD,cAAc,EAAE,OAAO,EAAE,CAAM;IAE/B,UAAU,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAM;IACxC,UAAU,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAM;IAC5C,MAAM,CAAC,0BAA0B,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;KAAE,CAAM;IACxE,oBAAoB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;KAAE,CAAM;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAEhC,IAAI,aAAa,IAAI,MAAM,CAAC,OAAO,CAKlC;IAED,IAAI,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAExC;gBAEW,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ;IAO9C,0CAA0C;IAC1C,IAAI,aAAa,IAAI,WAAW,CAI/B;IAED,iCAAiC;IACjC,IAAI,MAAM,IAAI,WAAW,CAExB;IAED,4DAA4D;IAC5D,IAAI,MAAM,CAAC,KAAK,EAAE,WAAW,EAG5B;IAED,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIhC,GAAG,IAAI,IAAI;IAIX,0BAA0B,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAInE,gCAAgC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAIzE,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAI3B,MAAM,CAAC,gCAAgC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAI1E,sBAAsB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;IAUnE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAInD;;OAEG;IACH,kBAAkB,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI;IAmB9C,IAAI,OAAO,IAAI,MAAM,EAAE,CAEtB;IAED,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;CA0CzC"}
1
+ {"version":3,"file":"RenderContext.d.ts","sourceRoot":"","sources":["../../../../../src/devvit/internals/blocks/handler/RenderContext.ts"],"names":[],"mappings":"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"}
@@ -55,6 +55,9 @@ export class RenderContext {
55
55
  changed[key] = this._state[key];
56
56
  return changed;
57
57
  }
58
+ get hooks() {
59
+ return this._hooks;
60
+ }
58
61
  /** The complete render state. */
59
62
  get _state() {
60
63
  return __classPrivateFieldGet(this, _RenderContext_state, "f");
@@ -79,6 +82,7 @@ export class RenderContext {
79
82
  getHook(ref) {
80
83
  return this._hooks[ref.id];
81
84
  }
85
+ /** Catches events with no active handler and routes to the corresponding hook to detach/unsubscribe/etc **/
82
86
  static addGlobalUndeliveredEventHandler(id, handler) {
83
87
  RenderContext._staticUndeliveredHandlers[id] = handler;
84
88
  }
@@ -9,9 +9,15 @@ export type Props = {
9
9
  };
10
10
  export type HookSegment = {
11
11
  /**
12
- * This is usually the name of the hook: useAsync, useAsyncState, useChannel,
13
- * useForm, useInterval, useState, etc, the block element, or the component
14
- * name (eg, AppToolbar or FooBar).
12
+ * This is usually the name of the hook: useAsync, useAsyncState,
13
+ * useChannel:channelName, useForm, useInterval, useState, the block element,
14
+ * or the component name (eg, AppToolbar or FooBar).
15
+ *
16
+ * Namespaces can be used to encode additional data such as logically shared
17
+ * instances that would otherwise have to be gathered from Hook instances.
18
+ *
19
+ * Dashes (-) and dots (.) delimit hook IDs so don't use those in your
20
+ * namespace.
15
21
  */
16
22
  namespace?: string;
17
23
  /**
@@ -37,7 +43,7 @@ export type EventHandler = (event: UIEvent, context: RenderContext) => Promise<v
37
43
  * Syncs state between client and server, responds to events, provides user
38
44
  * API, and transitions state across renders.
39
45
  */
40
- export interface Hook {
46
+ export type Hook = {
41
47
  /**
42
48
  * State to carry across renders. Hook constructor arguments are recreated on
43
49
  * render but state may be passed in the render request and used to prime that
@@ -59,7 +65,7 @@ export interface Hook {
59
65
  * 5. state gets serialized.
60
66
  */
61
67
  onStateLoaded?(): void;
62
- }
68
+ };
63
69
  export type HookRef = {
64
70
  id?: string;
65
71
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/devvit/internals/blocks/handler/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG;IAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,KAAK,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;OAKG;IAEH,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAErB;;;OAGG;IAEH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAErF;;;GAGG;AACH,MAAM,WAAW,IAAI;IACnB;;;;OAIG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;IAEzB;;;;;;;;;OASG;IACH,aAAa,CAAC,IAAI,IAAI,CAAC;CACxB;AAED,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,IAAI,IAAI,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;CAAG"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/devvit/internals/blocks/handler/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG;IAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,KAAK,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;OAKG;IAEH,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAErB;;;OAGG;IAEH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAErF;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB;;;;OAIG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;IAEzB;;;;;;;;;OASG;IACH,aAAa,CAAC,IAAI,IAAI,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,IAAI,IAAI,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;CAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"useChannel.d.ts","sourceRoot":"","sources":["../../../../../src/devvit/internals/blocks/handler/useChannel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAyFpE,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAI3E"}
1
+ {"version":3,"file":"useChannel.d.ts","sourceRoot":"","sources":["../../../../../src/devvit/internals/blocks/handler/useChannel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAkIpE,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAU3E"}
@@ -9,31 +9,50 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
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
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _ChannelHook_context, _ChannelHook_invalidate, _ChannelHook_opts;
13
- import { RealtimeSubscriptionStatus } from '@devvit/protos';
12
+ var _ChannelHook_instances, _a, _ChannelHook_context, _ChannelHook_debug, _ChannelHook_invalidate, _ChannelHook_opts, _ChannelHook_emitSubscribed;
13
+ import { EffectType, RealtimeSubscriptionStatus } from '@devvit/protos';
14
14
  import { Header } from '@devvit/shared-types/Header.js';
15
15
  import { ChannelStatus } from '../../../../types/realtime.js';
16
16
  import { registerHook } from './BlocksHandler.js';
17
+ import { RenderContext } from './RenderContext.js';
18
+ const useChannelList = {};
19
+ /** Unsubscribe and delete hooks with no active event handlers **/
20
+ RenderContext.addGlobalUndeliveredEventHandler('useChannel', async (event) => {
21
+ if (event.realtimeEvent && event.hook) {
22
+ useChannelList[event.hook].unsubscribe();
23
+ delete useChannelList[event.hook];
24
+ }
25
+ });
17
26
  class ChannelHook {
18
27
  constructor(opts, params) {
28
+ _ChannelHook_instances.add(this);
19
29
  _ChannelHook_context.set(this, void 0);
30
+ _ChannelHook_debug.set(this, void 0);
20
31
  /** Record state in BlocksHandler. */
21
32
  _ChannelHook_invalidate.set(this, void 0);
22
33
  _ChannelHook_opts.set(this, void 0);
23
34
  __classPrivateFieldSet(this, _ChannelHook_context, params.context, "f");
35
+ __classPrivateFieldSet(this, _ChannelHook_debug, !!params.context._devvitContext?.debug.realtime, "f");
24
36
  __classPrivateFieldSet(this, _ChannelHook_opts, opts, "f");
25
37
  __classPrivateFieldSet(this, _ChannelHook_invalidate, params.invalidate, "f");
26
38
  const appID = params.context.meta[Header.App]?.values[0];
27
39
  if (!appID)
28
- throw Error('useChannel() missing app ID metadata');
40
+ throw Error('useChannel error: missing app ID metadata');
29
41
  const installID = params.context.meta[Header.Installation]?.values[0];
30
42
  if (!installID)
31
- throw Error('useChannel() missing install ID from metadata');
43
+ throw Error('useChannel error: missing install ID from metadata');
44
+ const channel = `${appID}:${installID}:${opts.name}`;
45
+ const duplicate = Object.values(__classPrivateFieldGet(this, _ChannelHook_context, "f").hooks)
46
+ .filter((hook) => hook instanceof _a)
47
+ .some((hook) => hook.state.channel === channel);
48
+ if (duplicate)
49
+ throw Error('useChannel error: channel names must be unique');
32
50
  this.state = {
33
- channel: `${appID}:${installID}:${opts.name}`,
51
+ channel,
34
52
  connected: false,
35
53
  subscribed: false,
36
54
  };
55
+ useChannelList[this.state.channel] = this;
37
56
  }
38
57
  async onUIEvent(ev) {
39
58
  const realtime = ev.realtimeEvent;
@@ -41,16 +60,22 @@ class ChannelHook {
41
60
  return;
42
61
  switch (realtime.status) {
43
62
  case RealtimeSubscriptionStatus.REALTIME_SUBSCRIBED:
63
+ if (__classPrivateFieldGet(this, _ChannelHook_debug, "f"))
64
+ console.debug('[realtime] connected');
44
65
  this.state.connected = true;
45
66
  __classPrivateFieldGet(this, _ChannelHook_invalidate, "f").call(this);
46
67
  await __classPrivateFieldGet(this, _ChannelHook_opts, "f").onSubscribed?.();
47
68
  break;
48
69
  case RealtimeSubscriptionStatus.REALTIME_UNSUBSCRIBED:
70
+ if (__classPrivateFieldGet(this, _ChannelHook_debug, "f"))
71
+ console.debug('[realtime] disconnected');
49
72
  this.state.connected = false;
50
73
  __classPrivateFieldGet(this, _ChannelHook_invalidate, "f").call(this);
51
74
  await __classPrivateFieldGet(this, _ChannelHook_opts, "f").onUnsubscribed?.();
52
75
  break;
53
76
  default:
77
+ if (__classPrivateFieldGet(this, _ChannelHook_debug, "f"))
78
+ console.debug(`[realtime] received message: ${JSON.stringify(ev, undefined, 2)}`);
54
79
  // to-do: define a RealtimeSubscriptionStatus.MESSAGE. this could have
55
80
  // been a oneOf but the current approach allows for status + data
56
81
  // and this default case will break if another new type is added.
@@ -59,8 +84,12 @@ class ChannelHook {
59
84
  }
60
85
  }
61
86
  async send(data) {
62
- if (!this.state.subscribed || !this.state.connected)
63
- throw Error(`send failed; ${this.state.channel} channel not connected`);
87
+ if (__classPrivateFieldGet(this, _ChannelHook_debug, "f"))
88
+ console.debug(`[realtime] send message: ${JSON.stringify(data, undefined, 2)}`);
89
+ if (!this.state.subscribed || !this.state.connected) {
90
+ console.debug(`send failed; ${this.state.channel} channel not connected`);
91
+ throw Error(`useChannel error: send failed; ${this.state.channel} channel not connected`);
92
+ }
64
93
  await __classPrivateFieldGet(this, _ChannelHook_context, "f").devvitContext.realtime.send(this.state.channel, data);
65
94
  }
66
95
  get status() {
@@ -75,19 +104,39 @@ class ChannelHook {
75
104
  subscribe() {
76
105
  if (this.state.subscribed)
77
106
  return;
107
+ if (__classPrivateFieldGet(this, _ChannelHook_debug, "f"))
108
+ console.debug(`[realtime] subscribed`);
78
109
  this.state.subscribed = true;
79
110
  __classPrivateFieldGet(this, _ChannelHook_invalidate, "f").call(this);
111
+ __classPrivateFieldGet(this, _ChannelHook_instances, "m", _ChannelHook_emitSubscribed).call(this);
80
112
  }
81
113
  unsubscribe() {
82
114
  if (!this.state.subscribed)
83
115
  return;
116
+ if (__classPrivateFieldGet(this, _ChannelHook_debug, "f"))
117
+ console.debug(`[realtime] unsubscribed`);
84
118
  this.state.subscribed = false;
85
119
  __classPrivateFieldGet(this, _ChannelHook_invalidate, "f").call(this);
120
+ __classPrivateFieldGet(this, _ChannelHook_instances, "m", _ChannelHook_emitSubscribed).call(this);
86
121
  }
87
122
  }
88
- _ChannelHook_context = new WeakMap(), _ChannelHook_invalidate = new WeakMap(), _ChannelHook_opts = new WeakMap();
123
+ _a = ChannelHook, _ChannelHook_context = new WeakMap(), _ChannelHook_debug = new WeakMap(), _ChannelHook_invalidate = new WeakMap(), _ChannelHook_opts = new WeakMap(), _ChannelHook_instances = new WeakSet(), _ChannelHook_emitSubscribed = function _ChannelHook_emitSubscribed() {
124
+ const channels = Object.values(__classPrivateFieldGet(this, _ChannelHook_context, "f").hooks)
125
+ .filter((hook) => hook instanceof _a && hook.state.subscribed)
126
+ .map((hook) => hook.state.channel);
127
+ __classPrivateFieldGet(this, _ChannelHook_context, "f").emitEffect(`useChannel`, {
128
+ type: EffectType.EFFECT_REALTIME_SUB,
129
+ realtimeSubscriptions: { subscriptionIds: channels },
130
+ });
131
+ };
89
132
  export function useChannel(opts) {
90
- return registerHook({ namespace: 'useChannel' }, (params) => {
133
+ // encode channel name in the hook ID. this would enable sharing channels
134
+ // across useChannel() calls and across components more easily but is
135
+ // currently unused.
136
+ if (!opts.name || /[^a-zA-Z0-9]/.test(opts.name))
137
+ throw Error('useChannel error: channel names must be nonempty and alphanumeric');
138
+ const namespace = `useChannel:${opts.name}`;
139
+ return registerHook({ namespace }, (params) => {
91
140
  return new ChannelHook(opts, params);
92
141
  });
93
142
  }
@@ -38,10 +38,10 @@ export function parseDebug(meta) {
38
38
  blocks: undefined,
39
39
  emitSnapshots: undefined,
40
40
  emitState: undefined,
41
+ realtime: undefined,
41
42
  runtime: undefined,
42
43
  surface: undefined,
43
44
  useAsync: undefined,
44
- useChannel: undefined,
45
45
  };
46
46
  // {[key: Lowercase<AppDebug>]: AppDebug}
47
47
  const lowerKeyToKey = {};
package/index.d.ts CHANGED
@@ -10,4 +10,5 @@ export { useAsync } from './devvit/internals/blocks/handler/useAsync.js';
10
10
  export { useState, useAsyncState } from './devvit/internals/blocks/handler/useState.js';
11
11
  export { useForm } from './devvit/internals/blocks/handler/useForm.js';
12
12
  export { useInterval } from './devvit/internals/blocks/handler/useInterval.js';
13
+ export { useChannel } from './devvit/internals/blocks/handler/useChannel.js';
13
14
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,CAAC;AAE5B,cAAc,+BAA+B,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,cAAc,kBAAkB,CAAC;AACjC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,+CAA+C,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,8CAA8C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,CAAC;AAE5B,cAAc,+BAA+B,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,cAAc,kBAAkB,CAAC;AACjC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,+CAA+C,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,8CAA8C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,iDAAiD,CAAC"}
package/index.js CHANGED
@@ -9,3 +9,4 @@ export { useAsync } from './devvit/internals/blocks/handler/useAsync.js';
9
9
  export { useState, useAsyncState } from './devvit/internals/blocks/handler/useState.js';
10
10
  export { useForm } from './devvit/internals/blocks/handler/useForm.js';
11
11
  export { useInterval } from './devvit/internals/blocks/handler/useInterval.js';
12
+ export { useChannel } from './devvit/internals/blocks/handler/useChannel.js';
package/meta.json CHANGED
@@ -10066,7 +10066,7 @@
10066
10066
  "format": "esm"
10067
10067
  },
10068
10068
  "../protos/dist/types/devvit/plugin/redditapi/listings/listings_svc.js": {
10069
- "bytes": 35535,
10069
+ "bytes": 25214,
10070
10070
  "imports": [
10071
10071
  {
10072
10072
  "path": "../../node_modules/protobufjs/minimal.js",
@@ -11368,7 +11368,7 @@
11368
11368
  "format": "esm"
11369
11369
  },
11370
11370
  "../shared-types/dist/Header.js": {
11371
- "bytes": 1800,
11371
+ "bytes": 1809,
11372
11372
  "imports": [],
11373
11373
  "format": "esm"
11374
11374
  },
@@ -11764,7 +11764,7 @@
11764
11764
  "imports": []
11765
11765
  },
11766
11766
  "src/devvit/internals/context.ts": {
11767
- "bytes": 2683,
11767
+ "bytes": 2681,
11768
11768
  "imports": [
11769
11769
  {
11770
11770
  "path": "../shared-types/dist/Header.js",
@@ -12305,8 +12305,19 @@
12305
12305
  ],
12306
12306
  "format": "esm"
12307
12307
  },
12308
+ "src/devvit/internals/blocks/handler/RenderContext.ts": {
12309
+ "bytes": 5690,
12310
+ "imports": [
12311
+ {
12312
+ "path": "<runtime>",
12313
+ "kind": "import-statement",
12314
+ "external": true
12315
+ }
12316
+ ],
12317
+ "format": "esm"
12318
+ },
12308
12319
  "src/devvit/internals/blocks/handler/useChannel.ts": {
12309
- "bytes": 3523,
12320
+ "bytes": 5710,
12310
12321
  "imports": [
12311
12322
  {
12312
12323
  "path": "../protos/dist/index.js",
@@ -12329,16 +12340,10 @@
12329
12340
  "original": "./BlocksHandler.js"
12330
12341
  },
12331
12342
  {
12332
- "path": "<runtime>",
12343
+ "path": "src/devvit/internals/blocks/handler/RenderContext.ts",
12333
12344
  "kind": "import-statement",
12334
- "external": true
12335
- }
12336
- ],
12337
- "format": "esm"
12338
- },
12339
- "src/devvit/internals/blocks/handler/RenderContext.ts": {
12340
- "bytes": 5495,
12341
- "imports": [
12345
+ "original": "./RenderContext.js"
12346
+ },
12342
12347
  {
12343
12348
  "path": "<runtime>",
12344
12349
  "kind": "import-statement",
@@ -12374,7 +12379,7 @@
12374
12379
  "format": "esm"
12375
12380
  },
12376
12381
  "src/devvit/internals/blocks/handler/types.ts": {
12377
- "bytes": 2887,
12382
+ "bytes": 3147,
12378
12383
  "imports": [],
12379
12384
  "format": "esm"
12380
12385
  },
@@ -13346,7 +13351,7 @@
13346
13351
  "format": "esm"
13347
13352
  },
13348
13353
  "src/index.ts": {
13349
- "bytes": 707,
13354
+ "bytes": 785,
13350
13355
  "imports": [
13351
13356
  {
13352
13357
  "path": "../../node_modules/core-js/web/url.js",
@@ -13402,6 +13407,11 @@
13402
13407
  "path": "src/devvit/internals/blocks/handler/useInterval.ts",
13403
13408
  "kind": "import-statement",
13404
13409
  "original": "./devvit/internals/blocks/handler/useInterval.js"
13410
+ },
13411
+ {
13412
+ "path": "src/devvit/internals/blocks/handler/useChannel.ts",
13413
+ "kind": "import-statement",
13414
+ "original": "./devvit/internals/blocks/handler/useChannel.js"
13405
13415
  }
13406
13416
  ],
13407
13417
  "format": "esm"
@@ -13831,7 +13841,7 @@
13831
13841
  "bytesInOutput": 3912
13832
13842
  },
13833
13843
  "src/index.ts": {
13834
- "bytesInOutput": 1826
13844
+ "bytesInOutput": 1860
13835
13845
  },
13836
13846
  "../shared-types/dist/NonNull.js": {
13837
13847
  "bytesInOutput": 118
@@ -14227,7 +14237,7 @@
14227
14237
  "bytesInOutput": 43555
14228
14238
  },
14229
14239
  "../protos/dist/types/devvit/plugin/redditapi/listings/listings_svc.js": {
14230
- "bytesInOutput": 21563
14240
+ "bytesInOutput": 15070
14231
14241
  },
14232
14242
  "../protos/dist/types/devvit/plugin/redditapi/listings/listings_msg.js": {
14233
14243
  "bytesInOutput": 38038
@@ -14299,7 +14309,7 @@
14299
14309
  "bytesInOutput": 86
14300
14310
  },
14301
14311
  "../shared-types/dist/Header.js": {
14302
- "bytesInOutput": 1185
14312
+ "bytesInOutput": 1181
14303
14313
  },
14304
14314
  "src/devvit/internals/blocks/useChannel.ts": {
14305
14315
  "bytesInOutput": 3627
@@ -14359,7 +14369,7 @@
14359
14369
  "bytesInOutput": 2930
14360
14370
  },
14361
14371
  "src/devvit/internals/context.ts": {
14362
- "bytesInOutput": 1798
14372
+ "bytesInOutput": 1796
14363
14373
  },
14364
14374
  "src/devvit/internals/helpers/settingsUtils.ts": {
14365
14375
  "bytesInOutput": 1229
@@ -14410,7 +14420,7 @@
14410
14420
  "bytesInOutput": 3085
14411
14421
  },
14412
14422
  "src/devvit/internals/blocks/handler/BlocksHandler.ts": {
14413
- "bytesInOutput": 13784
14423
+ "bytesInOutput": 13799
14414
14424
  },
14415
14425
  "src/devvit/internals/blocks/handler/useForm.ts": {
14416
14426
  "bytesInOutput": 915
@@ -14418,11 +14428,11 @@
14418
14428
  "src/devvit/internals/blocks/handler/UIClient.ts": {
14419
14429
  "bytesInOutput": 2049
14420
14430
  },
14421
- "src/devvit/internals/blocks/handler/useChannel.ts": {
14422
- "bytesInOutput": 2808
14423
- },
14424
14431
  "src/devvit/internals/blocks/handler/RenderContext.ts": {
14425
- "bytesInOutput": 4138
14432
+ "bytesInOutput": 4301
14433
+ },
14434
+ "src/devvit/internals/blocks/handler/useChannel.ts": {
14435
+ "bytesInOutput": 5176
14426
14436
  },
14427
14437
  "src/devvit/internals/blocks/handler/useInterval.ts": {
14428
14438
  "bytesInOutput": 2357
@@ -14524,7 +14534,7 @@
14524
14534
  "bytesInOutput": 4450
14525
14535
  }
14526
14536
  },
14527
- "bytes": 14994832
14537
+ "bytes": 14977549
14528
14538
  }
14529
14539
  }
14530
14540
  }
package/meta.min.json CHANGED
@@ -2598,7 +2598,7 @@
2598
2598
  "format": "esm"
2599
2599
  },
2600
2600
  "../shared-types/dist/Header.js": {
2601
- "bytes": 1800,
2601
+ "bytes": 1809,
2602
2602
  "imports": [],
2603
2603
  "format": "esm"
2604
2604
  },
@@ -2994,7 +2994,7 @@
2994
2994
  "imports": []
2995
2995
  },
2996
2996
  "src/devvit/internals/context.ts": {
2997
- "bytes": 2683,
2997
+ "bytes": 2681,
2998
2998
  "imports": [
2999
2999
  {
3000
3000
  "path": "../shared-types/dist/Header.js",
@@ -3535,8 +3535,19 @@
3535
3535
  ],
3536
3536
  "format": "esm"
3537
3537
  },
3538
+ "src/devvit/internals/blocks/handler/RenderContext.ts": {
3539
+ "bytes": 5690,
3540
+ "imports": [
3541
+ {
3542
+ "path": "<runtime>",
3543
+ "kind": "import-statement",
3544
+ "external": true
3545
+ }
3546
+ ],
3547
+ "format": "esm"
3548
+ },
3538
3549
  "src/devvit/internals/blocks/handler/useChannel.ts": {
3539
- "bytes": 3523,
3550
+ "bytes": 5710,
3540
3551
  "imports": [
3541
3552
  {
3542
3553
  "path": "@devvit/protos",
@@ -3559,16 +3570,10 @@
3559
3570
  "original": "./BlocksHandler.js"
3560
3571
  },
3561
3572
  {
3562
- "path": "<runtime>",
3573
+ "path": "src/devvit/internals/blocks/handler/RenderContext.ts",
3563
3574
  "kind": "import-statement",
3564
- "external": true
3565
- }
3566
- ],
3567
- "format": "esm"
3568
- },
3569
- "src/devvit/internals/blocks/handler/RenderContext.ts": {
3570
- "bytes": 5495,
3571
- "imports": [
3575
+ "original": "./RenderContext.js"
3576
+ },
3572
3577
  {
3573
3578
  "path": "<runtime>",
3574
3579
  "kind": "import-statement",
@@ -3604,7 +3609,7 @@
3604
3609
  "format": "esm"
3605
3610
  },
3606
3611
  "src/devvit/internals/blocks/handler/types.ts": {
3607
- "bytes": 2887,
3612
+ "bytes": 3147,
3608
3613
  "imports": [],
3609
3614
  "format": "esm"
3610
3615
  },
@@ -4576,7 +4581,7 @@
4576
4581
  "format": "esm"
4577
4582
  },
4578
4583
  "src/index.ts": {
4579
- "bytes": 707,
4584
+ "bytes": 785,
4580
4585
  "imports": [
4581
4586
  {
4582
4587
  "path": "../../node_modules/core-js/web/url.js",
@@ -4632,6 +4637,11 @@
4632
4637
  "path": "src/devvit/internals/blocks/handler/useInterval.ts",
4633
4638
  "kind": "import-statement",
4634
4639
  "original": "./devvit/internals/blocks/handler/useInterval.js"
4640
+ },
4641
+ {
4642
+ "path": "src/devvit/internals/blocks/handler/useChannel.ts",
4643
+ "kind": "import-statement",
4644
+ "original": "./devvit/internals/blocks/handler/useChannel.js"
4635
4645
  }
4636
4646
  ],
4637
4647
  "format": "esm"
@@ -4642,7 +4652,7 @@
4642
4652
  "imports": [],
4643
4653
  "exports": [],
4644
4654
  "inputs": {},
4645
- "bytes": 1136297
4655
+ "bytes": 1140612
4646
4656
  },
4647
4657
  "dist/public-api.min.js": {
4648
4658
  "imports": [
@@ -4799,6 +4809,7 @@
4799
4809
  "svg",
4800
4810
  "useAsync",
4801
4811
  "useAsyncState",
4812
+ "useChannel",
4802
4813
  "useForm",
4803
4814
  "useInterval",
4804
4815
  "useState"
@@ -5214,7 +5225,7 @@
5214
5225
  "bytesInOutput": 1537
5215
5226
  },
5216
5227
  "../shared-types/dist/Header.js": {
5217
- "bytesInOutput": 869
5228
+ "bytesInOutput": 865
5218
5229
  },
5219
5230
  "src/apis/ui/helpers/getFormValues.ts": {
5220
5231
  "bytesInOutput": 407
@@ -5271,7 +5282,7 @@
5271
5282
  "bytesInOutput": 2377
5272
5283
  },
5273
5284
  "src/devvit/internals/context.ts": {
5274
- "bytesInOutput": 940
5285
+ "bytesInOutput": 938
5275
5286
  },
5276
5287
  "src/devvit/internals/custom-post.ts": {
5277
5288
  "bytesInOutput": 350
@@ -5328,14 +5339,14 @@
5328
5339
  "bytesInOutput": 422
5329
5340
  },
5330
5341
  "src/devvit/internals/blocks/handler/useChannel.ts": {
5331
- "bytesInOutput": 1519
5342
+ "bytesInOutput": 2903
5343
+ },
5344
+ "src/devvit/internals/blocks/handler/RenderContext.ts": {
5345
+ "bytesInOutput": 2082
5332
5346
  },
5333
5347
  "src/devvit/internals/blocks/handler/useInterval.ts": {
5334
5348
  "bytesInOutput": 1184
5335
5349
  },
5336
- "src/devvit/internals/blocks/handler/RenderContext.ts": {
5337
- "bytesInOutput": 2051
5338
- },
5339
5350
  "src/devvit/internals/blocks/handler/types.ts": {
5340
5351
  "bytesInOutput": 29
5341
5352
  },
@@ -5427,7 +5438,7 @@
5427
5438
  "bytesInOutput": 2135
5428
5439
  }
5429
5440
  },
5430
- "bytes": 242970
5441
+ "bytes": 244396
5431
5442
  }
5432
5443
  }
5433
5444
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devvit/public-api",
3
- "version": "0.10.23-next-2024-06-13-b4fe6dd97.0",
3
+ "version": "0.10.23-next-2024-06-13-8c5a69306.0",
4
4
  "license": "BSD-3-Clause",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,8 +30,8 @@
30
30
  },
31
31
  "types": "./index.d.ts",
32
32
  "dependencies": {
33
- "@devvit/protos": "0.10.23-next-2024-06-13-b4fe6dd97.0",
34
- "@devvit/shared-types": "0.10.23-next-2024-06-13-b4fe6dd97.0",
33
+ "@devvit/protos": "0.10.23-next-2024-06-13-8c5a69306.0",
34
+ "@devvit/shared-types": "0.10.23-next-2024-06-13-8c5a69306.0",
35
35
  "base64-js": "1.5.1",
36
36
  "clone-deep": "4.0.1",
37
37
  "core-js": "3.27.2",
@@ -41,7 +41,7 @@
41
41
  "@ampproject/filesize": "4.3.0",
42
42
  "@devvit/eslint-config": "0.10.22",
43
43
  "@devvit/repo-tools": "0.10.22",
44
- "@devvit/tsconfig": "0.10.23-next-2024-06-13-b4fe6dd97.0",
44
+ "@devvit/tsconfig": "0.10.23-next-2024-06-13-8c5a69306.0",
45
45
  "@microsoft/api-extractor": "7.41.0",
46
46
  "@reddit/faceplate-ui": "11.3.3",
47
47
  "@types/clone-deep": "4.0.1",
@@ -64,5 +64,5 @@
64
64
  }
65
65
  },
66
66
  "source": "./src/index.ts",
67
- "gitHead": "d96d7aa0244d2710146e1a6d779c2e59863c9f58"
67
+ "gitHead": "b31c59acd646237d8ffcb68ffc82fd18a429476f"
68
68
  }