payfri-video-sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +289 -0
- package/app.plugin.cjs +8 -0
- package/dist/client/index.cjs +99 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +53 -0
- package/dist/client/index.d.ts +53 -0
- package/dist/client/index.js +97 -0
- package/dist/client/index.js.map +1 -0
- package/dist/native/index.cjs +151 -0
- package/dist/native/index.cjs.map +1 -0
- package/dist/native/index.d.cts +84 -0
- package/dist/native/index.d.ts +84 -0
- package/dist/native/index.js +148 -0
- package/dist/native/index.js.map +1 -0
- package/dist/plugin/withVideoSdk.cjs +25 -0
- package/dist/plugin/withVideoSdk.cjs.map +1 -0
- package/dist/plugin/withVideoSdk.d.cts +23 -0
- package/dist/plugin/withVideoSdk.d.ts +23 -0
- package/dist/plugin/withVideoSdk.js +23 -0
- package/dist/plugin/withVideoSdk.js.map +1 -0
- package/dist/server/index.cjs +61 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +79 -0
- package/dist/server/index.d.ts +79 -0
- package/dist/server/index.js +58 -0
- package/dist/server/index.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/server/errors.ts
|
|
4
|
+
var VideoApiError = class extends Error {
|
|
5
|
+
constructor(code, message, status) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.name = "VideoApiError";
|
|
10
|
+
}
|
|
11
|
+
code;
|
|
12
|
+
status;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/server/client.ts
|
|
16
|
+
function isApiErrorBody(value) {
|
|
17
|
+
return typeof value === "object" && value !== null && "error" in value && typeof value.error?.code === "string";
|
|
18
|
+
}
|
|
19
|
+
function createVideoClient(options) {
|
|
20
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
21
|
+
if (typeof fetchFn !== "function") {
|
|
22
|
+
throw new Error("No hay fetch disponible; p\xE1salo en options.fetch");
|
|
23
|
+
}
|
|
24
|
+
const baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
25
|
+
async function request(method, path, body, parseJson = true) {
|
|
26
|
+
const res = await fetchFn(`${baseUrl}${path}`, {
|
|
27
|
+
method,
|
|
28
|
+
headers: {
|
|
29
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
30
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
31
|
+
},
|
|
32
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
33
|
+
});
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
const payload = await res.json().catch(() => null);
|
|
36
|
+
if (isApiErrorBody(payload)) {
|
|
37
|
+
throw new VideoApiError(payload.error.code, payload.error.message, res.status);
|
|
38
|
+
}
|
|
39
|
+
throw new VideoApiError("HTTP_ERROR", `Error HTTP ${res.status}`, res.status);
|
|
40
|
+
}
|
|
41
|
+
if (!parseJson) {
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
return await res.json();
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
rooms: {
|
|
48
|
+
create: (input = {}) => request("POST", "/v1/rooms", input),
|
|
49
|
+
get: (roomName) => request("GET", `/v1/rooms/${encodeURIComponent(roomName)}`),
|
|
50
|
+
end: (roomName) => request("DELETE", `/v1/rooms/${encodeURIComponent(roomName)}`, void 0, false)
|
|
51
|
+
},
|
|
52
|
+
tokens: {
|
|
53
|
+
issue: (input) => request("POST", "/v1/tokens", input)
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
exports.VideoApiError = VideoApiError;
|
|
59
|
+
exports.createVideoClient = createVideoClient;
|
|
60
|
+
//# sourceMappingURL=index.cjs.map
|
|
61
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/errors.ts","../../src/server/client.ts"],"names":[],"mappings":";;;AACO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EACvC,WAAA,CACW,IAAA,EACT,OAAA,EACS,MAAA,EACT;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAJJ,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAGT,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AAAA,EANW,IAAA;AAAA,EAEA,MAAA;AAKb;;;ACoBA,SAAS,eAAe,KAAA,EAAuC;AAC7D,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,IAAA,IACV,WAAW,KAAA,IACX,OAAQ,KAAA,CAAuB,KAAA,EAAO,IAAA,KAAS,QAAA;AAEnD;AAMO,SAAS,kBAAkB,OAAA,EAA0C;AAC1E,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,IAAS,UAAA,CAAW,KAAA;AAC5C,EAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,IAAA,MAAM,IAAI,MAAM,qDAAkD,CAAA;AAAA,EACpE;AACA,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAElD,EAAA,eAAe,OAAA,CACb,MAAA,EACA,IAAA,EACA,IAAA,EACA,YAAY,IAAA,EACA;AACZ,IAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,GAAG,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,MAC7C,MAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,aAAA,EAAe,CAAA,OAAA,EAAU,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA,QACvC,GAAI,IAAA,KAAS,MAAA,GAAY,EAAE,cAAA,EAAgB,kBAAA,KAAuB;AAAC,OACrE;AAAA,MACA,MAAM,IAAA,KAAS,MAAA,GAAY,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI;AAAA,KACnD,CAAA;AAED,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,UAAmB,MAAM,GAAA,CAAI,MAAK,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAC1D,MAAA,IAAI,cAAA,CAAe,OAAO,CAAA,EAAG;AAC3B,QAAA,MAAM,IAAI,cAAc,OAAA,CAAQ,KAAA,CAAM,MAAM,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,GAAA,CAAI,MAAM,CAAA;AAAA,MAC/E;AACA,MAAA,MAAM,IAAI,cAAc,YAAA,EAAc,CAAA,WAAA,EAAc,IAAI,MAAM,CAAA,CAAA,EAAI,IAAI,MAAM,CAAA;AAAA,IAC9E;AAEA,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,EACzB;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ,CAAC,KAAA,GAAQ,OAAO,OAAA,CAAc,MAAA,EAAQ,aAAa,KAAK,CAAA;AAAA,MAChE,GAAA,EAAK,CAAC,QAAA,KAAa,OAAA,CAAmB,OAAO,CAAA,UAAA,EAAa,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,MACxF,GAAA,EAAK,CAAC,QAAA,KACJ,OAAA,CAAc,QAAA,EAAU,CAAA,UAAA,EAAa,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA,EAAI,MAAA,EAAW,KAAK;AAAA,KACzF;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,OAAO,CAAC,KAAA,KAAU,OAAA,CAAqB,MAAA,EAAQ,cAAc,KAAK;AAAA;AACpE,GACF;AACF","file":"index.cjs","sourcesContent":["/** Error tipado de la API de video. Expone `code` estable y `status` HTTP. */\nexport class VideoApiError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = \"VideoApiError\";\n }\n}\n","import type {\n ApiErrorBody,\n CreateRoomInput,\n IssuedToken,\n IssueTokenInput,\n Room,\n RoomState,\n} from \"../shared/contract\";\nimport { VideoApiError } from \"./errors\";\n\nexport interface VideoClientOptions {\n /** Base URL de la API, p.ej. \"https://api.video.tuempresa.com\". */\n baseUrl: string;\n /** API key del tenant. SOLO en servidores; nunca en el navegador. */\n apiKey: string;\n /** fetch personalizado (tests / runtimes sin fetch global). */\n fetch?: typeof fetch;\n}\n\nexport interface VideoClient {\n rooms: {\n create(input?: CreateRoomInput): Promise<Room>;\n get(roomName: string): Promise<RoomState>;\n end(roomName: string): Promise<void>;\n };\n tokens: {\n issue(input: IssueTokenInput): Promise<IssuedToken>;\n };\n}\n\nfunction isApiErrorBody(value: unknown): value is ApiErrorBody {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"error\" in value &&\n typeof (value as ApiErrorBody).error?.code === \"string\"\n );\n}\n\n/**\n * Cliente backend del servicio de video. Usa la API key del tenant para hablar\n * con la API REST. Pensado para correr SOLO en servidores.\n */\nexport function createVideoClient(options: VideoClientOptions): VideoClient {\n const fetchFn = options.fetch ?? globalThis.fetch;\n if (typeof fetchFn !== \"function\") {\n throw new Error(\"No hay fetch disponible; pásalo en options.fetch\");\n }\n const baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n\n async function request<T>(\n method: string,\n path: string,\n body?: unknown,\n parseJson = true,\n ): Promise<T> {\n const res = await fetchFn(`${baseUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${options.apiKey}`,\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const payload: unknown = await res.json().catch(() => null);\n if (isApiErrorBody(payload)) {\n throw new VideoApiError(payload.error.code, payload.error.message, res.status);\n }\n throw new VideoApiError(\"HTTP_ERROR\", `Error HTTP ${res.status}`, res.status);\n }\n\n if (!parseJson) {\n return undefined as T;\n }\n return (await res.json()) as T;\n }\n\n return {\n rooms: {\n create: (input = {}) => request<Room>(\"POST\", \"/v1/rooms\", input),\n get: (roomName) => request<RoomState>(\"GET\", `/v1/rooms/${encodeURIComponent(roomName)}`),\n end: (roomName) =>\n request<void>(\"DELETE\", `/v1/rooms/${encodeURIComponent(roomName)}`, undefined, false),\n },\n tokens: {\n issue: (input) => request<IssuedToken>(\"POST\", \"/v1/tokens\", input),\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos del contrato REST (solo tipos, sin runtime). Compartidos por /server.
|
|
3
|
+
* El /client NO importa apiKey ni nada de aquí que la exponga.
|
|
4
|
+
*/
|
|
5
|
+
interface CreateRoomInput {
|
|
6
|
+
name?: string;
|
|
7
|
+
maxParticipants?: number;
|
|
8
|
+
emptyTimeoutSeconds?: number;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
interface Room {
|
|
12
|
+
id: string;
|
|
13
|
+
roomName: string;
|
|
14
|
+
livekitUrl: string;
|
|
15
|
+
maxParticipants: number | null;
|
|
16
|
+
createdAt: string;
|
|
17
|
+
}
|
|
18
|
+
interface Participant {
|
|
19
|
+
identity: string;
|
|
20
|
+
name: string | null;
|
|
21
|
+
state: string;
|
|
22
|
+
joinedAt: number | null;
|
|
23
|
+
}
|
|
24
|
+
interface RoomState {
|
|
25
|
+
roomName: string;
|
|
26
|
+
status: string;
|
|
27
|
+
participants: Participant[];
|
|
28
|
+
}
|
|
29
|
+
interface IssueTokenInput {
|
|
30
|
+
roomName: string;
|
|
31
|
+
identity: string;
|
|
32
|
+
displayName?: string;
|
|
33
|
+
canPublish?: boolean;
|
|
34
|
+
canSubscribe?: boolean;
|
|
35
|
+
canPublishData?: boolean;
|
|
36
|
+
ttlSeconds?: number;
|
|
37
|
+
metadata?: Record<string, unknown>;
|
|
38
|
+
createIfMissing?: boolean;
|
|
39
|
+
}
|
|
40
|
+
interface IssuedToken {
|
|
41
|
+
token: string;
|
|
42
|
+
livekitUrl: string;
|
|
43
|
+
roomName: string;
|
|
44
|
+
identity: string;
|
|
45
|
+
expiresAt: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface VideoClientOptions {
|
|
49
|
+
/** Base URL de la API, p.ej. "https://api.video.tuempresa.com". */
|
|
50
|
+
baseUrl: string;
|
|
51
|
+
/** API key del tenant. SOLO en servidores; nunca en el navegador. */
|
|
52
|
+
apiKey: string;
|
|
53
|
+
/** fetch personalizado (tests / runtimes sin fetch global). */
|
|
54
|
+
fetch?: typeof fetch;
|
|
55
|
+
}
|
|
56
|
+
interface VideoClient {
|
|
57
|
+
rooms: {
|
|
58
|
+
create(input?: CreateRoomInput): Promise<Room>;
|
|
59
|
+
get(roomName: string): Promise<RoomState>;
|
|
60
|
+
end(roomName: string): Promise<void>;
|
|
61
|
+
};
|
|
62
|
+
tokens: {
|
|
63
|
+
issue(input: IssueTokenInput): Promise<IssuedToken>;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Cliente backend del servicio de video. Usa la API key del tenant para hablar
|
|
68
|
+
* con la API REST. Pensado para correr SOLO en servidores.
|
|
69
|
+
*/
|
|
70
|
+
declare function createVideoClient(options: VideoClientOptions): VideoClient;
|
|
71
|
+
|
|
72
|
+
/** Error tipado de la API de video. Expone `code` estable y `status` HTTP. */
|
|
73
|
+
declare class VideoApiError extends Error {
|
|
74
|
+
readonly code: string;
|
|
75
|
+
readonly status: number;
|
|
76
|
+
constructor(code: string, message: string, status: number);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { type CreateRoomInput, type IssueTokenInput, type IssuedToken, type Participant, type Room, type RoomState, VideoApiError, type VideoClient, type VideoClientOptions, createVideoClient };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos del contrato REST (solo tipos, sin runtime). Compartidos por /server.
|
|
3
|
+
* El /client NO importa apiKey ni nada de aquí que la exponga.
|
|
4
|
+
*/
|
|
5
|
+
interface CreateRoomInput {
|
|
6
|
+
name?: string;
|
|
7
|
+
maxParticipants?: number;
|
|
8
|
+
emptyTimeoutSeconds?: number;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
interface Room {
|
|
12
|
+
id: string;
|
|
13
|
+
roomName: string;
|
|
14
|
+
livekitUrl: string;
|
|
15
|
+
maxParticipants: number | null;
|
|
16
|
+
createdAt: string;
|
|
17
|
+
}
|
|
18
|
+
interface Participant {
|
|
19
|
+
identity: string;
|
|
20
|
+
name: string | null;
|
|
21
|
+
state: string;
|
|
22
|
+
joinedAt: number | null;
|
|
23
|
+
}
|
|
24
|
+
interface RoomState {
|
|
25
|
+
roomName: string;
|
|
26
|
+
status: string;
|
|
27
|
+
participants: Participant[];
|
|
28
|
+
}
|
|
29
|
+
interface IssueTokenInput {
|
|
30
|
+
roomName: string;
|
|
31
|
+
identity: string;
|
|
32
|
+
displayName?: string;
|
|
33
|
+
canPublish?: boolean;
|
|
34
|
+
canSubscribe?: boolean;
|
|
35
|
+
canPublishData?: boolean;
|
|
36
|
+
ttlSeconds?: number;
|
|
37
|
+
metadata?: Record<string, unknown>;
|
|
38
|
+
createIfMissing?: boolean;
|
|
39
|
+
}
|
|
40
|
+
interface IssuedToken {
|
|
41
|
+
token: string;
|
|
42
|
+
livekitUrl: string;
|
|
43
|
+
roomName: string;
|
|
44
|
+
identity: string;
|
|
45
|
+
expiresAt: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface VideoClientOptions {
|
|
49
|
+
/** Base URL de la API, p.ej. "https://api.video.tuempresa.com". */
|
|
50
|
+
baseUrl: string;
|
|
51
|
+
/** API key del tenant. SOLO en servidores; nunca en el navegador. */
|
|
52
|
+
apiKey: string;
|
|
53
|
+
/** fetch personalizado (tests / runtimes sin fetch global). */
|
|
54
|
+
fetch?: typeof fetch;
|
|
55
|
+
}
|
|
56
|
+
interface VideoClient {
|
|
57
|
+
rooms: {
|
|
58
|
+
create(input?: CreateRoomInput): Promise<Room>;
|
|
59
|
+
get(roomName: string): Promise<RoomState>;
|
|
60
|
+
end(roomName: string): Promise<void>;
|
|
61
|
+
};
|
|
62
|
+
tokens: {
|
|
63
|
+
issue(input: IssueTokenInput): Promise<IssuedToken>;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Cliente backend del servicio de video. Usa la API key del tenant para hablar
|
|
68
|
+
* con la API REST. Pensado para correr SOLO en servidores.
|
|
69
|
+
*/
|
|
70
|
+
declare function createVideoClient(options: VideoClientOptions): VideoClient;
|
|
71
|
+
|
|
72
|
+
/** Error tipado de la API de video. Expone `code` estable y `status` HTTP. */
|
|
73
|
+
declare class VideoApiError extends Error {
|
|
74
|
+
readonly code: string;
|
|
75
|
+
readonly status: number;
|
|
76
|
+
constructor(code: string, message: string, status: number);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { type CreateRoomInput, type IssueTokenInput, type IssuedToken, type Participant, type Room, type RoomState, VideoApiError, type VideoClient, type VideoClientOptions, createVideoClient };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// src/server/errors.ts
|
|
2
|
+
var VideoApiError = class extends Error {
|
|
3
|
+
constructor(code, message, status) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.name = "VideoApiError";
|
|
8
|
+
}
|
|
9
|
+
code;
|
|
10
|
+
status;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/server/client.ts
|
|
14
|
+
function isApiErrorBody(value) {
|
|
15
|
+
return typeof value === "object" && value !== null && "error" in value && typeof value.error?.code === "string";
|
|
16
|
+
}
|
|
17
|
+
function createVideoClient(options) {
|
|
18
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
19
|
+
if (typeof fetchFn !== "function") {
|
|
20
|
+
throw new Error("No hay fetch disponible; p\xE1salo en options.fetch");
|
|
21
|
+
}
|
|
22
|
+
const baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
23
|
+
async function request(method, path, body, parseJson = true) {
|
|
24
|
+
const res = await fetchFn(`${baseUrl}${path}`, {
|
|
25
|
+
method,
|
|
26
|
+
headers: {
|
|
27
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
28
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
29
|
+
},
|
|
30
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
31
|
+
});
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
const payload = await res.json().catch(() => null);
|
|
34
|
+
if (isApiErrorBody(payload)) {
|
|
35
|
+
throw new VideoApiError(payload.error.code, payload.error.message, res.status);
|
|
36
|
+
}
|
|
37
|
+
throw new VideoApiError("HTTP_ERROR", `Error HTTP ${res.status}`, res.status);
|
|
38
|
+
}
|
|
39
|
+
if (!parseJson) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
return await res.json();
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
rooms: {
|
|
46
|
+
create: (input = {}) => request("POST", "/v1/rooms", input),
|
|
47
|
+
get: (roomName) => request("GET", `/v1/rooms/${encodeURIComponent(roomName)}`),
|
|
48
|
+
end: (roomName) => request("DELETE", `/v1/rooms/${encodeURIComponent(roomName)}`, void 0, false)
|
|
49
|
+
},
|
|
50
|
+
tokens: {
|
|
51
|
+
issue: (input) => request("POST", "/v1/tokens", input)
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { VideoApiError, createVideoClient };
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/errors.ts","../../src/server/client.ts"],"names":[],"mappings":";AACO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EACvC,WAAA,CACW,IAAA,EACT,OAAA,EACS,MAAA,EACT;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAJJ,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAGT,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AAAA,EANW,IAAA;AAAA,EAEA,MAAA;AAKb;;;ACoBA,SAAS,eAAe,KAAA,EAAuC;AAC7D,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,IAAA,IACV,WAAW,KAAA,IACX,OAAQ,KAAA,CAAuB,KAAA,EAAO,IAAA,KAAS,QAAA;AAEnD;AAMO,SAAS,kBAAkB,OAAA,EAA0C;AAC1E,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,IAAS,UAAA,CAAW,KAAA;AAC5C,EAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,IAAA,MAAM,IAAI,MAAM,qDAAkD,CAAA;AAAA,EACpE;AACA,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAElD,EAAA,eAAe,OAAA,CACb,MAAA,EACA,IAAA,EACA,IAAA,EACA,YAAY,IAAA,EACA;AACZ,IAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,GAAG,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,MAC7C,MAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,aAAA,EAAe,CAAA,OAAA,EAAU,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA,QACvC,GAAI,IAAA,KAAS,MAAA,GAAY,EAAE,cAAA,EAAgB,kBAAA,KAAuB;AAAC,OACrE;AAAA,MACA,MAAM,IAAA,KAAS,MAAA,GAAY,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI;AAAA,KACnD,CAAA;AAED,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,UAAmB,MAAM,GAAA,CAAI,MAAK,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAC1D,MAAA,IAAI,cAAA,CAAe,OAAO,CAAA,EAAG;AAC3B,QAAA,MAAM,IAAI,cAAc,OAAA,CAAQ,KAAA,CAAM,MAAM,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,GAAA,CAAI,MAAM,CAAA;AAAA,MAC/E;AACA,MAAA,MAAM,IAAI,cAAc,YAAA,EAAc,CAAA,WAAA,EAAc,IAAI,MAAM,CAAA,CAAA,EAAI,IAAI,MAAM,CAAA;AAAA,IAC9E;AAEA,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,EACzB;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ,CAAC,KAAA,GAAQ,OAAO,OAAA,CAAc,MAAA,EAAQ,aAAa,KAAK,CAAA;AAAA,MAChE,GAAA,EAAK,CAAC,QAAA,KAAa,OAAA,CAAmB,OAAO,CAAA,UAAA,EAAa,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,MACxF,GAAA,EAAK,CAAC,QAAA,KACJ,OAAA,CAAc,QAAA,EAAU,CAAA,UAAA,EAAa,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA,EAAI,MAAA,EAAW,KAAK;AAAA,KACzF;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,OAAO,CAAC,KAAA,KAAU,OAAA,CAAqB,MAAA,EAAQ,cAAc,KAAK;AAAA;AACpE,GACF;AACF","file":"index.js","sourcesContent":["/** Error tipado de la API de video. Expone `code` estable y `status` HTTP. */\nexport class VideoApiError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = \"VideoApiError\";\n }\n}\n","import type {\n ApiErrorBody,\n CreateRoomInput,\n IssuedToken,\n IssueTokenInput,\n Room,\n RoomState,\n} from \"../shared/contract\";\nimport { VideoApiError } from \"./errors\";\n\nexport interface VideoClientOptions {\n /** Base URL de la API, p.ej. \"https://api.video.tuempresa.com\". */\n baseUrl: string;\n /** API key del tenant. SOLO en servidores; nunca en el navegador. */\n apiKey: string;\n /** fetch personalizado (tests / runtimes sin fetch global). */\n fetch?: typeof fetch;\n}\n\nexport interface VideoClient {\n rooms: {\n create(input?: CreateRoomInput): Promise<Room>;\n get(roomName: string): Promise<RoomState>;\n end(roomName: string): Promise<void>;\n };\n tokens: {\n issue(input: IssueTokenInput): Promise<IssuedToken>;\n };\n}\n\nfunction isApiErrorBody(value: unknown): value is ApiErrorBody {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"error\" in value &&\n typeof (value as ApiErrorBody).error?.code === \"string\"\n );\n}\n\n/**\n * Cliente backend del servicio de video. Usa la API key del tenant para hablar\n * con la API REST. Pensado para correr SOLO en servidores.\n */\nexport function createVideoClient(options: VideoClientOptions): VideoClient {\n const fetchFn = options.fetch ?? globalThis.fetch;\n if (typeof fetchFn !== \"function\") {\n throw new Error(\"No hay fetch disponible; pásalo en options.fetch\");\n }\n const baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n\n async function request<T>(\n method: string,\n path: string,\n body?: unknown,\n parseJson = true,\n ): Promise<T> {\n const res = await fetchFn(`${baseUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${options.apiKey}`,\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const payload: unknown = await res.json().catch(() => null);\n if (isApiErrorBody(payload)) {\n throw new VideoApiError(payload.error.code, payload.error.message, res.status);\n }\n throw new VideoApiError(\"HTTP_ERROR\", `Error HTTP ${res.status}`, res.status);\n }\n\n if (!parseJson) {\n return undefined as T;\n }\n return (await res.json()) as T;\n }\n\n return {\n rooms: {\n create: (input = {}) => request<Room>(\"POST\", \"/v1/rooms\", input),\n get: (roomName) => request<RoomState>(\"GET\", `/v1/rooms/${encodeURIComponent(roomName)}`),\n end: (roomName) =>\n request<void>(\"DELETE\", `/v1/rooms/${encodeURIComponent(roomName)}`, undefined, false),\n },\n tokens: {\n issue: (input) => request<IssuedToken>(\"POST\", \"/v1/tokens\", input),\n },\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "payfri-video-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SDK del microservicio de video: entry /server (apiKey, backend), /client (token, navegador) y /native (token, React Native)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": ["livekit", "video", "webrtc", "react-native", "expo", "sdk"],
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/Payfri/VideoCallsGateway.git",
|
|
11
|
+
"directory": "packages/sdk"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
"./server": {
|
|
16
|
+
"types": "./dist/server/index.d.ts",
|
|
17
|
+
"import": "./dist/server/index.js",
|
|
18
|
+
"require": "./dist/server/index.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./client": {
|
|
21
|
+
"types": "./dist/client/index.d.ts",
|
|
22
|
+
"import": "./dist/client/index.js",
|
|
23
|
+
"require": "./dist/client/index.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./native": {
|
|
26
|
+
"types": "./dist/native/index.d.ts",
|
|
27
|
+
"import": "./dist/native/index.js",
|
|
28
|
+
"require": "./dist/native/index.cjs"
|
|
29
|
+
},
|
|
30
|
+
"./app.plugin.js": "./app.plugin.cjs"
|
|
31
|
+
},
|
|
32
|
+
"files": ["dist", "app.plugin.cjs"],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsup",
|
|
35
|
+
"dev": "tsup --watch",
|
|
36
|
+
"prepack": "tsup",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"lint": "eslint \"src/**/*.{ts,tsx}\"",
|
|
39
|
+
"test": "vitest run"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"livekit-client": "^2.19.2",
|
|
43
|
+
"react": ">=18",
|
|
44
|
+
"react-native": ">=0.72",
|
|
45
|
+
"react-native-webview": ">=13"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"livekit-client": { "optional": true },
|
|
49
|
+
"react": { "optional": true },
|
|
50
|
+
"react-native": { "optional": true },
|
|
51
|
+
"react-native-webview": { "optional": true }
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@expo/config-plugins": "^9.0.0",
|
|
55
|
+
"@types/react": "^19.2.0",
|
|
56
|
+
"livekit-client": "^2.19.2",
|
|
57
|
+
"react-native-webview": "^13.12.4",
|
|
58
|
+
"tsup": "^8.5.1",
|
|
59
|
+
"typescript": "^5.7.3",
|
|
60
|
+
"vitest": "^4.1.9"
|
|
61
|
+
}
|
|
62
|
+
}
|