restream-sdk 0.1.2 → 0.1.4
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/package.json +1 -1
- package/src/core.js +25 -5
- package/src/react.js +4 -2
- package/types/core.d.ts +1 -0
- package/types/index.d.ts +22 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "restream-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Plug-and-play headless React hooks to add multi-platform restreaming (connect socials, go live, live chat + viewers) with zero client backend.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/src/core.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// (publisherSessionId) is produced by the client's existing stream and passed
|
|
5
5
|
// into goLive() — this module never captures or publishes media itself.
|
|
6
6
|
|
|
7
|
-
export const PLATFORMS = ["twitch", "kick", "youtube", "facebook", "instagram"];
|
|
7
|
+
export const PLATFORMS = ["twitch", "kick", "youtube", "facebook", "instagram", "tiktok"];
|
|
8
8
|
|
|
9
9
|
const TERMINAL_STATUS = new Set(["stopped", "failed", "ended", "error", "completed"]);
|
|
10
10
|
|
|
@@ -129,12 +129,30 @@ export class RestreamStudio extends EventTarget {
|
|
|
129
129
|
return this.connections;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/** Ask the backend which OAuth platforms are configured for this client. */
|
|
133
|
+
async listOAuthPlatforms() {
|
|
134
|
+
return this._req("GET", `/api/v1/connect/platforms${this._userQuery()}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* List the channels the user connected inside their Restream account (the
|
|
139
|
+
* platforms Restream fans out to, e.g. TikTok). Requires a connected Restream
|
|
140
|
+
* account. Returns [{ id, platform, displayName, url, active }]; pass the chosen
|
|
141
|
+
* ids to goLive({ destinations: ["restream"], restreamChannels: [...] }).
|
|
142
|
+
*/
|
|
143
|
+
async listRestreamChannels() {
|
|
144
|
+
const r = await this._req("GET", `/api/v1/connect/restream/channels${this._userQuery()}`);
|
|
145
|
+
return r?.channels || [];
|
|
146
|
+
}
|
|
147
|
+
|
|
132
148
|
/** Open the hosted OAuth popup for a platform; resolves when connected (or the popup closes). */
|
|
133
149
|
async connect(platform) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const popup = window.open(
|
|
150
|
+
// Open the popup synchronously, inside the click's user-activation window —
|
|
151
|
+
// any await before window.open consumes the gesture and the browser blocks it.
|
|
152
|
+
const popup = window.open("", "restream_connect", "width=560,height=760");
|
|
137
153
|
if (!popup) throw new Error("popup blocked — allow popups to connect accounts");
|
|
154
|
+
const q = await this._authQuery();
|
|
155
|
+
popup.location = `${this.apiBase}/api/v1/connect/${platform}/start?${new URLSearchParams(q)}`;
|
|
138
156
|
return new Promise((resolve, reject) => {
|
|
139
157
|
const cleanup = () => {
|
|
140
158
|
window.removeEventListener("message", onMsg);
|
|
@@ -173,7 +191,7 @@ export class RestreamStudio extends EventTarget {
|
|
|
173
191
|
* @param {boolean} [opts.recording]
|
|
174
192
|
* @param {string[]} [opts.trackNames] tracks actually published, e.g. ["audio","video"]
|
|
175
193
|
*/
|
|
176
|
-
async goLive({ publisherSessionId, destinations, overlay, recording, trackNames } = {}) {
|
|
194
|
+
async goLive({ publisherSessionId, destinations, overlay, recording, trackNames, restreamChannels } = {}) {
|
|
177
195
|
if (!publisherSessionId) throw new Error("publisherSessionId is required (from your existing stream session)");
|
|
178
196
|
const body = {
|
|
179
197
|
publisherSessionId,
|
|
@@ -182,6 +200,8 @@ export class RestreamStudio extends EventTarget {
|
|
|
182
200
|
recording,
|
|
183
201
|
};
|
|
184
202
|
if (trackNames && trackNames.length) body.trackNames = trackNames;
|
|
203
|
+
// Per-platform selection for the "restream" fan-out bridge (channel ids or platform names).
|
|
204
|
+
if (restreamChannels && restreamChannels.length) body.restreamChannels = restreamChannels;
|
|
185
205
|
if (this.publishableKey && this.userId) body.clientUserId = this.userId; // token mode binds server-side
|
|
186
206
|
const job = await this._req("POST", "/api/v1/jobs", body);
|
|
187
207
|
this.job = job;
|
package/src/react.js
CHANGED
|
@@ -40,6 +40,8 @@ export function useRestream(opts) {
|
|
|
40
40
|
connect: useCallback((p) => studio.connect(p), [studio]),
|
|
41
41
|
disconnect: useCallback((p) => studio.disconnect(p), [studio]),
|
|
42
42
|
listConnections: useCallback(() => studio.listConnections(), [studio]),
|
|
43
|
+
listOAuthPlatforms: useCallback(() => studio.listOAuthPlatforms(), [studio]),
|
|
44
|
+
listRestreamChannels: useCallback(() => studio.listRestreamChannels(), [studio]),
|
|
43
45
|
arm: useCallback((o) => studio.arm(o), [studio]),
|
|
44
46
|
goLive: useCallback((o) => studio.goLive(o), [studio]),
|
|
45
47
|
stopLive: useCallback(() => studio.stopLive(), [studio]),
|
|
@@ -51,8 +53,8 @@ export function useRestream(opts) {
|
|
|
51
53
|
|
|
52
54
|
/** Convenience: just the social-connection state + actions. */
|
|
53
55
|
export function useConnections(opts) {
|
|
54
|
-
const { connections, connect, disconnect, listConnections } = useRestream(opts);
|
|
55
|
-
return { connections, connect, disconnect, refresh: listConnections };
|
|
56
|
+
const { connections, connect, disconnect, listConnections, listOAuthPlatforms, listRestreamChannels } = useRestream(opts);
|
|
57
|
+
return { connections, connect, disconnect, refresh: listConnections, listOAuthPlatforms, listRestreamChannels };
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
/** Convenience: live chat (incoming comments + outbound send). Pass an existing studio. */
|
package/types/core.d.ts
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
export type Platform = "twitch" | "kick" | "youtube" | "facebook" | "instagram";
|
|
1
|
+
export type Platform = "twitch" | "kick" | "youtube" | "facebook" | "instagram" | "tiktok" | "restream";
|
|
2
|
+
|
|
3
|
+
/** A channel the user connected inside their Restream account (a fan-out target). */
|
|
4
|
+
export interface RestreamChannel {
|
|
5
|
+
id: string;
|
|
6
|
+
platform: string;
|
|
7
|
+
displayName: string | null;
|
|
8
|
+
url: string | null;
|
|
9
|
+
active: boolean;
|
|
10
|
+
}
|
|
2
11
|
export const PLATFORMS: Platform[];
|
|
3
12
|
|
|
4
13
|
export interface RestreamOptions {
|
|
@@ -60,6 +69,12 @@ export interface GoLiveParams {
|
|
|
60
69
|
recording?: boolean;
|
|
61
70
|
/** Track names actually published (e.g. ["audio","video"] or ["video"]). */
|
|
62
71
|
trackNames?: string[];
|
|
72
|
+
/**
|
|
73
|
+
* For the "restream" fan-out destination: which Restream channels to relay to
|
|
74
|
+
* (channel ids from listRestreamChannels(), or platform names like "tiktok").
|
|
75
|
+
* Omit to use whichever channels are currently active in the Restream account.
|
|
76
|
+
*/
|
|
77
|
+
restreamChannels?: string[];
|
|
63
78
|
}
|
|
64
79
|
|
|
65
80
|
export interface OverlayUpdate {
|
|
@@ -84,6 +99,8 @@ export class RestreamStudio extends EventTarget {
|
|
|
84
99
|
on(type: "comments", cb: (c: Comment[]) => void): () => void;
|
|
85
100
|
on(type: "error", cb: (e: Error) => void): () => void;
|
|
86
101
|
listConnections(): Promise<Connection[]>;
|
|
102
|
+
listOAuthPlatforms(): Promise<{ platforms: Platform[]; frontendOrigin: string; redirectOrigin: string }>;
|
|
103
|
+
listRestreamChannels(): Promise<RestreamChannel[]>;
|
|
87
104
|
connect(platform: Platform): Promise<{ platform: Platform; closed?: boolean }>;
|
|
88
105
|
disconnect(platform: Platform): Promise<Connection[]>;
|
|
89
106
|
arm(opts: { destinations: Platform[] }): unknown;
|
|
@@ -111,6 +128,8 @@ export interface UseRestream {
|
|
|
111
128
|
connect(platform: Platform): Promise<{ platform: Platform; closed?: boolean }>;
|
|
112
129
|
disconnect(platform: Platform): Promise<Connection[]>;
|
|
113
130
|
listConnections(): Promise<Connection[]>;
|
|
131
|
+
listOAuthPlatforms(): Promise<{ platforms: Platform[]; frontendOrigin: string; redirectOrigin: string }>;
|
|
132
|
+
listRestreamChannels(): Promise<RestreamChannel[]>;
|
|
114
133
|
arm(opts: { destinations: Platform[] }): unknown;
|
|
115
134
|
goLive(opts: GoLiveParams): Promise<Job>;
|
|
116
135
|
stopLive(): Promise<unknown>;
|
|
@@ -125,6 +144,8 @@ export function useConnections(opts: RestreamOptions): {
|
|
|
125
144
|
connect(platform: Platform): Promise<{ platform: Platform; closed?: boolean }>;
|
|
126
145
|
disconnect(platform: Platform): Promise<Connection[]>;
|
|
127
146
|
refresh(): Promise<Connection[]>;
|
|
147
|
+
listOAuthPlatforms(): Promise<{ platforms: Platform[]; frontendOrigin: string; redirectOrigin: string }>;
|
|
148
|
+
listRestreamChannels(): Promise<RestreamChannel[]>;
|
|
128
149
|
};
|
|
129
150
|
export function useLiveChat(studio: RestreamStudio): { comments: Comment[]; send(message: string, platforms?: Platform[]): Promise<unknown> };
|
|
130
151
|
export function useViewers(studio: RestreamStudio): ViewerCounts | null;
|