@bunworks/inngest-realtime 0.1.0 → 0.1.5

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.
Files changed (101) hide show
  1. package/CHANGELOG.md +6 -6
  2. package/README.md +1 -1
  3. package/_virtual/_rolldown/runtime.cjs +29 -0
  4. package/api.cjs +45 -0
  5. package/api.cjs.map +1 -0
  6. package/api.mjs +44 -0
  7. package/api.mjs.map +1 -0
  8. package/channel.cjs +67 -0
  9. package/channel.cjs.map +1 -0
  10. package/channel.d.cts +19 -0
  11. package/channel.d.cts.map +1 -0
  12. package/channel.d.mts +19 -0
  13. package/channel.d.mts.map +1 -0
  14. package/channel.mjs +66 -0
  15. package/channel.mjs.map +1 -0
  16. package/env.cjs +72 -0
  17. package/env.cjs.map +1 -0
  18. package/env.mjs +71 -0
  19. package/env.mjs.map +1 -0
  20. package/hooks.cjs +147 -0
  21. package/hooks.cjs.map +1 -0
  22. package/hooks.d.cts +70 -0
  23. package/hooks.d.cts.map +1 -0
  24. package/hooks.d.mts +70 -0
  25. package/hooks.d.mts.map +1 -0
  26. package/hooks.mjs +144 -0
  27. package/hooks.mjs.map +1 -0
  28. package/index.cjs +19 -0
  29. package/index.d.cts +5 -0
  30. package/index.d.mts +6 -0
  31. package/index.mjs +7 -0
  32. package/middleware.cjs +41 -0
  33. package/middleware.cjs.map +1 -0
  34. package/middleware.d.cts +29 -0
  35. package/middleware.d.cts.map +1 -0
  36. package/middleware.d.mts +29 -0
  37. package/middleware.d.mts.map +1 -0
  38. package/middleware.mjs +34 -0
  39. package/middleware.mjs.map +1 -0
  40. package/package.json +6 -5
  41. package/subscribe/StreamFanout.cjs +47 -0
  42. package/subscribe/StreamFanout.cjs.map +1 -0
  43. package/subscribe/StreamFanout.mjs +46 -0
  44. package/subscribe/StreamFanout.mjs.map +1 -0
  45. package/subscribe/TokenSubscription.cjs +438 -0
  46. package/subscribe/TokenSubscription.cjs.map +1 -0
  47. package/subscribe/TokenSubscription.mjs +436 -0
  48. package/subscribe/TokenSubscription.mjs.map +1 -0
  49. package/subscribe/helpers.cjs +41 -0
  50. package/subscribe/helpers.cjs.map +1 -0
  51. package/subscribe/helpers.d.cts +64 -0
  52. package/subscribe/helpers.d.cts.map +1 -0
  53. package/subscribe/helpers.d.mts +64 -0
  54. package/subscribe/helpers.d.mts.map +1 -0
  55. package/subscribe/helpers.mjs +40 -0
  56. package/subscribe/helpers.mjs.map +1 -0
  57. package/subscribe/index.cjs +1 -0
  58. package/subscribe/index.d.mts +1 -0
  59. package/subscribe/index.mjs +3 -0
  60. package/topic.cjs +30 -0
  61. package/topic.cjs.map +1 -0
  62. package/topic.d.cts +19 -0
  63. package/topic.d.cts.map +1 -0
  64. package/topic.d.mts +19 -0
  65. package/topic.d.mts.map +1 -0
  66. package/topic.mjs +28 -0
  67. package/topic.mjs.map +1 -0
  68. package/types.cjs +45 -0
  69. package/types.cjs.map +1 -0
  70. package/types.d.cts +241 -0
  71. package/types.d.cts.map +1 -0
  72. package/types.d.mts +241 -0
  73. package/types.d.mts.map +1 -0
  74. package/types.mjs +39 -0
  75. package/types.mjs.map +1 -0
  76. package/util.cjs +72 -0
  77. package/util.cjs.map +1 -0
  78. package/util.mjs +69 -0
  79. package/util.mjs.map +1 -0
  80. package/CLAUDE.md +0 -69
  81. package/bun.lock +0 -527
  82. package/eslint.config.mjs +0 -19
  83. package/src/api.ts +0 -83
  84. package/src/channel.ts +0 -122
  85. package/src/env.d.ts +0 -15
  86. package/src/env.ts +0 -152
  87. package/src/hooks.ts +0 -256
  88. package/src/index.test.ts +0 -840
  89. package/src/index.ts +0 -4
  90. package/src/middleware.ts +0 -68
  91. package/src/subscribe/StreamFanout.ts +0 -82
  92. package/src/subscribe/TokenSubscription.ts +0 -524
  93. package/src/subscribe/helpers.ts +0 -153
  94. package/src/subscribe/index.ts +0 -1
  95. package/src/topic.ts +0 -51
  96. package/src/types.ts +0 -499
  97. package/src/util.ts +0 -104
  98. package/tsconfig.build.json +0 -7
  99. package/tsconfig.json +0 -114
  100. package/tsdown.config.ts +0 -18
  101. package/vitest.config.ts +0 -22
package/hooks.cjs ADDED
@@ -0,0 +1,147 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
3
+ const require_helpers = require('./subscribe/helpers.cjs');
4
+ require('./subscribe/index.cjs');
5
+ let react = require("react");
6
+
7
+ //#region src/hooks.ts
8
+ let InngestSubscriptionState = /* @__PURE__ */ function(InngestSubscriptionState) {
9
+ InngestSubscriptionState["Closed"] = "closed";
10
+ InngestSubscriptionState["Error"] = "error";
11
+ InngestSubscriptionState["RefreshingToken"] = "refresh_token";
12
+ InngestSubscriptionState["Connecting"] = "connecting";
13
+ InngestSubscriptionState["Active"] = "active";
14
+ InngestSubscriptionState["Closing"] = "closing";
15
+ return InngestSubscriptionState;
16
+ }({});
17
+ /**
18
+ * React hook for subscribing to Inngest realtime channels
19
+ */
20
+ function useInngestSubscription({ token: tokenInput, refreshToken, key, enabled = true, bufferInterval = 0 }) {
21
+ const [token, setToken] = (0, react.useState)(tokenInput);
22
+ const [data, setData] = (0, react.useState)([]);
23
+ const [freshData, setFreshData] = (0, react.useState)([]);
24
+ const [error, setError] = (0, react.useState)(null);
25
+ const [state, setState] = (0, react.useState)(InngestSubscriptionState.Closed);
26
+ const subscriptionRef = (0, react.useRef)(null);
27
+ const readerRef = (0, react.useRef)(null);
28
+ const messageBuffer = (0, react.useRef)([]);
29
+ const bufferIntervalRef = (0, react.useRef)(bufferInterval);
30
+ (0, react.useEffect)(() => {
31
+ if (tokenInput) setToken(tokenInput);
32
+ }, [tokenInput]);
33
+ (0, react.useEffect)(() => {
34
+ if (!token && enabled) if (refreshToken) {
35
+ setState(InngestSubscriptionState.RefreshingToken);
36
+ refreshToken().then((newToken) => setToken(newToken)).catch((err) => {
37
+ setError(err);
38
+ setState(InngestSubscriptionState.Error);
39
+ });
40
+ } else {
41
+ setError(/* @__PURE__ */ new Error("No token provided and no refreshToken handler."));
42
+ setState(InngestSubscriptionState.Error);
43
+ }
44
+ }, []);
45
+ (0, react.useEffect)(() => {
46
+ setError(null);
47
+ if (!enabled || !token) return;
48
+ let cancelled = false;
49
+ const start = async () => {
50
+ try {
51
+ setState(InngestSubscriptionState.Connecting);
52
+ const stream = await require_helpers.subscribe({ ...token });
53
+ if (cancelled) return;
54
+ subscriptionRef.current = stream;
55
+ setState(InngestSubscriptionState.Active);
56
+ const reader = stream.getReader();
57
+ readerRef.current = reader;
58
+ try {
59
+ while (!cancelled) {
60
+ const { done, value } = await reader.read();
61
+ if (done || cancelled) break;
62
+ if (bufferIntervalRef.current === 0) {
63
+ setFreshData([value]);
64
+ setData((prev) => [...prev, value]);
65
+ } else messageBuffer.current.push(value);
66
+ }
67
+ } finally {
68
+ try {
69
+ reader.releaseLock();
70
+ } catch {}
71
+ readerRef.current = null;
72
+ }
73
+ if (!cancelled) {
74
+ setState(InngestSubscriptionState.Closed);
75
+ if (enabled) start();
76
+ }
77
+ } catch (err) {
78
+ if (cancelled) return;
79
+ if (refreshToken) {
80
+ setState(InngestSubscriptionState.RefreshingToken);
81
+ refreshToken().then((newToken) => setToken(newToken)).catch((e) => {
82
+ setError(e);
83
+ setState(InngestSubscriptionState.Error);
84
+ });
85
+ } else {
86
+ setError(err);
87
+ setState(InngestSubscriptionState.Error);
88
+ }
89
+ }
90
+ };
91
+ start();
92
+ return () => {
93
+ cancelled = true;
94
+ const cleanup = async () => {
95
+ const readerToRemove = readerRef.current;
96
+ const subToRemove = subscriptionRef.current;
97
+ readerRef.current = null;
98
+ subscriptionRef.current = null;
99
+ try {
100
+ await readerToRemove?.cancel();
101
+ } catch {}
102
+ try {
103
+ readerToRemove?.releaseLock();
104
+ } catch {}
105
+ try {
106
+ await subToRemove?.cancel();
107
+ } catch {}
108
+ };
109
+ cleanup().catch((err) => {
110
+ console.error("Error cleaning up Inngest subscription", err);
111
+ }).finally(() => {
112
+ setState(InngestSubscriptionState.Closed);
113
+ });
114
+ };
115
+ }, [
116
+ token,
117
+ enabled,
118
+ key
119
+ ]);
120
+ (0, react.useEffect)(() => {
121
+ bufferIntervalRef.current = bufferInterval;
122
+ let interval = null;
123
+ if (bufferInterval > 0) interval = setInterval(() => {
124
+ if (messageBuffer.current.length > 0) {
125
+ const buffered = [...messageBuffer.current];
126
+ messageBuffer.current = [];
127
+ setFreshData(buffered);
128
+ setData((prev) => [...prev, ...buffered]);
129
+ }
130
+ }, bufferInterval);
131
+ return () => {
132
+ if (interval) clearInterval(interval);
133
+ };
134
+ }, [bufferInterval]);
135
+ return {
136
+ data,
137
+ latestData: data[data.length - 1] ?? null,
138
+ freshData,
139
+ error,
140
+ state
141
+ };
142
+ }
143
+
144
+ //#endregion
145
+ exports.InngestSubscriptionState = InngestSubscriptionState;
146
+ exports.useInngestSubscription = useInngestSubscription;
147
+ //# sourceMappingURL=hooks.cjs.map
package/hooks.cjs.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.cjs","names":["subscribe"],"sources":["../src/hooks.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\r\nimport { subscribe } from \"./subscribe\";\r\nimport { type Realtime } from \"./types\";\r\n\r\nexport enum InngestSubscriptionState {\r\n Closed = \"closed\",\r\n Error = \"error\",\r\n RefreshingToken = \"refresh_token\",\r\n Connecting = \"connecting\",\r\n Active = \"active\",\r\n Closing = \"closing\",\r\n}\r\n\r\n/**\r\n * Inngest subscription state and data\r\n */\r\nexport interface InngestSubscription<TToken extends Realtime.Subscribe.Token> {\r\n /**\r\n * All received messages\r\n */\r\n data: Realtime.Subscribe.Token.InferMessage<TToken>[];\r\n\r\n /**\r\n * Most recent message\r\n */\r\n latestData: Realtime.Subscribe.Token.InferMessage<TToken> | null;\r\n\r\n /**\r\n * Messages received since last render\r\n */\r\n freshData: Realtime.Subscribe.Token.InferMessage<TToken>[];\r\n\r\n /**\r\n * Connection or subscription error\r\n */\r\n error: Error | null;\r\n\r\n /**\r\n * Current subscription state\r\n */\r\n state: InngestSubscriptionState;\r\n}\r\n\r\n/**\r\n * React hook for subscribing to Inngest realtime channels\r\n */\r\nexport function useInngestSubscription<\r\n const TToken extends Realtime.Subscribe.Token | null | undefined,\r\n>({\r\n token: tokenInput,\r\n refreshToken,\r\n key,\r\n enabled = true,\r\n bufferInterval = 0,\r\n}: {\r\n /**\r\n * Subscription token\r\n */\r\n token?: TToken;\r\n\r\n /**\r\n * Function to refresh token when needed\r\n */\r\n refreshToken?: () => Promise<TToken>;\r\n\r\n /**\r\n * Unique key to force reconnection\r\n */\r\n key?: string;\r\n\r\n /**\r\n * Whether subscription is enabled\r\n */\r\n enabled?: boolean;\r\n\r\n /**\r\n * Interval in ms to buffer messages (0 = no buffering)\r\n */\r\n bufferInterval?: number;\r\n}): InngestSubscription<NonNullable<TToken>> {\r\n const [token, setToken] = useState<TToken | null | undefined>(tokenInput);\r\n const [data, setData] = useState<Realtime.Message[]>([]);\r\n const [freshData, setFreshData] = useState<Realtime.Message[]>([]);\r\n const [error, setError] = useState<Error | null>(null);\r\n const [state, setState] = useState<InngestSubscriptionState>(\r\n InngestSubscriptionState.Closed,\r\n );\r\n\r\n const subscriptionRef = useRef<Realtime.Subscribe.StreamSubscription | null>(\r\n null,\r\n );\r\n const readerRef =\r\n useRef<ReadableStreamDefaultReader<Realtime.Message> | null>(null);\r\n const messageBuffer = useRef<Realtime.Message[]>([]);\r\n const bufferIntervalRef = useRef<number>(bufferInterval);\r\n\r\n // Sync token if tokenInput prop changes\r\n useEffect(() => {\r\n if (tokenInput) setToken(tokenInput);\r\n }, [tokenInput]);\r\n\r\n // Token fetch fallback on mount\r\n useEffect(() => {\r\n if (!token && enabled) {\r\n if (refreshToken) {\r\n setState(InngestSubscriptionState.RefreshingToken);\r\n refreshToken()\r\n .then((newToken) => setToken(newToken))\r\n .catch((err) => {\r\n setError(err);\r\n setState(InngestSubscriptionState.Error);\r\n });\r\n } else {\r\n setError(new Error(\"No token provided and no refreshToken handler.\"));\r\n setState(InngestSubscriptionState.Error);\r\n }\r\n }\r\n }, []);\r\n\r\n // Subscription management\r\n useEffect(() => {\r\n setError(null);\r\n if (!enabled || !token) return;\r\n let cancelled = false;\r\n\r\n const start = async () => {\r\n try {\r\n setState(InngestSubscriptionState.Connecting);\r\n const stream = await subscribe({ ...token });\r\n if (cancelled) return;\r\n\r\n subscriptionRef.current = stream;\r\n setState(InngestSubscriptionState.Active);\r\n\r\n // Explicitly get and manage the reader so that we can manually release\r\n // the lock if anything goes wrong or we're done with it.\r\n //\r\n // Especially when this is unmounted.\r\n const reader = stream.getReader();\r\n readerRef.current = reader;\r\n try {\r\n while (!cancelled) {\r\n const { done, value } = await reader.read();\r\n if (done || cancelled) break;\r\n\r\n if (bufferIntervalRef.current === 0) {\r\n setFreshData([value]);\r\n setData((prev) => [...prev, value]);\r\n } else {\r\n messageBuffer.current.push(value);\r\n }\r\n }\r\n } finally {\r\n try {\r\n reader.releaseLock();\r\n } catch {\r\n // Reader might already be released\r\n }\r\n\r\n readerRef.current = null;\r\n }\r\n\r\n // Stream has closed cleanly\r\n if (!cancelled) {\r\n setState(InngestSubscriptionState.Closed);\r\n if (enabled) start();\r\n }\r\n } catch (err) {\r\n if (cancelled) return;\r\n if (refreshToken) {\r\n setState(InngestSubscriptionState.RefreshingToken);\r\n refreshToken()\r\n .then((newToken) => setToken(newToken))\r\n .catch((e) => {\r\n setError(e);\r\n setState(InngestSubscriptionState.Error);\r\n });\r\n } else {\r\n setError(err as Error);\r\n setState(InngestSubscriptionState.Error);\r\n }\r\n }\r\n };\r\n\r\n start();\r\n\r\n return () => {\r\n cancelled = true;\r\n\r\n const cleanup = async () => {\r\n const readerToRemove = readerRef.current;\r\n const subToRemove = subscriptionRef.current;\r\n\r\n readerRef.current = null;\r\n subscriptionRef.current = null;\r\n\r\n try {\r\n await readerToRemove?.cancel();\r\n } catch {\r\n // Reader might already be cancelled\r\n }\r\n\r\n try {\r\n readerToRemove?.releaseLock();\r\n } catch {\r\n // Reader might already be released\r\n }\r\n\r\n try {\r\n await subToRemove?.cancel();\r\n } catch {\r\n // Subscription might already be cancelled\r\n }\r\n };\r\n\r\n cleanup()\r\n .catch((err) => {\r\n console.error(\"Error cleaning up Inngest subscription\", err);\r\n })\r\n .finally(() => {\r\n // Ensure state is always updated even if cleanup fails\r\n setState(InngestSubscriptionState.Closed);\r\n });\r\n };\r\n }, [token, enabled, key]);\r\n\r\n // Buffer flushing\r\n useEffect(() => {\r\n bufferIntervalRef.current = bufferInterval;\r\n let interval: NodeJS.Timeout | null = null;\r\n\r\n if (bufferInterval > 0) {\r\n interval = setInterval(() => {\r\n if (messageBuffer.current.length > 0) {\r\n const buffered = [...messageBuffer.current];\r\n messageBuffer.current = [];\r\n\r\n setFreshData(buffered);\r\n setData((prev) => [...prev, ...buffered]);\r\n }\r\n }, bufferInterval);\r\n }\r\n\r\n return () => {\r\n if (interval) clearInterval(interval);\r\n };\r\n }, [bufferInterval]);\r\n\r\n return {\r\n data,\r\n latestData: data[data.length - 1] ?? null,\r\n freshData,\r\n error,\r\n state,\r\n } as unknown as InngestSubscription<NonNullable<TToken>>;\r\n}\r\n"],"mappings":"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"}
package/hooks.d.cts ADDED
@@ -0,0 +1,70 @@
1
+ import { Realtime } from "./types.cjs";
2
+
3
+ //#region src/hooks.d.ts
4
+ declare enum InngestSubscriptionState {
5
+ Closed = "closed",
6
+ Error = "error",
7
+ RefreshingToken = "refresh_token",
8
+ Connecting = "connecting",
9
+ Active = "active",
10
+ Closing = "closing"
11
+ }
12
+ /**
13
+ * Inngest subscription state and data
14
+ */
15
+ interface InngestSubscription<TToken extends Realtime.Subscribe.Token> {
16
+ /**
17
+ * All received messages
18
+ */
19
+ data: Realtime.Subscribe.Token.InferMessage<TToken>[];
20
+ /**
21
+ * Most recent message
22
+ */
23
+ latestData: Realtime.Subscribe.Token.InferMessage<TToken> | null;
24
+ /**
25
+ * Messages received since last render
26
+ */
27
+ freshData: Realtime.Subscribe.Token.InferMessage<TToken>[];
28
+ /**
29
+ * Connection or subscription error
30
+ */
31
+ error: Error | null;
32
+ /**
33
+ * Current subscription state
34
+ */
35
+ state: InngestSubscriptionState;
36
+ }
37
+ /**
38
+ * React hook for subscribing to Inngest realtime channels
39
+ */
40
+ declare function useInngestSubscription<const TToken extends Realtime.Subscribe.Token | null | undefined>({
41
+ token: tokenInput,
42
+ refreshToken,
43
+ key,
44
+ enabled,
45
+ bufferInterval
46
+ }: {
47
+ /**
48
+ * Subscription token
49
+ */
50
+ token?: TToken;
51
+ /**
52
+ * Function to refresh token when needed
53
+ */
54
+ refreshToken?: () => Promise<TToken>;
55
+ /**
56
+ * Unique key to force reconnection
57
+ */
58
+ key?: string;
59
+ /**
60
+ * Whether subscription is enabled
61
+ */
62
+ enabled?: boolean;
63
+ /**
64
+ * Interval in ms to buffer messages (0 = no buffering)
65
+ */
66
+ bufferInterval?: number;
67
+ }): InngestSubscription<NonNullable<TToken>>;
68
+ //#endregion
69
+ export { InngestSubscription, InngestSubscriptionState, useInngestSubscription };
70
+ //# sourceMappingURL=hooks.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.cts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;aAIY,wBAAA;EACV,MAAA;EACA,KAAA;EACA,eAAA;EACA,UAAA;EACA,MAAA;EACA,OAAA;AAAA;;;;UAMe,mBAAA,gBAAmC,QAAA,CAAS,SAAA,CAAU,KAAA;EAN9D;;AAMT;EAIE,IAAA,EAAM,QAAA,CAAS,SAAA,CAAU,KAAA,CAAM,YAAA,CAAa,MAAA;EAJV;;;EASlC,UAAA,EAAY,QAAA,CAAS,SAAA,CAAU,KAAA,CAAM,YAAA,CAAa,MAAA;EAAA;;;EAKlD,SAAA,EAAW,QAAA,CAAS,SAAA,CAAU,KAAA,CAAM,YAAA,CAAa,MAAA;EAK1C;;;EAAP,KAAA,EAAO,KAAA;EAnB4B;;;EAwBnC,KAAA,EAAO,wBAAA;AAAA;;;;iBAMO,sBAAA,sBACO,QAAA,CAAS,SAAA,CAAU,KAAA,oBAAA,CAAA;EAExC,KAAA,EAAO,UAAA;EACP,YAAA;EACA,GAAA;EACA,OAAA;EACA;AAAA;EAjC4C;;;EAsC5C,KAAA,GAAQ,MAAA;EAjCuB;;;EAsC/B,YAAA,SAAqB,OAAA,CAAQ,MAAA;EAjClB;;;EAsCX,GAAA;EAtCiD;;;EA2CjD,OAAA;EAjCO;;;EAsCP,cAAA;AAAA,IACE,mBAAA,CAAoB,WAAA,CAAY,MAAA"}
package/hooks.d.mts ADDED
@@ -0,0 +1,70 @@
1
+ import { Realtime } from "./types.mjs";
2
+
3
+ //#region src/hooks.d.ts
4
+ declare enum InngestSubscriptionState {
5
+ Closed = "closed",
6
+ Error = "error",
7
+ RefreshingToken = "refresh_token",
8
+ Connecting = "connecting",
9
+ Active = "active",
10
+ Closing = "closing"
11
+ }
12
+ /**
13
+ * Inngest subscription state and data
14
+ */
15
+ interface InngestSubscription<TToken extends Realtime.Subscribe.Token> {
16
+ /**
17
+ * All received messages
18
+ */
19
+ data: Realtime.Subscribe.Token.InferMessage<TToken>[];
20
+ /**
21
+ * Most recent message
22
+ */
23
+ latestData: Realtime.Subscribe.Token.InferMessage<TToken> | null;
24
+ /**
25
+ * Messages received since last render
26
+ */
27
+ freshData: Realtime.Subscribe.Token.InferMessage<TToken>[];
28
+ /**
29
+ * Connection or subscription error
30
+ */
31
+ error: Error | null;
32
+ /**
33
+ * Current subscription state
34
+ */
35
+ state: InngestSubscriptionState;
36
+ }
37
+ /**
38
+ * React hook for subscribing to Inngest realtime channels
39
+ */
40
+ declare function useInngestSubscription<const TToken extends Realtime.Subscribe.Token | null | undefined>({
41
+ token: tokenInput,
42
+ refreshToken,
43
+ key,
44
+ enabled,
45
+ bufferInterval
46
+ }: {
47
+ /**
48
+ * Subscription token
49
+ */
50
+ token?: TToken;
51
+ /**
52
+ * Function to refresh token when needed
53
+ */
54
+ refreshToken?: () => Promise<TToken>;
55
+ /**
56
+ * Unique key to force reconnection
57
+ */
58
+ key?: string;
59
+ /**
60
+ * Whether subscription is enabled
61
+ */
62
+ enabled?: boolean;
63
+ /**
64
+ * Interval in ms to buffer messages (0 = no buffering)
65
+ */
66
+ bufferInterval?: number;
67
+ }): InngestSubscription<NonNullable<TToken>>;
68
+ //#endregion
69
+ export { InngestSubscription, InngestSubscriptionState, useInngestSubscription };
70
+ //# sourceMappingURL=hooks.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.mts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;aAIY,wBAAA;EACV,MAAA;EACA,KAAA;EACA,eAAA;EACA,UAAA;EACA,MAAA;EACA,OAAA;AAAA;;;;UAMe,mBAAA,gBAAmC,QAAA,CAAS,SAAA,CAAU,KAAA;EAN9D;;AAMT;EAIE,IAAA,EAAM,QAAA,CAAS,SAAA,CAAU,KAAA,CAAM,YAAA,CAAa,MAAA;EAJV;;;EASlC,UAAA,EAAY,QAAA,CAAS,SAAA,CAAU,KAAA,CAAM,YAAA,CAAa,MAAA;EAAA;;;EAKlD,SAAA,EAAW,QAAA,CAAS,SAAA,CAAU,KAAA,CAAM,YAAA,CAAa,MAAA;EAK1C;;;EAAP,KAAA,EAAO,KAAA;EAnB4B;;;EAwBnC,KAAA,EAAO,wBAAA;AAAA;;;;iBAMO,sBAAA,sBACO,QAAA,CAAS,SAAA,CAAU,KAAA,oBAAA,CAAA;EAExC,KAAA,EAAO,UAAA;EACP,YAAA;EACA,GAAA;EACA,OAAA;EACA;AAAA;EAjC4C;;;EAsC5C,KAAA,GAAQ,MAAA;EAjCuB;;;EAsC/B,YAAA,SAAqB,OAAA,CAAQ,MAAA;EAjClB;;;EAsCX,GAAA;EAtCiD;;;EA2CjD,OAAA;EAjCO;;;EAsCP,cAAA;AAAA,IACE,mBAAA,CAAoB,WAAA,CAAY,MAAA"}
package/hooks.mjs ADDED
@@ -0,0 +1,144 @@
1
+ import { subscribe } from "./subscribe/helpers.mjs";
2
+ import "./subscribe/index.mjs";
3
+ import { useEffect, useRef, useState } from "react";
4
+
5
+ //#region src/hooks.ts
6
+ let InngestSubscriptionState = /* @__PURE__ */ function(InngestSubscriptionState) {
7
+ InngestSubscriptionState["Closed"] = "closed";
8
+ InngestSubscriptionState["Error"] = "error";
9
+ InngestSubscriptionState["RefreshingToken"] = "refresh_token";
10
+ InngestSubscriptionState["Connecting"] = "connecting";
11
+ InngestSubscriptionState["Active"] = "active";
12
+ InngestSubscriptionState["Closing"] = "closing";
13
+ return InngestSubscriptionState;
14
+ }({});
15
+ /**
16
+ * React hook for subscribing to Inngest realtime channels
17
+ */
18
+ function useInngestSubscription({ token: tokenInput, refreshToken, key, enabled = true, bufferInterval = 0 }) {
19
+ const [token, setToken] = useState(tokenInput);
20
+ const [data, setData] = useState([]);
21
+ const [freshData, setFreshData] = useState([]);
22
+ const [error, setError] = useState(null);
23
+ const [state, setState] = useState(InngestSubscriptionState.Closed);
24
+ const subscriptionRef = useRef(null);
25
+ const readerRef = useRef(null);
26
+ const messageBuffer = useRef([]);
27
+ const bufferIntervalRef = useRef(bufferInterval);
28
+ useEffect(() => {
29
+ if (tokenInput) setToken(tokenInput);
30
+ }, [tokenInput]);
31
+ useEffect(() => {
32
+ if (!token && enabled) if (refreshToken) {
33
+ setState(InngestSubscriptionState.RefreshingToken);
34
+ refreshToken().then((newToken) => setToken(newToken)).catch((err) => {
35
+ setError(err);
36
+ setState(InngestSubscriptionState.Error);
37
+ });
38
+ } else {
39
+ setError(/* @__PURE__ */ new Error("No token provided and no refreshToken handler."));
40
+ setState(InngestSubscriptionState.Error);
41
+ }
42
+ }, []);
43
+ useEffect(() => {
44
+ setError(null);
45
+ if (!enabled || !token) return;
46
+ let cancelled = false;
47
+ const start = async () => {
48
+ try {
49
+ setState(InngestSubscriptionState.Connecting);
50
+ const stream = await subscribe({ ...token });
51
+ if (cancelled) return;
52
+ subscriptionRef.current = stream;
53
+ setState(InngestSubscriptionState.Active);
54
+ const reader = stream.getReader();
55
+ readerRef.current = reader;
56
+ try {
57
+ while (!cancelled) {
58
+ const { done, value } = await reader.read();
59
+ if (done || cancelled) break;
60
+ if (bufferIntervalRef.current === 0) {
61
+ setFreshData([value]);
62
+ setData((prev) => [...prev, value]);
63
+ } else messageBuffer.current.push(value);
64
+ }
65
+ } finally {
66
+ try {
67
+ reader.releaseLock();
68
+ } catch {}
69
+ readerRef.current = null;
70
+ }
71
+ if (!cancelled) {
72
+ setState(InngestSubscriptionState.Closed);
73
+ if (enabled) start();
74
+ }
75
+ } catch (err) {
76
+ if (cancelled) return;
77
+ if (refreshToken) {
78
+ setState(InngestSubscriptionState.RefreshingToken);
79
+ refreshToken().then((newToken) => setToken(newToken)).catch((e) => {
80
+ setError(e);
81
+ setState(InngestSubscriptionState.Error);
82
+ });
83
+ } else {
84
+ setError(err);
85
+ setState(InngestSubscriptionState.Error);
86
+ }
87
+ }
88
+ };
89
+ start();
90
+ return () => {
91
+ cancelled = true;
92
+ const cleanup = async () => {
93
+ const readerToRemove = readerRef.current;
94
+ const subToRemove = subscriptionRef.current;
95
+ readerRef.current = null;
96
+ subscriptionRef.current = null;
97
+ try {
98
+ await readerToRemove?.cancel();
99
+ } catch {}
100
+ try {
101
+ readerToRemove?.releaseLock();
102
+ } catch {}
103
+ try {
104
+ await subToRemove?.cancel();
105
+ } catch {}
106
+ };
107
+ cleanup().catch((err) => {
108
+ console.error("Error cleaning up Inngest subscription", err);
109
+ }).finally(() => {
110
+ setState(InngestSubscriptionState.Closed);
111
+ });
112
+ };
113
+ }, [
114
+ token,
115
+ enabled,
116
+ key
117
+ ]);
118
+ useEffect(() => {
119
+ bufferIntervalRef.current = bufferInterval;
120
+ let interval = null;
121
+ if (bufferInterval > 0) interval = setInterval(() => {
122
+ if (messageBuffer.current.length > 0) {
123
+ const buffered = [...messageBuffer.current];
124
+ messageBuffer.current = [];
125
+ setFreshData(buffered);
126
+ setData((prev) => [...prev, ...buffered]);
127
+ }
128
+ }, bufferInterval);
129
+ return () => {
130
+ if (interval) clearInterval(interval);
131
+ };
132
+ }, [bufferInterval]);
133
+ return {
134
+ data,
135
+ latestData: data[data.length - 1] ?? null,
136
+ freshData,
137
+ error,
138
+ state
139
+ };
140
+ }
141
+
142
+ //#endregion
143
+ export { InngestSubscriptionState, useInngestSubscription };
144
+ //# sourceMappingURL=hooks.mjs.map
package/hooks.mjs.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.mjs","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\r\nimport { subscribe } from \"./subscribe\";\r\nimport { type Realtime } from \"./types\";\r\n\r\nexport enum InngestSubscriptionState {\r\n Closed = \"closed\",\r\n Error = \"error\",\r\n RefreshingToken = \"refresh_token\",\r\n Connecting = \"connecting\",\r\n Active = \"active\",\r\n Closing = \"closing\",\r\n}\r\n\r\n/**\r\n * Inngest subscription state and data\r\n */\r\nexport interface InngestSubscription<TToken extends Realtime.Subscribe.Token> {\r\n /**\r\n * All received messages\r\n */\r\n data: Realtime.Subscribe.Token.InferMessage<TToken>[];\r\n\r\n /**\r\n * Most recent message\r\n */\r\n latestData: Realtime.Subscribe.Token.InferMessage<TToken> | null;\r\n\r\n /**\r\n * Messages received since last render\r\n */\r\n freshData: Realtime.Subscribe.Token.InferMessage<TToken>[];\r\n\r\n /**\r\n * Connection or subscription error\r\n */\r\n error: Error | null;\r\n\r\n /**\r\n * Current subscription state\r\n */\r\n state: InngestSubscriptionState;\r\n}\r\n\r\n/**\r\n * React hook for subscribing to Inngest realtime channels\r\n */\r\nexport function useInngestSubscription<\r\n const TToken extends Realtime.Subscribe.Token | null | undefined,\r\n>({\r\n token: tokenInput,\r\n refreshToken,\r\n key,\r\n enabled = true,\r\n bufferInterval = 0,\r\n}: {\r\n /**\r\n * Subscription token\r\n */\r\n token?: TToken;\r\n\r\n /**\r\n * Function to refresh token when needed\r\n */\r\n refreshToken?: () => Promise<TToken>;\r\n\r\n /**\r\n * Unique key to force reconnection\r\n */\r\n key?: string;\r\n\r\n /**\r\n * Whether subscription is enabled\r\n */\r\n enabled?: boolean;\r\n\r\n /**\r\n * Interval in ms to buffer messages (0 = no buffering)\r\n */\r\n bufferInterval?: number;\r\n}): InngestSubscription<NonNullable<TToken>> {\r\n const [token, setToken] = useState<TToken | null | undefined>(tokenInput);\r\n const [data, setData] = useState<Realtime.Message[]>([]);\r\n const [freshData, setFreshData] = useState<Realtime.Message[]>([]);\r\n const [error, setError] = useState<Error | null>(null);\r\n const [state, setState] = useState<InngestSubscriptionState>(\r\n InngestSubscriptionState.Closed,\r\n );\r\n\r\n const subscriptionRef = useRef<Realtime.Subscribe.StreamSubscription | null>(\r\n null,\r\n );\r\n const readerRef =\r\n useRef<ReadableStreamDefaultReader<Realtime.Message> | null>(null);\r\n const messageBuffer = useRef<Realtime.Message[]>([]);\r\n const bufferIntervalRef = useRef<number>(bufferInterval);\r\n\r\n // Sync token if tokenInput prop changes\r\n useEffect(() => {\r\n if (tokenInput) setToken(tokenInput);\r\n }, [tokenInput]);\r\n\r\n // Token fetch fallback on mount\r\n useEffect(() => {\r\n if (!token && enabled) {\r\n if (refreshToken) {\r\n setState(InngestSubscriptionState.RefreshingToken);\r\n refreshToken()\r\n .then((newToken) => setToken(newToken))\r\n .catch((err) => {\r\n setError(err);\r\n setState(InngestSubscriptionState.Error);\r\n });\r\n } else {\r\n setError(new Error(\"No token provided and no refreshToken handler.\"));\r\n setState(InngestSubscriptionState.Error);\r\n }\r\n }\r\n }, []);\r\n\r\n // Subscription management\r\n useEffect(() => {\r\n setError(null);\r\n if (!enabled || !token) return;\r\n let cancelled = false;\r\n\r\n const start = async () => {\r\n try {\r\n setState(InngestSubscriptionState.Connecting);\r\n const stream = await subscribe({ ...token });\r\n if (cancelled) return;\r\n\r\n subscriptionRef.current = stream;\r\n setState(InngestSubscriptionState.Active);\r\n\r\n // Explicitly get and manage the reader so that we can manually release\r\n // the lock if anything goes wrong or we're done with it.\r\n //\r\n // Especially when this is unmounted.\r\n const reader = stream.getReader();\r\n readerRef.current = reader;\r\n try {\r\n while (!cancelled) {\r\n const { done, value } = await reader.read();\r\n if (done || cancelled) break;\r\n\r\n if (bufferIntervalRef.current === 0) {\r\n setFreshData([value]);\r\n setData((prev) => [...prev, value]);\r\n } else {\r\n messageBuffer.current.push(value);\r\n }\r\n }\r\n } finally {\r\n try {\r\n reader.releaseLock();\r\n } catch {\r\n // Reader might already be released\r\n }\r\n\r\n readerRef.current = null;\r\n }\r\n\r\n // Stream has closed cleanly\r\n if (!cancelled) {\r\n setState(InngestSubscriptionState.Closed);\r\n if (enabled) start();\r\n }\r\n } catch (err) {\r\n if (cancelled) return;\r\n if (refreshToken) {\r\n setState(InngestSubscriptionState.RefreshingToken);\r\n refreshToken()\r\n .then((newToken) => setToken(newToken))\r\n .catch((e) => {\r\n setError(e);\r\n setState(InngestSubscriptionState.Error);\r\n });\r\n } else {\r\n setError(err as Error);\r\n setState(InngestSubscriptionState.Error);\r\n }\r\n }\r\n };\r\n\r\n start();\r\n\r\n return () => {\r\n cancelled = true;\r\n\r\n const cleanup = async () => {\r\n const readerToRemove = readerRef.current;\r\n const subToRemove = subscriptionRef.current;\r\n\r\n readerRef.current = null;\r\n subscriptionRef.current = null;\r\n\r\n try {\r\n await readerToRemove?.cancel();\r\n } catch {\r\n // Reader might already be cancelled\r\n }\r\n\r\n try {\r\n readerToRemove?.releaseLock();\r\n } catch {\r\n // Reader might already be released\r\n }\r\n\r\n try {\r\n await subToRemove?.cancel();\r\n } catch {\r\n // Subscription might already be cancelled\r\n }\r\n };\r\n\r\n cleanup()\r\n .catch((err) => {\r\n console.error(\"Error cleaning up Inngest subscription\", err);\r\n })\r\n .finally(() => {\r\n // Ensure state is always updated even if cleanup fails\r\n setState(InngestSubscriptionState.Closed);\r\n });\r\n };\r\n }, [token, enabled, key]);\r\n\r\n // Buffer flushing\r\n useEffect(() => {\r\n bufferIntervalRef.current = bufferInterval;\r\n let interval: NodeJS.Timeout | null = null;\r\n\r\n if (bufferInterval > 0) {\r\n interval = setInterval(() => {\r\n if (messageBuffer.current.length > 0) {\r\n const buffered = [...messageBuffer.current];\r\n messageBuffer.current = [];\r\n\r\n setFreshData(buffered);\r\n setData((prev) => [...prev, ...buffered]);\r\n }\r\n }, bufferInterval);\r\n }\r\n\r\n return () => {\r\n if (interval) clearInterval(interval);\r\n };\r\n }, [bufferInterval]);\r\n\r\n return {\r\n data,\r\n latestData: data[data.length - 1] ?? null,\r\n freshData,\r\n error,\r\n state,\r\n } as unknown as InngestSubscription<NonNullable<TToken>>;\r\n}\r\n"],"mappings":"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"}
package/index.cjs ADDED
@@ -0,0 +1,19 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_topic = require('./topic.cjs');
3
+ const require_channel = require('./channel.cjs');
4
+ const require_types = require('./types.cjs');
5
+ const require_helpers = require('./subscribe/helpers.cjs');
6
+ require('./subscribe/index.cjs');
7
+
8
+ Object.defineProperty(exports, 'Realtime', {
9
+ enumerable: true,
10
+ get: function () {
11
+ return require_types.Realtime;
12
+ }
13
+ });
14
+ exports.TopicDefinitionImpl = require_topic.TopicDefinitionImpl;
15
+ exports.channel = require_channel.channel;
16
+ exports.getSubscriptionToken = require_helpers.getSubscriptionToken;
17
+ exports.subscribe = require_helpers.subscribe;
18
+ exports.topic = require_topic.topic;
19
+ exports.typeOnlyChannel = require_channel.typeOnlyChannel;
package/index.d.cts ADDED
@@ -0,0 +1,5 @@
1
+ import { Expect, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify } from "./types.cjs";
2
+ import { channel, typeOnlyChannel } from "./channel.cjs";
3
+ import { InngestApp, getSubscriptionToken, subscribe } from "./subscribe/helpers.cjs";
4
+ import { TopicDefinitionImpl, topic } from "./topic.cjs";
5
+ export { Expect, InngestApp, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify, TopicDefinitionImpl, channel, getSubscriptionToken, subscribe, topic, typeOnlyChannel };
package/index.d.mts ADDED
@@ -0,0 +1,6 @@
1
+ import { Expect, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify } from "./types.mjs";
2
+ import { channel, typeOnlyChannel } from "./channel.mjs";
3
+ import { InngestApp, getSubscriptionToken, subscribe } from "./subscribe/helpers.mjs";
4
+ import "./subscribe/index.mjs";
5
+ import { TopicDefinitionImpl, topic } from "./topic.mjs";
6
+ export { Expect, InngestApp, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify, TopicDefinitionImpl, channel, getSubscriptionToken, subscribe, topic, typeOnlyChannel };
package/index.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import { TopicDefinitionImpl, topic } from "./topic.mjs";
2
+ import { channel, typeOnlyChannel } from "./channel.mjs";
3
+ import { Realtime } from "./types.mjs";
4
+ import { getSubscriptionToken, subscribe } from "./subscribe/helpers.mjs";
5
+ import "./subscribe/index.mjs";
6
+
7
+ export { Realtime, TopicDefinitionImpl, channel, getSubscriptionToken, subscribe, topic, typeOnlyChannel };
package/middleware.cjs ADDED
@@ -0,0 +1,41 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_types = require('./types.cjs');
3
+
4
+ //#region src/middleware.ts
5
+ const realtimeMiddleware = () => {
6
+ return {
7
+ name: "publish",
8
+ init({ client }) {
9
+ return { onFunctionRun({ ctx: { runId } }) {
10
+ return { transformInput({ ctx: { step } }) {
11
+ const publish = async (input) => {
12
+ const { topic, channel, data } = await input;
13
+ const publishOpts = {
14
+ topics: [topic],
15
+ channel,
16
+ runId
17
+ };
18
+ const action = async () => {
19
+ const result = await client["api"].publish(publishOpts, data);
20
+ if (!result.ok) throw new Error(`Failed to publish event: ${result.error?.error}`);
21
+ };
22
+ return step.run(`publish:${publishOpts.channel}`, action).then(() => {
23
+ return data;
24
+ });
25
+ };
26
+ return { ctx: { publish } };
27
+ } };
28
+ } };
29
+ }
30
+ };
31
+ };
32
+
33
+ //#endregion
34
+ Object.defineProperty(exports, 'Realtime', {
35
+ enumerable: true,
36
+ get: function () {
37
+ return require_types.Realtime;
38
+ }
39
+ });
40
+ exports.realtimeMiddleware = realtimeMiddleware;
41
+ //# sourceMappingURL=middleware.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.cjs","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import type { Realtime } from \"./types\";\r\n\r\nexport interface InngestMiddleware {\r\n name: string;\r\n init: (config: { client: any }) => {\r\n onFunctionRun: (config: { ctx: { runId: string } }) => {\r\n transformInput: (config: { ctx: { step: any } }) => {\r\n ctx: {\r\n publish: Realtime.PublishFn;\r\n };\r\n };\r\n };\r\n };\r\n}\r\n\r\nexport const realtimeMiddleware = () => {\r\n return {\r\n name: \"publish\",\r\n init({ client }: { client: any }) {\r\n return {\r\n onFunctionRun({ ctx: { runId } }: { ctx: { runId: string } }) {\r\n return {\r\n transformInput({ ctx: { step } }: { ctx: { step: any } }) {\r\n const publish: Realtime.PublishFn = async (input) => {\r\n const { topic, channel, data } = await input;\r\n\r\n const publishOpts = {\r\n topics: [topic],\r\n channel,\r\n runId,\r\n };\r\n\r\n const action = async () => {\r\n const result = await client[\"api\"].publish(publishOpts, data);\r\n\r\n if (!result.ok) {\r\n throw new Error(\r\n `Failed to publish event: ${result.error?.error}`,\r\n );\r\n }\r\n };\r\n\r\n return step\r\n .run(`publish:${publishOpts.channel}`, action)\r\n .then(() => {\r\n return data;\r\n });\r\n };\r\n\r\n return {\r\n ctx: {\r\n /**\r\n * Function to publish messages to realtime channel\r\n */\r\n publish,\r\n },\r\n };\r\n },\r\n };\r\n },\r\n };\r\n },\r\n } as InngestMiddleware;\r\n};\r\n\r\n// Re-export types from here, as this is used as a separate entrypoint now\r\nexport * from \"./types\";\r\n"],"mappings":";;;;AAeA,MAAa,2BAA2B;AACtC,QAAO;EACL,MAAM;EACN,KAAK,EAAE,UAA2B;AAChC,UAAO,EACL,cAAc,EAAE,KAAK,EAAE,WAAuC;AAC5D,WAAO,EACL,eAAe,EAAE,KAAK,EAAE,UAAkC;KACxD,MAAM,UAA8B,OAAO,UAAU;MACnD,MAAM,EAAE,OAAO,SAAS,SAAS,MAAM;MAEvC,MAAM,cAAc;OAClB,QAAQ,CAAC,MAAM;OACf;OACA;OACD;MAED,MAAM,SAAS,YAAY;OACzB,MAAM,SAAS,MAAM,OAAO,OAAO,QAAQ,aAAa,KAAK;AAE7D,WAAI,CAAC,OAAO,GACV,OAAM,IAAI,MACR,4BAA4B,OAAO,OAAO,QAC3C;;AAIL,aAAO,KACJ,IAAI,WAAW,YAAY,WAAW,OAAO,CAC7C,WAAW;AACV,cAAO;QACP;;AAGN,YAAO,EACL,KAAK,EAIH,SACD,EACF;OAEJ;MAEJ;;EAEJ"}
@@ -0,0 +1,29 @@
1
+ import { Expect, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify } from "./types.cjs";
2
+
3
+ //#region src/middleware.d.ts
4
+ interface InngestMiddleware {
5
+ name: string;
6
+ init: (config: {
7
+ client: any;
8
+ }) => {
9
+ onFunctionRun: (config: {
10
+ ctx: {
11
+ runId: string;
12
+ };
13
+ }) => {
14
+ transformInput: (config: {
15
+ ctx: {
16
+ step: any;
17
+ };
18
+ }) => {
19
+ ctx: {
20
+ publish: Realtime.PublishFn;
21
+ };
22
+ };
23
+ };
24
+ };
25
+ }
26
+ declare const realtimeMiddleware: () => InngestMiddleware;
27
+ //#endregion
28
+ export { Expect, InngestMiddleware, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify, realtimeMiddleware };
29
+ //# sourceMappingURL=middleware.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.cts","names":[],"sources":["../src/middleware.ts"],"mappings":";;;UAEiB,iBAAA;EACf,IAAA;EACA,IAAA,GAAO,MAAA;IAAU,MAAA;EAAA;IACf,aAAA,GAAgB,MAAA;MAAU,GAAA;QAAO,KAAA;MAAA;IAAA;MAC/B,cAAA,GAAiB,MAAA;QAAU,GAAA;UAAO,IAAA;QAAA;MAAA;QAChC,GAAA;UACE,OAAA,EAAS,QAAA,CAAS,SAAA;QAAA;MAAA;IAAA;EAAA;AAAA;AAAA,cAOf,kBAAA,QA+CN,iBAAA"}
@@ -0,0 +1,29 @@
1
+ import { Expect, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify } from "./types.mjs";
2
+
3
+ //#region src/middleware.d.ts
4
+ interface InngestMiddleware {
5
+ name: string;
6
+ init: (config: {
7
+ client: any;
8
+ }) => {
9
+ onFunctionRun: (config: {
10
+ ctx: {
11
+ runId: string;
12
+ };
13
+ }) => {
14
+ transformInput: (config: {
15
+ ctx: {
16
+ step: any;
17
+ };
18
+ }) => {
19
+ ctx: {
20
+ publish: Realtime.PublishFn;
21
+ };
22
+ };
23
+ };
24
+ };
25
+ }
26
+ declare const realtimeMiddleware: () => InngestMiddleware;
27
+ //#endregion
28
+ export { Expect, InngestMiddleware, IsEqual, IsLiteral, IsStringLiteral, MaybePromise, Realtime, Simplify, realtimeMiddleware };
29
+ //# sourceMappingURL=middleware.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.mts","names":[],"sources":["../src/middleware.ts"],"mappings":";;;UAEiB,iBAAA;EACf,IAAA;EACA,IAAA,GAAO,MAAA;IAAU,MAAA;EAAA;IACf,aAAA,GAAgB,MAAA;MAAU,GAAA;QAAO,KAAA;MAAA;IAAA;MAC/B,cAAA,GAAiB,MAAA;QAAU,GAAA;UAAO,IAAA;QAAA;MAAA;QAChC,GAAA;UACE,OAAA,EAAS,QAAA,CAAS,SAAA;QAAA;MAAA;IAAA;EAAA;AAAA;AAAA,cAOf,kBAAA,QA+CN,iBAAA"}