@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
@@ -1,153 +0,0 @@
1
- import { getEnvVar } from "../env";
2
- import type { Realtime } from "../types";
3
- import { TokenSubscription } from "./TokenSubscription";
4
-
5
- export interface BunworksApp {
6
- apiBaseUrl?: string;
7
- api?: {
8
- signingKey?: string;
9
- signingKeyFallback?: string;
10
- getSubscriptionToken?: (channelId: string, topics: string[]) => Promise<string>;
11
- };
12
- }
13
-
14
- /**
15
- * Подписка на realtime канал
16
- */
17
- export const subscribe = async <
18
- const InputChannel extends Realtime.Channel | string,
19
- const InputTopics extends (keyof Realtime.Channel.InferTopics<
20
- Realtime.Channel.AsChannel<InputChannel>
21
- > &
22
- string)[],
23
- const TToken extends Realtime.Subscribe.Token<
24
- Realtime.Channel.AsChannel<InputChannel>,
25
- InputTopics
26
- >,
27
- const TOutput extends Realtime.Subscribe.StreamSubscription<TToken>,
28
- >(
29
- /**
30
- * Токен подписки с настройками
31
- */
32
- token: {
33
- /**
34
- * Экземпляр приложения Bunworks
35
- */
36
- app?: BunworksApp;
37
-
38
- /**
39
- * ID канала или объект канала
40
- */
41
- channel: Realtime.Subscribe.InferChannelInput<InputChannel>;
42
-
43
- /**
44
- * Список топиков для подписки
45
- */
46
- topics: InputTopics;
47
- },
48
-
49
- /**
50
- * Callback для обработки сообщений
51
- */
52
- callback?: Realtime.Subscribe.Callback<TToken>,
53
- ): Promise<TOutput> => {
54
- const app = token.app;
55
- const api = app?.api;
56
-
57
- // Allow users to specify public env vars for the target URLs, but do not
58
- // allow this for signing keys, as they should never be on a client.
59
- const maybeApiBaseUrl =
60
- app?.apiBaseUrl ||
61
- getEnvVar("BUNWORKS_BASE_URL") ||
62
- getEnvVar("BUNWORKS_API_BASE_URL");
63
-
64
- const maybeSigningKey =
65
- api?.signingKey || getEnvVar("BUNWORKS_SIGNING_KEY");
66
-
67
- const maybeSigningKeyFallback =
68
- api?.signingKeyFallback || getEnvVar("BUNWORKS_SIGNING_KEY_FALLBACK");
69
-
70
- const subscription = new TokenSubscription(
71
- token as Realtime.Subscribe.Token,
72
- maybeApiBaseUrl,
73
- maybeSigningKey,
74
- maybeSigningKeyFallback,
75
- );
76
-
77
- const retStream = subscription.getJsonStream();
78
- const callbackStream = subscription.getJsonStream();
79
-
80
- await subscription.connect();
81
-
82
- const extras = {
83
- getJsonStream: () => subscription.getJsonStream(),
84
- getEncodedStream: () => subscription.getEncodedStream(),
85
- };
86
-
87
- if (callback) {
88
- subscription.useCallback(callback, callbackStream);
89
- } else {
90
- callbackStream.cancel("Not needed");
91
- }
92
-
93
- return Object.assign(retStream, extras) as unknown as TOutput;
94
- };
95
-
96
- /**
97
- * Получение токена подписки
98
- */
99
- export const getSubscriptionToken = async <
100
- const InputChannel extends Realtime.Channel | string,
101
- const InputTopics extends (keyof Realtime.Channel.InferTopics<
102
- Realtime.Channel.AsChannel<InputChannel>
103
- > &
104
- string)[],
105
- const TToken extends Realtime.Subscribe.Token<
106
- Realtime.Channel.AsChannel<InputChannel>,
107
- InputTopics
108
- >,
109
- >(
110
- /**
111
- * Экземпляр приложения Bunworks
112
- */
113
- app: BunworksApp,
114
-
115
- /**
116
- * Параметры подписки
117
- */
118
- args: {
119
- /**
120
- * ID канала или объект канала
121
- */
122
- channel: Realtime.Subscribe.InferChannelInput<InputChannel>;
123
-
124
- /**
125
- * Список топиков
126
- */
127
- topics: InputTopics;
128
- },
129
- ): Promise<TToken> => {
130
- const channelId =
131
- typeof args.channel === "string" ? args.channel : args.channel.name;
132
-
133
- if (!channelId) {
134
- throw new Error("Требуется ID канала для создания токена подписки");
135
- }
136
-
137
- const key = await app.api?.getSubscriptionToken?.(
138
- channelId,
139
- args.topics,
140
- );
141
-
142
- if (!key) {
143
- throw new Error("Не удалось получить токен подписки");
144
- }
145
-
146
- const token = {
147
- channel: channelId,
148
- topics: args.topics,
149
- key,
150
- } as TToken;
151
-
152
- return token;
153
- };
@@ -1 +0,0 @@
1
- export * from "./helpers";
package/src/topic.ts DELETED
@@ -1,51 +0,0 @@
1
- import { type StandardSchemaV1 } from "@standard-schema/spec";
2
- import { type Realtime } from "./types.js";
3
-
4
- /**
5
- * TODO
6
- */
7
- export const topic: Realtime.Topic.Builder = (
8
- /**
9
- * TODO
10
- */
11
- id,
12
- ) => {
13
- return new TopicDefinitionImpl(id);
14
- };
15
-
16
- export class TopicDefinitionImpl<
17
- TTopicId extends string = string,
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
- TPublish = any,
20
- TSubscribe = TPublish,
21
- > implements Realtime.Topic.Definition<TTopicId, TPublish, TSubscribe>
22
- {
23
- public name: TTopicId;
24
- #schema?: StandardSchemaV1;
25
-
26
- constructor(name: TTopicId, schema?: StandardSchemaV1) {
27
- this.name = name;
28
- this.#schema = schema;
29
- }
30
-
31
- public type<
32
- const UPublish,
33
- const USubscribe = UPublish,
34
- >(): Realtime.Topic.Definition<TTopicId, UPublish, USubscribe> {
35
- return this as Realtime.Topic.Definition<TTopicId, UPublish, USubscribe>;
36
- }
37
-
38
- public schema<const TSchema extends StandardSchemaV1>(
39
- schema: TSchema,
40
- ): Realtime.Topic.Definition<
41
- TTopicId,
42
- StandardSchemaV1.InferInput<TSchema>,
43
- StandardSchemaV1.InferOutput<TSchema>
44
- > {
45
- return new TopicDefinitionImpl(this.name, schema);
46
- }
47
-
48
- public getSchema(): StandardSchemaV1 | undefined {
49
- return this.#schema;
50
- }
51
- }
package/src/types.ts DELETED
@@ -1,499 +0,0 @@
1
- import { type StandardSchemaV1 } from "@standard-schema/spec";
2
- import { z } from "zod";
3
-
4
- export namespace Realtime {
5
- export type PublishFn = <
6
- TMessage extends MaybePromise<Realtime.Message.Input>,
7
- >(
8
- message: TMessage,
9
- ) => Promise<Awaited<TMessage>["data"]>;
10
-
11
- export type Token<
12
- TChannel extends Channel | Channel.Definition,
13
- TTopics extends (keyof Channel.InferTopics<
14
- Channel.Definition.AsChannel<TChannel>
15
- > &
16
- string)[] = (keyof Channel.InferTopics<
17
- Channel.Definition.AsChannel<TChannel>
18
- > &
19
- string)[],
20
- > = TChannel extends Channel.Definition
21
- ? Subscribe.Token<Channel.Definition.AsChannel<TChannel>, TTopics>
22
- : TChannel extends Channel
23
- ? Subscribe.Token<TChannel, TTopics>
24
- : never;
25
-
26
- export namespace Subscribe {
27
- export type InferChannelInput<T> = T extends Realtime.Channel.Definition
28
- ? Realtime.Channel.Definition.InferId<T>
29
- : T;
30
-
31
- export type StreamSubscription<
32
- TSubscribeToken extends Token = Token,
33
- TData extends Simplify<Token.InferMessage<TSubscribeToken>> = Simplify<
34
- Token.InferMessage<TSubscribeToken>
35
- >,
36
- > = ReadableStream<TData> & {
37
- /**
38
- * Get a new readable stream from the subscription that delivers JSON chunks.
39
- *
40
- * The stream starts when this function is called and will not contain any
41
- * messages that were sent before this function was called.
42
- */
43
- getJsonStream(): ReadableStream<TData>;
44
-
45
- /**
46
- * Get a new readable stream from the subscription that delivers
47
- * SSE-compatible chunks, which are compatible with the `EventSource` API
48
- * and generally used for streaming data from a server to the browser.
49
- *
50
- * The stream starts when this function is called and will not contain any
51
- * messages that were sent before this function was called.
52
- */
53
- getEncodedStream(): ReadableStream<Uint8Array>;
54
- };
55
-
56
- export type Callback<
57
- TSubscribeToken extends Subscribe.Token = Subscribe.Token,
58
- > = (message: Token.InferMessage<TSubscribeToken>) => void;
59
-
60
- export interface Token<
61
- TChannel extends Channel | Channel.Definition = Channel,
62
- TTopics extends
63
- (keyof Channel.InferTopics<TChannel>)[] = (keyof Channel.InferTopics<TChannel>)[],
64
- > {
65
- // key used to auth - could be undefined as then we can do a cold subscribe
66
- key?: string | undefined;
67
- channel: Realtime.Channel.Definition.AsChannel<TChannel>;
68
- topics: TTopics;
69
- }
70
-
71
- export namespace Token {
72
- export type InferChannel<TToken extends Token> = TToken extends Token<
73
- infer IChannel,
74
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
- any
76
- >
77
- ? IChannel
78
- : Channel;
79
-
80
- export type InferTopicData<
81
- TToken extends Token,
82
- TChannelTopics extends Record<
83
- string,
84
- Topic.Definition
85
- > = Channel.InferTopics<Token.InferChannel<TToken>>,
86
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
- > = TToken extends Token<any, infer ITopics>
88
- ? { [K in ITopics[number]]: TChannelTopics[K] }
89
- : never;
90
-
91
- export type InferMessage<TToken extends Token> = Simplify<
92
- Realtime.Message<
93
- Channel.InferId<Token.InferChannel<TToken>>,
94
- Token.InferTopicData<TToken>
95
- >
96
- >;
97
- }
98
- }
99
-
100
- // We need to use a `Message` type so that we can appropriately type incoming
101
- // and outgoing messages with generics, but we also need to validate these at
102
- // runtime.
103
- //
104
- // Ideally in the future we use protobuf for this, but for now we use Zod.
105
- // This type is used to assert that the Zod schema matches the generic type.
106
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
107
- type _AssertMessageSchemaMatchesGeneric = Expect<
108
- IsEqual<z.output<typeof messageSchema>, Message.Raw>
109
- >;
110
-
111
- export const messageSchema = z
112
- .object({
113
- channel: z.string().optional(),
114
- topic: z.string().optional(),
115
- data: z.any(),
116
- run_id: z.string().optional(),
117
- fn_id: z.string().optional(),
118
- created_at: z
119
- .string()
120
- .optional()
121
- .transform((v) => (v ? new Date(v) : undefined)),
122
- env_id: z.string().optional(),
123
- stream_id: z.string().optional(),
124
- kind: z.enum([
125
- "step",
126
- "run",
127
- "data",
128
- "ping",
129
- "pong",
130
- "closing",
131
- "event",
132
- "sub",
133
- "unsub",
134
- "datastream-start",
135
- "datastream-end",
136
- "chunk",
137
- ]),
138
- })
139
- .transform(({ data, ...rest }) => {
140
- return {
141
- ...rest,
142
- data: data ?? undefined,
143
- };
144
- });
145
-
146
- // Subscribe (output) msg
147
- export type Message<
148
- TChannelId extends string = string,
149
- TTopics extends Record<string, Realtime.Topic.Definition> = Record<
150
- string,
151
- Realtime.Topic.Definition
152
- >,
153
- > = {
154
- [K in keyof TTopics]:
155
- | {
156
- topic: K;
157
- channel: TChannelId;
158
- data: Realtime.Topic.InferSubscribe<TTopics[K]>;
159
- runId?: string;
160
- fnId?: string;
161
- createdAt: Date;
162
- envId?: string;
163
- kind: "data";
164
- }
165
- | {
166
- topic: K;
167
- channel: TChannelId;
168
- data: Realtime.Topic.InferSubscribe<TTopics[K]>;
169
- runId?: string;
170
- fnId?: string;
171
- kind: "datastream-start" | "datastream-end" | "chunk";
172
- streamId: string;
173
- stream: ReadableStream<Realtime.Topic.InferSubscribe<TTopics[K]>>;
174
- };
175
- }[keyof TTopics];
176
-
177
- export namespace Message {
178
- // Publish (input) msg
179
- export type Input<
180
- TChannelId extends string = string,
181
- TTopicId extends string = string,
182
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
- TData = any,
184
- > = {
185
- channel: TChannelId;
186
- topic: TTopicId;
187
- data: TData;
188
- };
189
-
190
- export type Raw<
191
- TChannelId extends string = string,
192
- TTopics extends Record<string, Realtime.Topic.Definition> = Record<
193
- string,
194
- Realtime.Topic.Definition
195
- >,
196
- > = {
197
- [K in keyof TTopics]: {
198
- topic?: K;
199
- stream_id?: string;
200
- data: Realtime.Topic.InferSubscribe<TTopics[K]>;
201
- channel?: TChannelId;
202
- run_id?: string;
203
- fn_id?: string;
204
- created_at?: Date;
205
- env_id?: string;
206
- kind:
207
- | "step" // step data
208
- | "run" // run results
209
- | "data" // misc stream data from `ctx.publish()`
210
- | "datastream-start"
211
- | "datastream-end"
212
- | "ping" // keepalive server -> client
213
- | "pong" // keepalive client -> server
214
- | "closing" // server is closing connection, client should reconnect
215
- | "event" // event sent to inngest
216
- | "sub"
217
- | "unsub"
218
- | "chunk";
219
- };
220
- }[keyof TTopics];
221
- }
222
-
223
- export type Channel<
224
- TChannelId extends string = string,
225
- TTopics extends Record<string, Realtime.Topic.Definition> = Record<
226
- string,
227
- Realtime.Topic.Definition
228
- >,
229
- > = {
230
- [K in
231
- | IsLiteral<keyof TTopics, keyof TTopics, never>
232
- | "name"
233
- | "topics"]: K extends "name"
234
- ? string
235
- : K extends "topics"
236
- ? TTopics
237
- : Realtime.Topic<TChannelId, TTopics[K]>;
238
- };
239
-
240
- export namespace Channel {
241
- export type Like = {
242
- channel: string;
243
- topics: string[];
244
- };
245
-
246
- export type InferId<TChannel extends Channel> = TChannel extends Channel<
247
- infer IId,
248
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
249
- any
250
- >
251
- ? IId
252
- : string;
253
-
254
- export type AsChannel<T extends Channel | string> = T extends Channel
255
- ? T
256
- : T extends string
257
- ? Realtime.Channel<T>
258
- : never;
259
-
260
- export type InferTopics<
261
- TChannel extends Channel | Channel.Definition,
262
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
263
- > = TChannel extends Channel.Definition<any, infer ITopics>
264
- ? ITopics
265
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
266
- TChannel extends Channel<any, infer ITopics>
267
- ? ITopics
268
- : Record<string, Realtime.Topic.Definition>;
269
-
270
- export interface Definition<
271
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
272
- TChannelBuilderFn extends BuilderFn = (...args: any[]) => string,
273
- TTopics extends Record<string, Topic.Definition> = Record<
274
- string,
275
- Topic.Definition
276
- >,
277
- > {
278
- (
279
- ...args: Parameters<TChannelBuilderFn>
280
- ): Channel<ReturnType<TChannelBuilderFn>, TTopics>;
281
-
282
- addTopic<UTopic extends Topic.Definition>(
283
- topic: UTopic,
284
- ): Definition<TChannelBuilderFn, AddTopic<TTopics, UTopic>>;
285
-
286
- topics: TTopics;
287
- }
288
-
289
- export namespace Definition {
290
- export type InferId<TChannel extends Definition> =
291
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
292
- TChannel extends Definition<infer IBuilder, any>
293
- ? ReturnType<IBuilder>
294
- : string;
295
-
296
- export type InferTopics<TChannel extends Definition> =
297
- TChannel extends Definition<
298
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
299
- any,
300
- infer ITopics
301
- >
302
- ? ITopics
303
- : Record<string, Topic.Definition>;
304
-
305
- export type AsChannel<T extends Definition | Channel> =
306
- T extends Definition
307
- ? Channel<InferId<T>, InferTopics<T>>
308
- : T extends Channel
309
- ? T
310
- : never;
311
- }
312
-
313
- export type AddTopic<
314
- TCurr extends Record<string, Topic.Definition>,
315
- TInc extends Topic.Definition,
316
- TIncWrapped extends Record<TInc["name"], TInc> = Record<
317
- TInc["name"],
318
- TInc
319
- >,
320
- > = IsStringLiteral<keyof TCurr & string> extends true
321
- ? Simplify<Omit<TCurr, TInc["name"]> & TIncWrapped>
322
- : TIncWrapped;
323
-
324
- export type BuilderFn<TChannelId extends string = string> = (
325
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
326
- ...args: any[]
327
- ) => TChannelId;
328
-
329
- export type Builder = <
330
- const TChannelId extends string,
331
- const TIdInput extends TChannelId | BuilderFn<TChannelId>,
332
- >(
333
- id: TIdInput,
334
- ) => TIdInput extends TChannelId
335
- ? Channel.Definition<() => TIdInput>
336
- : TIdInput extends BuilderFn<TChannelId>
337
- ? Channel.Definition<TIdInput>
338
- : never;
339
- }
340
-
341
- export type Topic<
342
- TChannelId extends string = string,
343
- TTopic extends Topic.Definition = Topic.Definition,
344
- > = (
345
- data: Topic.InferPublish<TTopic>,
346
- ) => Promise<
347
- Realtime.Message.Input<
348
- TChannelId,
349
- Topic.InferId<TTopic>,
350
- Topic.InferPublish<TTopic>
351
- >
352
- >;
353
-
354
- export namespace Topic {
355
- export type Like = {
356
- name: string;
357
- };
358
-
359
- export interface Definition<
360
- TTopicId extends string = string,
361
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
362
- TPublish = any,
363
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
364
- _TSubscribe = TPublish,
365
- > {
366
- name: TTopicId;
367
-
368
- // Deliberately doesn't include `USubscribe` typing, as there's no schema
369
- // to perform transformations.
370
- type<const UPublish>(): Definition<TTopicId, UPublish>;
371
-
372
- schema<const TSchema extends StandardSchemaV1>(
373
- schema: TSchema,
374
- ): Definition<
375
- TTopicId,
376
- StandardSchemaV1.InferInput<TSchema>,
377
- StandardSchemaV1.InferOutput<TSchema>
378
- >;
379
-
380
- getSchema(): StandardSchemaV1 | undefined;
381
- }
382
-
383
- export type InferId<TTopic extends Topic.Definition> =
384
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
385
- TTopic extends Topic.Definition<infer IId, any, any> ? IId : string;
386
-
387
- export type InferPublish<TTopic extends Topic.Definition> =
388
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
389
- TTopic extends Topic.Definition<any, infer IPublish, any>
390
- ? IPublish
391
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
392
- any;
393
-
394
- export type InferSubscribe<TTopic extends Topic.Definition> =
395
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
396
- TTopic extends Topic.Definition<any, any, infer ISubscribe>
397
- ? ISubscribe
398
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
399
- any;
400
-
401
- export type Builder = <const TTopicId extends string>(
402
- id: TTopicId,
403
- ) => Topic.Definition<TTopicId>;
404
- }
405
- }
406
-
407
- /**
408
- * Expects that a value resolves to `true`, useful for asserting type checks.
409
- */
410
- export type Expect<T extends true> = T;
411
-
412
- /**
413
- Returns a boolean for whether the two given types are equal.
414
-
415
- {@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650}
416
- {@link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796}
417
-
418
- Use-cases:
419
- - If you want to make a conditional branch based on the result of a comparison of two types.
420
-
421
- @example
422
- ```
423
- import type {IsEqual} from 'type-fest';
424
-
425
- // This type returns a boolean for whether the given array includes the given item.
426
- // `IsEqual` is used to compare the given array at position 0 and the given item and then return true if they are equal.
427
- type Includes<Value extends readonly any[], Item> =
428
- Value extends readonly [Value[0], ...infer rest]
429
- ? IsEqual<Value[0], Item> extends true
430
- ? true
431
- : Includes<rest, Item>
432
- : false;
433
- ```
434
- */
435
- export type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends <
436
- G,
437
- >() => G extends B ? 1 : 2
438
- ? true
439
- : false;
440
-
441
- /**
442
- * Given a type `T`, return `Then` if `T` is a string, number, or symbol
443
- * literal, else `Else`.
444
- *
445
- * `Then` defaults to `true` and `Else` defaults to `false`.
446
- *
447
- * Useful for determining if an object is a generic type or has known keys.
448
- *
449
- * @example
450
- * ```ts
451
- * type IsLiteralType = IsLiteral<"foo">; // true
452
- * type IsLiteralType = IsLiteral<string>; // false
453
- *
454
- * type IsLiteralType = IsLiteral<1>; // true
455
- * type IsLiteralType = IsLiteral<number>; // false
456
- *
457
- * type IsLiteralType = IsLiteral<symbol>; // true
458
- * type IsLiteralType = IsLiteral<typeof Symbol.iterator>; // false
459
- *
460
- * type T0 = { foo: string };
461
- * type HasAllKnownKeys = IsLiteral<keyof T0>; // true
462
- *
463
- * type T1 = { [x: string]: any; foo: boolean };
464
- * type HasAllKnownKeys = IsLiteral<keyof T1>; // false
465
- * ```
466
- */
467
- export type IsLiteral<T, Then = true, Else = false> = string extends T
468
- ? Else
469
- : number extends T
470
- ? Else
471
- : symbol extends T
472
- ? Else
473
- : Then;
474
-
475
- /**
476
- * Returns `true` if the given generic `T` is a string literal, e.g. `"foo"`, or
477
- * `false` if it is a string type, e.g. `string`.
478
- *
479
- * Useful for checking whether the keys of an object are known or not.
480
- *
481
- * @example
482
- * ```ts
483
- * // false
484
- * type ObjIsGeneric = IsStringLiteral<keyof Record<string, boolean>>;
485
- *
486
- * // true
487
- * type ObjIsKnown = IsStringLiteral<keyof { foo: boolean; }>; // true
488
- * ```
489
- *
490
- * @internal
491
- */
492
- export type IsStringLiteral<T extends string> = string extends T ? false : true;
493
-
494
- /**
495
- * Returns the given generic as either itself or a promise of itself.
496
- */
497
- export type MaybePromise<T> = T | Promise<T>;
498
-
499
- export type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};