spectrum-ts 0.0.1 → 0.1.1
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.
- package/dist/chunk-3TBRO2J7.js +58 -0
- package/dist/chunk-UZ2CXPOD.js +175 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +344 -0
- package/dist/providers/imessage/index.d.ts +82 -0
- package/dist/providers/imessage/index.js +413 -0
- package/dist/providers/terminal/index.d.ts +35 -0
- package/dist/providers/terminal/index.js +61 -0
- package/dist/stream-DGy4geUK.d.ts +8 -0
- package/dist/types-DiKuSemh.d.ts +261 -0
- package/package.json +48 -3
- package/src/index.ts +26 -0
- package/src/platform/define.ts +309 -0
- package/src/platform/types.ts +438 -0
- package/src/providers/imessage/auth.ts +161 -0
- package/src/providers/imessage/index.ts +145 -0
- package/src/providers/imessage/local.ts +55 -0
- package/src/providers/imessage/remote.ts +157 -0
- package/src/providers/imessage/types.ts +31 -0
- package/src/providers/terminal/index.ts +66 -0
- package/src/spectrum.ts +377 -0
- package/src/types/content.ts +85 -0
- package/src/types/message.ts +18 -0
- package/src/types/space.ts +10 -0
- package/src/types/user.ts +4 -0
- package/src/utils/cloud.ts +1 -0
- package/src/utils/stream.ts +71 -0
- package/index.js +0 -1
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { Pipe, Tuples, Fn } from 'hotscript';
|
|
2
|
+
import z__default from 'zod';
|
|
3
|
+
import { NonEmptyString } from 'type-fest';
|
|
4
|
+
|
|
5
|
+
declare const contentSchema: z__default.ZodDiscriminatedUnion<[z__default.ZodObject<{
|
|
6
|
+
type: z__default.ZodLiteral<"plain_text">;
|
|
7
|
+
text: z__default.ZodString;
|
|
8
|
+
}, z__default.core.$strip>, z__default.ZodObject<{
|
|
9
|
+
type: z__default.ZodLiteral<"custom">;
|
|
10
|
+
raw: z__default.ZodJSONSchema;
|
|
11
|
+
}, z__default.core.$strip>, z__default.ZodObject<{
|
|
12
|
+
type: z__default.ZodLiteral<"attachment">;
|
|
13
|
+
data: z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>;
|
|
14
|
+
mimeType: z__default.ZodString;
|
|
15
|
+
name: z__default.ZodString;
|
|
16
|
+
}, z__default.core.$strip>], "type">;
|
|
17
|
+
type Content = z__default.infer<typeof contentSchema>;
|
|
18
|
+
interface ContentBuilder {
|
|
19
|
+
build(): Promise<Content>;
|
|
20
|
+
}
|
|
21
|
+
declare function text<T extends string>(text: NonEmptyString<T>): ContentBuilder;
|
|
22
|
+
declare function custom(raw: z__default.infer<ReturnType<typeof z__default.json>>): ContentBuilder;
|
|
23
|
+
declare function attachment(input: string | Buffer, options?: {
|
|
24
|
+
mimeType?: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
}): ContentBuilder;
|
|
27
|
+
|
|
28
|
+
interface Space<_Def = unknown> {
|
|
29
|
+
readonly __platform: string;
|
|
30
|
+
readonly id: string;
|
|
31
|
+
responding<T>(fn: () => T | Promise<T>): Promise<T>;
|
|
32
|
+
send(...content: [ContentBuilder, ...ContentBuilder[]]): Promise<void>;
|
|
33
|
+
startTyping(): Promise<void>;
|
|
34
|
+
stopTyping(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface User {
|
|
38
|
+
readonly __platform: string;
|
|
39
|
+
readonly id: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface Message<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> {
|
|
43
|
+
content: Content[];
|
|
44
|
+
readonly id: string;
|
|
45
|
+
platform: TPlatform;
|
|
46
|
+
react(reaction: string): Promise<void>;
|
|
47
|
+
reply(...content: [ContentBuilder, ...ContentBuilder[]]): Promise<void>;
|
|
48
|
+
sender: TSender;
|
|
49
|
+
space: TSpace;
|
|
50
|
+
timestamp: Date;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type ResolvedSpace = Pick<Space, "id">;
|
|
54
|
+
type SpaceRef = Pick<Space, "id" | "__platform">;
|
|
55
|
+
type ResolvedUser = Pick<User, "id">;
|
|
56
|
+
type AwaitedReturn<T> = T extends (...args: never[]) => Promise<infer R> ? R : never;
|
|
57
|
+
type SchemaInfer<T> = T extends {
|
|
58
|
+
schema?: infer S extends z__default.ZodType<object>;
|
|
59
|
+
} ? z__default.infer<S> : Record<never, never>;
|
|
60
|
+
type InferSchema<TSchema> = TSchema extends z__default.ZodType<object> ? z__default.infer<TSchema> : Record<never, never>;
|
|
61
|
+
type InferOptionalSchema<TSchema> = TSchema extends z__default.ZodType<object> ? z__default.infer<TSchema> : never;
|
|
62
|
+
type InputSchema<TSchema> = TSchema extends z__default.ZodType<object> ? z__default.input<TSchema> : never;
|
|
63
|
+
type EventProducer<TPayload = unknown, TClient = unknown, TConfig = unknown> = (ctx: {
|
|
64
|
+
client: TClient;
|
|
65
|
+
config: TConfig;
|
|
66
|
+
}) => AsyncIterable<TPayload>;
|
|
67
|
+
type ProviderMessage<TSender extends ResolvedUser = ResolvedUser, TSpace extends ResolvedSpace = ResolvedSpace, TExtra extends object = Record<never, never>> = {
|
|
68
|
+
id: string;
|
|
69
|
+
content: Content[];
|
|
70
|
+
sender: TSender;
|
|
71
|
+
space: TSpace;
|
|
72
|
+
timestamp?: Date;
|
|
73
|
+
} & TExtra;
|
|
74
|
+
type MergeSchema<TSchema extends z__default.ZodType | undefined, TBase extends object> = TSchema extends z__default.ZodType ? string extends keyof z__default.infer<TSchema> ? TBase : Omit<z__default.infer<TSchema>, keyof TBase> & TBase : TBase;
|
|
75
|
+
type SchemaMessage<TUserSchema extends z__default.ZodType | undefined = undefined, TSpaceSchema extends z__default.ZodType | undefined = undefined> = ProviderMessage<MergeSchema<TUserSchema, ResolvedUser>, MergeSchema<TSpaceSchema, ResolvedSpace>>;
|
|
76
|
+
type InferEventPayload<T> = T extends (ctx: never) => AsyncIterable<infer P> ? P : never;
|
|
77
|
+
type ReservedNames = "stop" | "send" | "__internal" | "__providers";
|
|
78
|
+
interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__default.ZodType<object> = z__default.ZodType<object>, _UserSchema extends z__default.ZodType<object> | undefined = undefined, _SpaceSchema extends z__default.ZodType<object> | undefined = undefined, _SpaceParamsSchema extends z__default.ZodType<object> | undefined = undefined, _Client = unknown, _ResolvedUser extends ResolvedUser = ResolvedUser, _ResolvedSpace extends ResolvedSpace = ResolvedSpace, _MessageSchema extends z__default.ZodType<object> | undefined = undefined, _MessageType extends ProviderMessage<_ResolvedUser, _ResolvedSpace, InferSchema<_MessageSchema>> = ProviderMessage<_ResolvedUser, _ResolvedSpace, InferSchema<_MessageSchema>>, _Events extends {
|
|
79
|
+
messages: EventProducer<_MessageType, _Client, z__default.infer<_ConfigSchema>>;
|
|
80
|
+
} = {
|
|
81
|
+
messages: EventProducer<_MessageType, _Client, z__default.infer<_ConfigSchema>>;
|
|
82
|
+
}> {
|
|
83
|
+
actions: {
|
|
84
|
+
send: (_: {
|
|
85
|
+
space: _ResolvedSpace & SpaceRef;
|
|
86
|
+
content: Content[];
|
|
87
|
+
client: _Client;
|
|
88
|
+
config: z__default.infer<_ConfigSchema>;
|
|
89
|
+
}) => Promise<void>;
|
|
90
|
+
startTyping?: (_: {
|
|
91
|
+
space: _ResolvedSpace & SpaceRef;
|
|
92
|
+
client: _Client;
|
|
93
|
+
config: z__default.infer<_ConfigSchema>;
|
|
94
|
+
}) => Promise<void>;
|
|
95
|
+
stopTyping?: (_: {
|
|
96
|
+
space: _ResolvedSpace & SpaceRef;
|
|
97
|
+
client: _Client;
|
|
98
|
+
config: z__default.infer<_ConfigSchema>;
|
|
99
|
+
}) => Promise<void>;
|
|
100
|
+
reactToMessage?: (_: {
|
|
101
|
+
space: _ResolvedSpace & SpaceRef;
|
|
102
|
+
messageId: string;
|
|
103
|
+
reaction: string;
|
|
104
|
+
client: _Client;
|
|
105
|
+
config: z__default.infer<_ConfigSchema>;
|
|
106
|
+
}) => Promise<void>;
|
|
107
|
+
replyToMessage?: (_: {
|
|
108
|
+
space: _ResolvedSpace & SpaceRef;
|
|
109
|
+
messageId: string;
|
|
110
|
+
content: Content[];
|
|
111
|
+
client: _Client;
|
|
112
|
+
config: z__default.infer<_ConfigSchema>;
|
|
113
|
+
}) => Promise<void>;
|
|
114
|
+
};
|
|
115
|
+
config: _ConfigSchema;
|
|
116
|
+
events: _Events;
|
|
117
|
+
lifecycle: {
|
|
118
|
+
createClient: (ctx: {
|
|
119
|
+
config: z__default.infer<_ConfigSchema>;
|
|
120
|
+
projectId: string;
|
|
121
|
+
projectSecret: string;
|
|
122
|
+
}) => Promise<_Client>;
|
|
123
|
+
destroyClient: (ctx: {
|
|
124
|
+
client: _Client;
|
|
125
|
+
}) => Promise<void>;
|
|
126
|
+
};
|
|
127
|
+
message?: {
|
|
128
|
+
schema?: _MessageSchema;
|
|
129
|
+
};
|
|
130
|
+
name: _Name;
|
|
131
|
+
space: {
|
|
132
|
+
schema?: _SpaceSchema;
|
|
133
|
+
params?: _SpaceParamsSchema;
|
|
134
|
+
resolve: (_: {
|
|
135
|
+
input: {
|
|
136
|
+
users: (_ResolvedUser & {
|
|
137
|
+
__platform: _Name;
|
|
138
|
+
})[];
|
|
139
|
+
params?: _SpaceParamsSchema extends z__default.ZodType<object> ? z__default.infer<_SpaceParamsSchema> : undefined;
|
|
140
|
+
};
|
|
141
|
+
client: _Client;
|
|
142
|
+
config: z__default.infer<_ConfigSchema>;
|
|
143
|
+
}) => Promise<_ResolvedSpace>;
|
|
144
|
+
};
|
|
145
|
+
user: {
|
|
146
|
+
schema?: _UserSchema;
|
|
147
|
+
resolve: (_: {
|
|
148
|
+
input: {
|
|
149
|
+
userID: string;
|
|
150
|
+
};
|
|
151
|
+
client: _Client;
|
|
152
|
+
config: z__default.infer<_ConfigSchema>;
|
|
153
|
+
}) => Promise<_ResolvedUser>;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
interface AnyPlatformDef {
|
|
157
|
+
actions: {
|
|
158
|
+
send: (_: any) => Promise<void>;
|
|
159
|
+
startTyping?: (_: any) => Promise<void>;
|
|
160
|
+
stopTyping?: (_: any) => Promise<void>;
|
|
161
|
+
reactToMessage?: (_: any) => Promise<void>;
|
|
162
|
+
replyToMessage?: (_: any) => Promise<void>;
|
|
163
|
+
};
|
|
164
|
+
config: z__default.ZodType<object>;
|
|
165
|
+
events: {
|
|
166
|
+
messages: (ctx: any) => AsyncIterable<any>;
|
|
167
|
+
[key: string]: (ctx: any) => AsyncIterable<any>;
|
|
168
|
+
};
|
|
169
|
+
lifecycle: {
|
|
170
|
+
createClient: (ctx: any) => Promise<any>;
|
|
171
|
+
destroyClient: (ctx: any) => Promise<void>;
|
|
172
|
+
};
|
|
173
|
+
message?: {
|
|
174
|
+
schema?: z__default.ZodType<object>;
|
|
175
|
+
};
|
|
176
|
+
name: string;
|
|
177
|
+
space: {
|
|
178
|
+
schema?: z__default.ZodType<object>;
|
|
179
|
+
params?: z__default.ZodType<object>;
|
|
180
|
+
resolve: (_: any) => Promise<any>;
|
|
181
|
+
};
|
|
182
|
+
user: {
|
|
183
|
+
schema?: z__default.ZodType<object>;
|
|
184
|
+
resolve: (_: any) => Promise<any>;
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
interface PlatformProviderConfig<Def extends AnyPlatformDef = AnyPlatformDef> {
|
|
188
|
+
readonly __def: Def;
|
|
189
|
+
readonly __definition: AnyPlatformDef;
|
|
190
|
+
readonly __name: Def["name"];
|
|
191
|
+
readonly __tag: "PlatformProviderConfig";
|
|
192
|
+
readonly config: unknown;
|
|
193
|
+
}
|
|
194
|
+
interface MatchesPlatformName<Name extends string> extends Fn {
|
|
195
|
+
return: this["arg0"] extends PlatformProviderConfig<infer Def> ? Def["name"] extends Name ? true : false : false;
|
|
196
|
+
}
|
|
197
|
+
interface ExtractDef extends Fn {
|
|
198
|
+
return: this["arg0"] extends PlatformProviderConfig<infer Def> ? Def : never;
|
|
199
|
+
}
|
|
200
|
+
interface ExtractCustomEventNames extends Fn {
|
|
201
|
+
return: this["arg0"] extends AnyPlatformDef ? Exclude<keyof this["arg0"]["events"], "messages" | symbol | number> : never;
|
|
202
|
+
}
|
|
203
|
+
interface ToCustomEventVariant<EventName extends string> extends Fn {
|
|
204
|
+
return: this["arg0"] extends PlatformProviderConfig<infer Def> ? EventName extends keyof Def["events"] ? InferEventPayload<Def["events"][EventName]> & {
|
|
205
|
+
platform: Def["name"];
|
|
206
|
+
} : never : never;
|
|
207
|
+
}
|
|
208
|
+
type HasProvider<Providers extends PlatformProviderConfig[], Name extends string> = Pipe<Providers, [Tuples.Some<MatchesPlatformName<Name>>]>;
|
|
209
|
+
type AllCustomEventNames<Providers extends PlatformProviderConfig[]> = Pipe<Providers, [
|
|
210
|
+
Tuples.Map<ExtractDef>,
|
|
211
|
+
Tuples.Map<ExtractCustomEventNames>,
|
|
212
|
+
Tuples.ToUnion
|
|
213
|
+
]>;
|
|
214
|
+
type UnifiedCustomEvent<Providers extends PlatformProviderConfig[], EventName extends string> = Pipe<Providers, [
|
|
215
|
+
Tuples.Map<ToCustomEventVariant<EventName>>,
|
|
216
|
+
Tuples.ToUnion
|
|
217
|
+
]>;
|
|
218
|
+
type CustomEventStreams<Providers extends PlatformProviderConfig[]> = {
|
|
219
|
+
[K in Exclude<AllCustomEventNames<Providers>, ReservedNames> & string]: AsyncIterable<UnifiedCustomEvent<Providers, K>>;
|
|
220
|
+
};
|
|
221
|
+
type ResolvedSpaceOf<Def extends AnyPlatformDef> = AwaitedReturn<Def["space"]["resolve"]>;
|
|
222
|
+
type SchemaSpaceOf<Def extends AnyPlatformDef> = InferOptionalSchema<Def["space"]["schema"]>;
|
|
223
|
+
type ResolvedUserOf<Def extends AnyPlatformDef> = AwaitedReturn<Def["user"]["resolve"]>;
|
|
224
|
+
type SpaceShapeOf<Def extends AnyPlatformDef> = [SchemaSpaceOf<Def>] extends [
|
|
225
|
+
never
|
|
226
|
+
] ? ResolvedSpaceOf<Def> : SchemaSpaceOf<Def>;
|
|
227
|
+
type SpaceParamsInputOf<Def extends AnyPlatformDef> = InputSchema<Def["space"]["params"]>;
|
|
228
|
+
type SpaceArrayArgs<Def extends AnyPlatformDef> = [
|
|
229
|
+
SpaceParamsInputOf<Def>
|
|
230
|
+
] extends [never] ? [users: PlatformUser<Def>[]] : [users: PlatformUser<Def>[]] | [users: PlatformUser<Def>[], params: SpaceParamsInputOf<Def>] | [params: SpaceParamsInputOf<Def>];
|
|
231
|
+
type SpaceVarargArgs<Def extends AnyPlatformDef> = [
|
|
232
|
+
SpaceParamsInputOf<Def>
|
|
233
|
+
] extends [never] ? PlatformUser<Def>[] : PlatformUser<Def>[] | [...PlatformUser<Def>[], SpaceParamsInputOf<Def>];
|
|
234
|
+
type SpaceArgs<Def extends AnyPlatformDef> = SpaceArrayArgs<Def> | SpaceVarargArgs<Def>;
|
|
235
|
+
type PlatformSpace<Def extends AnyPlatformDef> = Omit<SpaceShapeOf<Def>, keyof Space> & Space;
|
|
236
|
+
type PlatformMessage<Def extends AnyPlatformDef> = Omit<SchemaInfer<Def["message"]>, keyof Message> & Message<Def["name"], PlatformUser<Def>, PlatformSpace<Def>>;
|
|
237
|
+
type PlatformUser<Def extends AnyPlatformDef> = Omit<ResolvedUserOf<Def>, keyof User> & User;
|
|
238
|
+
type PlatformInstance<Def extends AnyPlatformDef> = {
|
|
239
|
+
space(...args: SpaceArgs<Def>): Promise<PlatformSpace<Def>>;
|
|
240
|
+
user(userID: string): Promise<PlatformUser<Def>>;
|
|
241
|
+
} & {
|
|
242
|
+
[K in Exclude<keyof Def["events"], "messages" | symbol | number> as K extends ReservedNames ? never : K]: AsyncIterable<InferEventPayload<Def["events"][K]>>;
|
|
243
|
+
};
|
|
244
|
+
interface SpectrumLike<Providers extends PlatformProviderConfig[] = PlatformProviderConfig[]> {
|
|
245
|
+
readonly __internal: {
|
|
246
|
+
platforms: Map<string, {
|
|
247
|
+
client: unknown;
|
|
248
|
+
config: unknown;
|
|
249
|
+
definition: AnyPlatformDef;
|
|
250
|
+
}>;
|
|
251
|
+
};
|
|
252
|
+
readonly __providers: Providers;
|
|
253
|
+
}
|
|
254
|
+
interface Platform<Def extends AnyPlatformDef> {
|
|
255
|
+
config(config?: z__default.input<Def["config"]>): PlatformProviderConfig<Def>;
|
|
256
|
+
<Providers extends PlatformProviderConfig[]>(spectrum: SpectrumLike<Providers>): HasProvider<Providers, Def["name"]> extends true ? PlatformInstance<Def> : never;
|
|
257
|
+
(space: Space): PlatformSpace<Def>;
|
|
258
|
+
(message: Message): PlatformMessage<Def>;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export { type AnyPlatformDef as A, type CustomEventStreams as C, type EventProducer as E, type Message as M, type ProviderMessage as P, type SpectrumLike as S, type User as U, type PlatformDef as a, type Platform as b, type PlatformProviderConfig as c, type Space as d, type ContentBuilder as e, type Content as f, type PlatformInstance as g, type PlatformMessage as h, type PlatformSpace as i, type PlatformUser as j, type SchemaMessage as k, attachment as l, custom as m, text as t };
|
package/package.json
CHANGED
|
@@ -1,7 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spectrum-ts",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"main": "index.js",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"bun": "./src/index.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./providers/imessage": {
|
|
19
|
+
"types": "./dist/providers/imessage/index.d.ts",
|
|
20
|
+
"bun": "./src/providers/imessage/index.ts",
|
|
21
|
+
"default": "./dist/providers/imessage/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./providers/terminal": {
|
|
24
|
+
"types": "./dist/providers/terminal/index.d.ts",
|
|
25
|
+
"bun": "./src/providers/terminal/index.ts",
|
|
26
|
+
"default": "./dist/providers/terminal/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"dev": "tsup --watch"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@photon-ai/advanced-imessage": "^0.1.0",
|
|
35
|
+
"@photon-ai/imessage-kit": "^2.1.2",
|
|
36
|
+
"@repeaterjs/repeater": "^3.0.6",
|
|
37
|
+
"better-grpc": "^0.3.2",
|
|
38
|
+
"mime-types": "^3.0.1",
|
|
39
|
+
"type-fest": "^5.4.1",
|
|
40
|
+
"zod": "^4.2.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/bun": "latest",
|
|
44
|
+
"@types/mime-types": "^3.0.1",
|
|
45
|
+
"hotscript": "^1.0.13",
|
|
46
|
+
"tsup": "^8.4.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"typescript": "^5"
|
|
50
|
+
},
|
|
6
51
|
"license": "MIT"
|
|
7
52
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// biome-ignore lint/performance/noBarrelFile: library entry point
|
|
2
|
+
export { definePlatform } from "./platform/define";
|
|
3
|
+
export type {
|
|
4
|
+
AnyPlatformDef,
|
|
5
|
+
EventProducer,
|
|
6
|
+
Platform,
|
|
7
|
+
PlatformDef,
|
|
8
|
+
PlatformInstance,
|
|
9
|
+
PlatformMessage,
|
|
10
|
+
PlatformProviderConfig,
|
|
11
|
+
PlatformSpace,
|
|
12
|
+
PlatformUser,
|
|
13
|
+
SchemaMessage,
|
|
14
|
+
} from "./platform/types";
|
|
15
|
+
export { Spectrum, type SpectrumInstance } from "./spectrum";
|
|
16
|
+
export {
|
|
17
|
+
attachment,
|
|
18
|
+
type Content,
|
|
19
|
+
type ContentBuilder,
|
|
20
|
+
custom,
|
|
21
|
+
text,
|
|
22
|
+
} from "./types/content";
|
|
23
|
+
export type { Message } from "./types/message";
|
|
24
|
+
export type { Space } from "./types/space";
|
|
25
|
+
export type { User } from "./types/user";
|
|
26
|
+
export { type ManagedStream, mergeStreams, stream } from "./utils/stream";
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import type z from "zod";
|
|
2
|
+
import type { ContentBuilder } from "../types/content";
|
|
3
|
+
import type { Message } from "../types/message";
|
|
4
|
+
import type { Space } from "../types/space";
|
|
5
|
+
import type {
|
|
6
|
+
AnyPlatformDef,
|
|
7
|
+
Platform,
|
|
8
|
+
PlatformDef,
|
|
9
|
+
PlatformInstance,
|
|
10
|
+
PlatformMessage,
|
|
11
|
+
PlatformProviderConfig,
|
|
12
|
+
PlatformSpace,
|
|
13
|
+
PlatformUser,
|
|
14
|
+
ProviderMessage,
|
|
15
|
+
SpectrumLike,
|
|
16
|
+
} from "./types";
|
|
17
|
+
|
|
18
|
+
function createPlatformInstance<
|
|
19
|
+
Def extends AnyPlatformDef,
|
|
20
|
+
_Client,
|
|
21
|
+
_ConfigSchema extends z.ZodType<object>,
|
|
22
|
+
>(
|
|
23
|
+
def: Def,
|
|
24
|
+
runtime: { client: unknown; config: unknown }
|
|
25
|
+
): PlatformInstance<Def> {
|
|
26
|
+
const isPlatformUser = (value: unknown): value is PlatformUser<Def> => {
|
|
27
|
+
return (
|
|
28
|
+
typeof value === "object" &&
|
|
29
|
+
value !== null &&
|
|
30
|
+
"__platform" in value &&
|
|
31
|
+
(value as { __platform?: unknown }).__platform === def.name
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const normalizeSpaceArgs = (
|
|
36
|
+
args: unknown[]
|
|
37
|
+
): { users: PlatformUser<Def>[]; params: unknown } => {
|
|
38
|
+
if (args.length === 0) {
|
|
39
|
+
return { users: [], params: undefined };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const [first, ...rest] = args;
|
|
43
|
+
if (Array.isArray(first)) {
|
|
44
|
+
return {
|
|
45
|
+
users: first as PlatformUser<Def>[],
|
|
46
|
+
params: rest[0],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!isPlatformUser(first)) {
|
|
51
|
+
return {
|
|
52
|
+
users: [],
|
|
53
|
+
params: first,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const last = args.at(-1);
|
|
58
|
+
if (last !== undefined && !isPlatformUser(last)) {
|
|
59
|
+
return {
|
|
60
|
+
users: args.slice(0, -1) as PlatformUser<Def>[],
|
|
61
|
+
params: last,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
users: args as PlatformUser<Def>[],
|
|
67
|
+
params: undefined,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const base = {
|
|
72
|
+
async user(userID: string) {
|
|
73
|
+
const resolved = await def.user.resolve({
|
|
74
|
+
input: { userID },
|
|
75
|
+
client: runtime.client as _Client,
|
|
76
|
+
config: runtime.config as z.infer<_ConfigSchema>,
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
...resolved,
|
|
80
|
+
__platform: def.name,
|
|
81
|
+
} as PlatformUser<Def>;
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
async space(...args: unknown[]) {
|
|
85
|
+
const { users, params } = normalizeSpaceArgs(args);
|
|
86
|
+
let parsedParams = params;
|
|
87
|
+
if (params !== undefined && def.space.params) {
|
|
88
|
+
parsedParams = def.space.params.parse(params);
|
|
89
|
+
}
|
|
90
|
+
const resolved = await def.space.resolve({
|
|
91
|
+
input: { users, params: parsedParams },
|
|
92
|
+
client: runtime.client as _Client,
|
|
93
|
+
config: runtime.config as z.infer<_ConfigSchema>,
|
|
94
|
+
});
|
|
95
|
+
const parsedSpace = def.space.schema
|
|
96
|
+
? def.space.schema.parse(resolved)
|
|
97
|
+
: resolved;
|
|
98
|
+
const spaceRef = {
|
|
99
|
+
id: parsedSpace.id,
|
|
100
|
+
__platform: def.name,
|
|
101
|
+
};
|
|
102
|
+
const typingCtx = {
|
|
103
|
+
space: spaceRef,
|
|
104
|
+
client: runtime.client as _Client,
|
|
105
|
+
config: runtime.config as z.infer<_ConfigSchema>,
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
...parsedSpace,
|
|
109
|
+
...spaceRef,
|
|
110
|
+
send: async (...content: [ContentBuilder, ...ContentBuilder[]]) => {
|
|
111
|
+
const built = await Promise.all(content.map((c) => c.build()));
|
|
112
|
+
await def.actions.send({
|
|
113
|
+
...typingCtx,
|
|
114
|
+
content: built,
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
startTyping: async () => {
|
|
118
|
+
await def.actions.startTyping?.(typingCtx);
|
|
119
|
+
},
|
|
120
|
+
stopTyping: async () => {
|
|
121
|
+
await def.actions.stopTyping?.(typingCtx);
|
|
122
|
+
},
|
|
123
|
+
responding: async <T>(fn: () => T | Promise<T>): Promise<T> => {
|
|
124
|
+
await def.actions.startTyping?.(typingCtx);
|
|
125
|
+
try {
|
|
126
|
+
return await fn();
|
|
127
|
+
} finally {
|
|
128
|
+
await def.actions.stopTyping?.(typingCtx).catch(() => {});
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
} as PlatformSpace<Def>;
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Add flat event properties for custom events (non-messages)
|
|
136
|
+
const eventProperties: Record<string, AsyncIterable<unknown>> = {};
|
|
137
|
+
for (const eventName of Object.keys(def.events)) {
|
|
138
|
+
if (eventName === "messages") {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const producer = def.events[eventName] as
|
|
142
|
+
| ((ctx: { client: unknown; config: unknown }) => AsyncIterable<unknown>)
|
|
143
|
+
| undefined;
|
|
144
|
+
if (producer) {
|
|
145
|
+
eventProperties[eventName] = producer({
|
|
146
|
+
client: runtime.client,
|
|
147
|
+
config: runtime.config,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return Object.assign(base, eventProperties) as PlatformInstance<Def>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function definePlatform<
|
|
156
|
+
_Name extends string,
|
|
157
|
+
_ConfigSchema extends z.ZodType<object>,
|
|
158
|
+
_UserSchema extends z.ZodType<object> | undefined,
|
|
159
|
+
_SpaceSchema extends z.ZodType<object> | undefined,
|
|
160
|
+
_SpaceParamsSchema extends z.ZodType<object> | undefined,
|
|
161
|
+
_Client,
|
|
162
|
+
_ResolvedUser extends { id: string },
|
|
163
|
+
_ResolvedSpace extends { id: string },
|
|
164
|
+
_MessageSchema extends z.ZodType<object> | undefined = undefined,
|
|
165
|
+
_MessageType extends ProviderMessage<
|
|
166
|
+
_ResolvedUser,
|
|
167
|
+
_ResolvedSpace,
|
|
168
|
+
_MessageSchema extends z.ZodType<object>
|
|
169
|
+
? z.infer<_MessageSchema>
|
|
170
|
+
: Record<never, never>
|
|
171
|
+
> = ProviderMessage<
|
|
172
|
+
_ResolvedUser,
|
|
173
|
+
_ResolvedSpace,
|
|
174
|
+
_MessageSchema extends z.ZodType<object>
|
|
175
|
+
? z.infer<_MessageSchema>
|
|
176
|
+
: Record<never, never>
|
|
177
|
+
>,
|
|
178
|
+
_Events extends {
|
|
179
|
+
messages: (ctx: {
|
|
180
|
+
client: _Client;
|
|
181
|
+
config: z.infer<_ConfigSchema>;
|
|
182
|
+
}) => AsyncIterable<_MessageType>;
|
|
183
|
+
} = {
|
|
184
|
+
messages: (ctx: {
|
|
185
|
+
client: _Client;
|
|
186
|
+
config: z.infer<_ConfigSchema>;
|
|
187
|
+
}) => AsyncIterable<_MessageType>;
|
|
188
|
+
},
|
|
189
|
+
_Static extends Record<string, unknown> = Record<never, never>,
|
|
190
|
+
>(
|
|
191
|
+
name: _Name,
|
|
192
|
+
def: Omit<
|
|
193
|
+
PlatformDef<
|
|
194
|
+
_Name,
|
|
195
|
+
_ConfigSchema,
|
|
196
|
+
_UserSchema,
|
|
197
|
+
_SpaceSchema,
|
|
198
|
+
_SpaceParamsSchema,
|
|
199
|
+
_Client,
|
|
200
|
+
_ResolvedUser,
|
|
201
|
+
_ResolvedSpace,
|
|
202
|
+
_MessageSchema,
|
|
203
|
+
_MessageType,
|
|
204
|
+
_Events
|
|
205
|
+
>,
|
|
206
|
+
"name"
|
|
207
|
+
> & { static?: _Static }
|
|
208
|
+
): Platform<
|
|
209
|
+
PlatformDef<
|
|
210
|
+
_Name,
|
|
211
|
+
_ConfigSchema,
|
|
212
|
+
_UserSchema,
|
|
213
|
+
_SpaceSchema,
|
|
214
|
+
_SpaceParamsSchema,
|
|
215
|
+
_Client,
|
|
216
|
+
_ResolvedUser,
|
|
217
|
+
_ResolvedSpace,
|
|
218
|
+
_MessageSchema,
|
|
219
|
+
_MessageType,
|
|
220
|
+
_Events
|
|
221
|
+
>
|
|
222
|
+
> &
|
|
223
|
+
Readonly<_Static> {
|
|
224
|
+
type Def = PlatformDef<
|
|
225
|
+
_Name,
|
|
226
|
+
_ConfigSchema,
|
|
227
|
+
_UserSchema,
|
|
228
|
+
_SpaceSchema,
|
|
229
|
+
_SpaceParamsSchema,
|
|
230
|
+
_Client,
|
|
231
|
+
_ResolvedUser,
|
|
232
|
+
_ResolvedSpace,
|
|
233
|
+
_MessageSchema,
|
|
234
|
+
_MessageType,
|
|
235
|
+
_Events
|
|
236
|
+
>;
|
|
237
|
+
|
|
238
|
+
const fullDef = { name, ...def };
|
|
239
|
+
|
|
240
|
+
const platformCache = new WeakMap<SpectrumLike, PlatformInstance<Def>>();
|
|
241
|
+
|
|
242
|
+
const narrowSpectrum = (spectrum: SpectrumLike) => {
|
|
243
|
+
const cached = platformCache.get(spectrum);
|
|
244
|
+
if (cached) {
|
|
245
|
+
return cached;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const runtime = spectrum.__internal.platforms.get(name);
|
|
249
|
+
if (!runtime) {
|
|
250
|
+
throw new Error(`Platform "${name}" is not registered`);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const instance = createPlatformInstance<Def, _Client, _ConfigSchema>(
|
|
254
|
+
fullDef as Def & AnyPlatformDef,
|
|
255
|
+
runtime
|
|
256
|
+
);
|
|
257
|
+
platformCache.set(spectrum, instance);
|
|
258
|
+
return instance;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const narrowSpace = (input: Space) => {
|
|
262
|
+
if (input.__platform !== name) {
|
|
263
|
+
throw new Error(
|
|
264
|
+
`Expected space from "${name}", got "${input.__platform}"`
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
return input as PlatformSpace<Def>;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const narrowMessage = (input: Message) => {
|
|
271
|
+
if (input.platform !== name) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
`Expected message from "${name}", got "${input.platform}"`
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
return input as PlatformMessage<Def>;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const narrower = ((input: SpectrumLike | Space | Message) => {
|
|
280
|
+
if ("__providers" in input && "__internal" in input) {
|
|
281
|
+
return narrowSpectrum(input as SpectrumLike);
|
|
282
|
+
}
|
|
283
|
+
if ("__platform" in input && "send" in input) {
|
|
284
|
+
return narrowSpace(input as Space);
|
|
285
|
+
}
|
|
286
|
+
if ("platform" in input && "sender" in input && "space" in input) {
|
|
287
|
+
return narrowMessage(input as Message);
|
|
288
|
+
}
|
|
289
|
+
throw new Error("Invalid input to platform narrowing function");
|
|
290
|
+
}) as Platform<Def>;
|
|
291
|
+
|
|
292
|
+
narrower.config = (
|
|
293
|
+
config: z.input<_ConfigSchema> = {} as z.input<_ConfigSchema>
|
|
294
|
+
) => {
|
|
295
|
+
return {
|
|
296
|
+
__tag: "PlatformProviderConfig" as const,
|
|
297
|
+
__def: undefined as unknown as Def,
|
|
298
|
+
__name: name,
|
|
299
|
+
config,
|
|
300
|
+
__definition: fullDef as AnyPlatformDef,
|
|
301
|
+
} satisfies PlatformProviderConfig<Def> as PlatformProviderConfig<Def>;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
if (def.static) {
|
|
305
|
+
Object.assign(narrower, def.static);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return narrower as Platform<Def> & Readonly<_Static>;
|
|
309
|
+
}
|