@kokimoki/app 0.2.5 → 0.3.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/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/kokimoki-client.d.ts +20 -9
- package/dist/kokimoki-client.js +81 -25
- package/dist/types/common.d.ts +0 -1
- package/dist/types/events.d.ts +0 -3
- package/package.json +1 -1
- package/dist/api/abortMediaUpload.d.ts +0 -2
- package/dist/api/abortMediaUpload.js +0 -12
- package/dist/api/fetchAuth.d.ts +0 -2
- package/dist/api/fetchAuth.js +0 -12
- package/dist/api/getETags.d.ts +0 -2
- package/dist/api/getETags.js +0 -18
- package/dist/api/sendMediaUpload.d.ts +0 -2
- package/dist/api/sendMediaUpload.js +0 -20
- package/dist/api/uploadMedia.d.ts +0 -2
- package/dist/api/uploadMedia.js +0 -14
- package/dist/kokimoki-storage.d.ts +0 -13
- package/dist/kokimoki-storage.js +0 -63
- package/dist/types/api.d.ts +0 -36
- package/dist/types/api.js +0 -1
- package/dist/user-media-handler.d.ts +0 -16
- package/dist/user-media-handler.js +0 -62
- package/dist/utils.d.ts +0 -2
- package/dist/utils.js +0 -19
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -3,27 +3,38 @@ import type TypedEmitter from "typed-emitter";
|
|
|
3
3
|
import type { SyncedStore } from "./synced-store";
|
|
4
4
|
import type { DocTypeDescription } from "@syncedstore/core/types/doc";
|
|
5
5
|
import type { KokimokiClientEvents } from "./types/events";
|
|
6
|
+
import type { Upload } from "./types/upload";
|
|
7
|
+
import type { Paginated } from "./types/common";
|
|
6
8
|
declare const KokimokiClient_base: new <T>() => TypedEmitter<KokimokiClientEvents<T>>;
|
|
7
9
|
export declare class KokimokiClient<StatelessDataT = any> extends KokimokiClient_base<StatelessDataT> {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
private _wsUrl
|
|
11
|
-
private _apiUrl
|
|
10
|
+
readonly host: string;
|
|
11
|
+
readonly appId: string;
|
|
12
|
+
private _wsUrl;
|
|
13
|
+
private _apiUrl;
|
|
12
14
|
private _id?;
|
|
13
15
|
private _token?;
|
|
16
|
+
private _apiHeaders?;
|
|
14
17
|
private _providers;
|
|
15
|
-
|
|
18
|
+
private _serverTimeOffset;
|
|
19
|
+
constructor(host: string, appId: string);
|
|
16
20
|
get id(): string;
|
|
17
|
-
get appId(): string;
|
|
18
21
|
get token(): string;
|
|
19
22
|
get apiUrl(): string;
|
|
20
|
-
|
|
23
|
+
get apiHeaders(): Headers;
|
|
24
|
+
connect(): Promise<void>;
|
|
25
|
+
serverTimestamp(): number;
|
|
21
26
|
setProvider<T extends DocTypeDescription>(name: string, store: SyncedStore<T>): Promise<void>;
|
|
22
27
|
removeProvider(name: string): void;
|
|
23
28
|
getProvider(name: string): HocuspocusProvider | undefined;
|
|
24
|
-
serverTimestamp(): number;
|
|
25
29
|
sendStatelessToClient(room: string, clientId: string, data: StatelessDataT): void;
|
|
26
30
|
sendStatelessToRoom(room: string, data: StatelessDataT, self?: boolean): void;
|
|
31
|
+
private createUpload;
|
|
32
|
+
private uploadChunks;
|
|
33
|
+
private completeUpload;
|
|
34
|
+
upload(name: string, blob: Blob, tags?: string[]): Promise<Upload>;
|
|
35
|
+
listUploads(filter?: {
|
|
36
|
+
clientId?: string;
|
|
37
|
+
mimeTypes?: string[];
|
|
38
|
+
}, skip?: number, limit?: number): Promise<Paginated<Upload>>;
|
|
27
39
|
}
|
|
28
|
-
export declare const kmClient: KokimokiClient<any>;
|
|
29
40
|
export {};
|
package/dist/kokimoki-client.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { HocuspocusProvider } from "@hocuspocus/provider";
|
|
2
2
|
import EventEmitter from "events";
|
|
3
3
|
export class KokimokiClient extends EventEmitter {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
host;
|
|
5
|
+
appId;
|
|
6
6
|
_wsUrl;
|
|
7
7
|
_apiUrl;
|
|
8
8
|
_id;
|
|
9
9
|
_token;
|
|
10
|
+
_apiHeaders;
|
|
10
11
|
_providers = new Map();
|
|
11
|
-
|
|
12
|
+
_serverTimeOffset = 0;
|
|
13
|
+
constructor(host, appId) {
|
|
12
14
|
super();
|
|
15
|
+
this.host = host;
|
|
16
|
+
this.appId = appId;
|
|
17
|
+
// Set up the URLs
|
|
18
|
+
const secure = this.host.indexOf(":") === -1;
|
|
19
|
+
this._wsUrl = `ws${secure ? "s" : ""}://${this.host}`;
|
|
20
|
+
this._apiUrl = `http${secure ? "s" : ""}://${this.host}`;
|
|
13
21
|
}
|
|
14
22
|
get id() {
|
|
15
23
|
if (!this._id) {
|
|
@@ -17,12 +25,6 @@ export class KokimokiClient extends EventEmitter {
|
|
|
17
25
|
}
|
|
18
26
|
return this._id;
|
|
19
27
|
}
|
|
20
|
-
get appId() {
|
|
21
|
-
if (!this._appId) {
|
|
22
|
-
throw new Error("Client not connected");
|
|
23
|
-
}
|
|
24
|
-
return this._appId;
|
|
25
|
-
}
|
|
26
28
|
get token() {
|
|
27
29
|
if (!this._token) {
|
|
28
30
|
throw new Error("Client not connected");
|
|
@@ -35,16 +37,17 @@ export class KokimokiClient extends EventEmitter {
|
|
|
35
37
|
}
|
|
36
38
|
return this._apiUrl;
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
40
|
+
get apiHeaders() {
|
|
41
|
+
if (!this._apiHeaders) {
|
|
42
|
+
throw new Error("Client not connected");
|
|
43
|
+
}
|
|
44
|
+
return this._apiHeaders;
|
|
45
|
+
}
|
|
46
|
+
async connect() {
|
|
44
47
|
// Fetch the auth token
|
|
45
48
|
let clientToken = localStorage.getItem("KM_TOKEN");
|
|
46
49
|
const startTime = Date.now();
|
|
47
|
-
const res = await fetch(`${this.apiUrl}/auth/token?appId=${appId}`, {
|
|
50
|
+
const res = await fetch(`${this.apiUrl}/auth/token?appId=${this.appId}`, {
|
|
48
51
|
method: "GET",
|
|
49
52
|
headers: new Headers({
|
|
50
53
|
"Content-Type": "application/json",
|
|
@@ -56,8 +59,13 @@ export class KokimokiClient extends EventEmitter {
|
|
|
56
59
|
const ping = Math.round((endTime - startTime) / 2);
|
|
57
60
|
this._id = clientId;
|
|
58
61
|
this._token = appToken;
|
|
59
|
-
this.
|
|
62
|
+
this._serverTimeOffset = Date.now() - serverTime - ping;
|
|
60
63
|
localStorage.setItem("KM_TOKEN", token);
|
|
64
|
+
// Set up the auth headers
|
|
65
|
+
this._apiHeaders = new Headers({
|
|
66
|
+
Authorization: `Bearer ${this.token}`,
|
|
67
|
+
"Content-Type": "application/json",
|
|
68
|
+
});
|
|
61
69
|
// Ping interval
|
|
62
70
|
setInterval(() => {
|
|
63
71
|
this._providers.forEach((provider) => {
|
|
@@ -65,13 +73,14 @@ export class KokimokiClient extends EventEmitter {
|
|
|
65
73
|
});
|
|
66
74
|
}, 30000);
|
|
67
75
|
}
|
|
76
|
+
serverTimestamp() {
|
|
77
|
+
return Date.now() - this._serverTimeOffset;
|
|
78
|
+
}
|
|
79
|
+
// Realtime database
|
|
68
80
|
async setProvider(name, store) {
|
|
69
|
-
if (!this._wsUrl || !this._appId) {
|
|
70
|
-
throw new Error("Client not connected");
|
|
71
|
-
}
|
|
72
81
|
const provider = new HocuspocusProvider({
|
|
73
82
|
url: `${this._wsUrl}/connection`,
|
|
74
|
-
name: `${this.
|
|
83
|
+
name: `${this.appId}/${name}`,
|
|
75
84
|
document: store.doc,
|
|
76
85
|
token: this.token,
|
|
77
86
|
});
|
|
@@ -101,9 +110,6 @@ export class KokimokiClient extends EventEmitter {
|
|
|
101
110
|
getProvider(name) {
|
|
102
111
|
return this._providers.get(name);
|
|
103
112
|
}
|
|
104
|
-
serverTimestamp() {
|
|
105
|
-
return Date.now() - this.serverTimeOffset;
|
|
106
|
-
}
|
|
107
113
|
sendStatelessToClient(room, clientId, data) {
|
|
108
114
|
const provider = this._providers.get(room);
|
|
109
115
|
if (!provider) {
|
|
@@ -118,5 +124,55 @@ export class KokimokiClient extends EventEmitter {
|
|
|
118
124
|
}
|
|
119
125
|
provider.sendStateless(JSON.stringify({ data, self }));
|
|
120
126
|
}
|
|
127
|
+
// Storage
|
|
128
|
+
async createUpload(name, blob, tags) {
|
|
129
|
+
const res = await fetch(`${this._apiUrl}/uploads`, {
|
|
130
|
+
method: "POST",
|
|
131
|
+
headers: this.apiHeaders,
|
|
132
|
+
body: JSON.stringify({
|
|
133
|
+
name,
|
|
134
|
+
size: blob.size,
|
|
135
|
+
mimeType: blob.type,
|
|
136
|
+
tags,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
return await res.json();
|
|
140
|
+
}
|
|
141
|
+
async uploadChunks(blob, chunkSize, signedUrls) {
|
|
142
|
+
return await Promise.all(signedUrls.map(async (url, index) => {
|
|
143
|
+
const start = index * chunkSize;
|
|
144
|
+
const end = Math.min(start + chunkSize, blob.size);
|
|
145
|
+
const chunk = blob.slice(start, end);
|
|
146
|
+
const res = await fetch(url, { method: "PUT", body: chunk });
|
|
147
|
+
return JSON.parse(res.headers.get("ETag") || '""');
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
async completeUpload(id, etags) {
|
|
151
|
+
const res = await fetch(`${this._apiUrl}/uploads/${id}`, {
|
|
152
|
+
method: "PUT",
|
|
153
|
+
headers: this.apiHeaders,
|
|
154
|
+
body: JSON.stringify({ etags }),
|
|
155
|
+
});
|
|
156
|
+
return await res.json();
|
|
157
|
+
}
|
|
158
|
+
async upload(name, blob, tags = []) {
|
|
159
|
+
const { id, chunkSize, urls } = await this.createUpload(name, blob, tags);
|
|
160
|
+
const etags = await this.uploadChunks(blob, chunkSize, urls);
|
|
161
|
+
return await this.completeUpload(id, etags);
|
|
162
|
+
}
|
|
163
|
+
async listUploads(filter = {}, skip = 0, limit = 100) {
|
|
164
|
+
const url = new URL("/uploads", this._apiUrl);
|
|
165
|
+
url.searchParams.set("skip", skip.toString());
|
|
166
|
+
url.searchParams.set("limit", limit.toString());
|
|
167
|
+
if (filter.clientId) {
|
|
168
|
+
url.searchParams.set("clientId", filter.clientId);
|
|
169
|
+
}
|
|
170
|
+
if (filter.mimeTypes) {
|
|
171
|
+
url.searchParams.set("mimeTypes", filter.mimeTypes.join());
|
|
172
|
+
}
|
|
173
|
+
const res = await fetch(url.href, {
|
|
174
|
+
headers: this.apiHeaders,
|
|
175
|
+
});
|
|
176
|
+
return await res.json();
|
|
177
|
+
}
|
|
121
178
|
}
|
|
122
|
-
export const kmClient = new KokimokiClient();
|
package/dist/types/common.d.ts
CHANGED
package/dist/types/events.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { getHeaders } from "../utils";
|
|
2
|
-
export async function abortMediaUpload(id, { apiUrl, appToken, signal }) {
|
|
3
|
-
const res = await fetch(`${apiUrl}/upload/${id}`, {
|
|
4
|
-
method: "DELETE",
|
|
5
|
-
headers: getHeaders(appToken),
|
|
6
|
-
signal,
|
|
7
|
-
});
|
|
8
|
-
// TODO: Improve error handling
|
|
9
|
-
if (res.status !== 200) {
|
|
10
|
-
throw await res.json();
|
|
11
|
-
}
|
|
12
|
-
}
|
package/dist/api/fetchAuth.d.ts
DELETED
package/dist/api/fetchAuth.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { getHeaders } from "../utils";
|
|
2
|
-
export async function fetchAuth({ apiUrl, clientToken, appId, }) {
|
|
3
|
-
const res = await fetch(`${apiUrl}/auth/token?appId=${appId}`, {
|
|
4
|
-
method: "GET",
|
|
5
|
-
headers: getHeaders(clientToken),
|
|
6
|
-
});
|
|
7
|
-
// TODO: Improve error handling
|
|
8
|
-
if (res.status !== 200) {
|
|
9
|
-
throw await res.json();
|
|
10
|
-
}
|
|
11
|
-
return await res.json();
|
|
12
|
-
}
|
package/dist/api/getETags.d.ts
DELETED
package/dist/api/getETags.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// TODO: Improve method below
|
|
2
|
-
export async function getETags(blob, { urls, chunkSize }) {
|
|
3
|
-
const uploadData = [];
|
|
4
|
-
for (let index = 0; index < urls.length; ++index) {
|
|
5
|
-
const url = urls[index];
|
|
6
|
-
uploadData.push({
|
|
7
|
-
url,
|
|
8
|
-
body: index < urls.length - 1
|
|
9
|
-
? blob.slice(index * chunkSize, (index + 1) * chunkSize)
|
|
10
|
-
: blob.slice(index * chunkSize),
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
const responses = await Promise.all(uploadData.map(({ url, body }) => fetch(url, {
|
|
14
|
-
method: "PUT",
|
|
15
|
-
body,
|
|
16
|
-
})));
|
|
17
|
-
return responses.map((response) => JSON.parse(response.headers.get("ETag") || '""'));
|
|
18
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import ObjectId from "bson-objectid";
|
|
2
|
-
import { getHeaders } from "../utils";
|
|
3
|
-
export async function sendMediaUpload(blob, { apiUrl, appToken, signal }) {
|
|
4
|
-
const objectId = new ObjectId().toHexString();
|
|
5
|
-
const res = await fetch(`${apiUrl}/upload`, {
|
|
6
|
-
method: "POST",
|
|
7
|
-
headers: getHeaders(appToken),
|
|
8
|
-
body: JSON.stringify({
|
|
9
|
-
name: objectId,
|
|
10
|
-
size: blob.size,
|
|
11
|
-
mimeType: blob.type,
|
|
12
|
-
}),
|
|
13
|
-
signal,
|
|
14
|
-
});
|
|
15
|
-
// TODO: Improve error handling
|
|
16
|
-
if (res.status !== 200) {
|
|
17
|
-
throw await res.json();
|
|
18
|
-
}
|
|
19
|
-
return await res.json();
|
|
20
|
-
}
|
package/dist/api/uploadMedia.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { getHeaders } from "../utils";
|
|
2
|
-
export async function uploadMedia({ id, etags }, { apiUrl, appToken, signal }) {
|
|
3
|
-
const res = await fetch(`${apiUrl}/upload/${id}`, {
|
|
4
|
-
method: "PUT",
|
|
5
|
-
headers: getHeaders(appToken),
|
|
6
|
-
body: JSON.stringify({ etags }),
|
|
7
|
-
signal,
|
|
8
|
-
});
|
|
9
|
-
// TODO: Improve error handling
|
|
10
|
-
if (res.status !== 200) {
|
|
11
|
-
throw await res.json();
|
|
12
|
-
}
|
|
13
|
-
return await res.json();
|
|
14
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Paginated } from "./types/common";
|
|
2
|
-
import type { Upload } from "./types/upload";
|
|
3
|
-
export declare class KokimokiStorage {
|
|
4
|
-
private createUpload;
|
|
5
|
-
private uploadChunks;
|
|
6
|
-
private completeUpload;
|
|
7
|
-
upload(name: string, blob: Blob, tags?: string[]): Promise<Upload>;
|
|
8
|
-
listUploads(filter?: {
|
|
9
|
-
clientId?: string;
|
|
10
|
-
mimeTypes?: string[];
|
|
11
|
-
}, skip?: number, limit?: number): Promise<Paginated<Upload>>;
|
|
12
|
-
}
|
|
13
|
-
export declare const kmStorage: KokimokiStorage;
|
package/dist/kokimoki-storage.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { kmClient } from "./kokimoki-client";
|
|
2
|
-
export class KokimokiStorage {
|
|
3
|
-
async createUpload(name, blob, tags) {
|
|
4
|
-
const res = await fetch(`${kmClient.apiUrl}/uploads`, {
|
|
5
|
-
method: "POST",
|
|
6
|
-
headers: new Headers({
|
|
7
|
-
Authorization: `Bearer ${kmClient.token}`,
|
|
8
|
-
"Content-Type": "application/json",
|
|
9
|
-
}),
|
|
10
|
-
body: JSON.stringify({
|
|
11
|
-
name,
|
|
12
|
-
size: blob.size,
|
|
13
|
-
mimeType: blob.type,
|
|
14
|
-
tags,
|
|
15
|
-
}),
|
|
16
|
-
});
|
|
17
|
-
return await res.json();
|
|
18
|
-
}
|
|
19
|
-
async uploadChunks(blob, chunkSize, signedUrls) {
|
|
20
|
-
return await Promise.all(signedUrls.map(async (url, index) => {
|
|
21
|
-
const start = index * chunkSize;
|
|
22
|
-
const end = Math.min(start + chunkSize, blob.size);
|
|
23
|
-
const chunk = blob.slice(start, end);
|
|
24
|
-
const res = await fetch(url, { method: "PUT", body: chunk });
|
|
25
|
-
return JSON.parse(res.headers.get("ETag") || '""');
|
|
26
|
-
}));
|
|
27
|
-
}
|
|
28
|
-
async completeUpload(id, etags) {
|
|
29
|
-
const res = await fetch(`${kmClient.apiUrl}/uploads/${id}`, {
|
|
30
|
-
method: "PUT",
|
|
31
|
-
headers: new Headers({
|
|
32
|
-
Authorization: `Bearer ${kmClient.token}`,
|
|
33
|
-
"Content-Type": "application/json",
|
|
34
|
-
}),
|
|
35
|
-
body: JSON.stringify({ etags }),
|
|
36
|
-
});
|
|
37
|
-
return await res.json();
|
|
38
|
-
}
|
|
39
|
-
async upload(name, blob, tags = []) {
|
|
40
|
-
const { id, chunkSize, urls } = await this.createUpload(name, blob, tags);
|
|
41
|
-
const etags = await this.uploadChunks(blob, chunkSize, urls);
|
|
42
|
-
return await this.completeUpload(id, etags);
|
|
43
|
-
}
|
|
44
|
-
async listUploads(filter = {}, skip = 0, limit = 100) {
|
|
45
|
-
const url = new URL("/uploads", kmClient.apiUrl);
|
|
46
|
-
url.searchParams.set("skip", skip.toString());
|
|
47
|
-
url.searchParams.set("limit", limit.toString());
|
|
48
|
-
if (filter.clientId) {
|
|
49
|
-
url.searchParams.set("clientId", filter.clientId);
|
|
50
|
-
}
|
|
51
|
-
if (filter.mimeTypes) {
|
|
52
|
-
url.searchParams.set("mimeTypes", filter.mimeTypes.join());
|
|
53
|
-
}
|
|
54
|
-
const res = await fetch(url.href, {
|
|
55
|
-
headers: new Headers({
|
|
56
|
-
Authorization: `Bearer ${kmClient.token}`,
|
|
57
|
-
"Content-Type": "application/json",
|
|
58
|
-
}),
|
|
59
|
-
});
|
|
60
|
-
return await res.json();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
export const kmStorage = new KokimokiStorage();
|
package/dist/types/api.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export interface SendUploadResponse {
|
|
2
|
-
id: string;
|
|
3
|
-
urls: string[];
|
|
4
|
-
chunkSize: number;
|
|
5
|
-
}
|
|
6
|
-
export interface UploadMediaResponse {
|
|
7
|
-
url: string;
|
|
8
|
-
}
|
|
9
|
-
export interface AuthResponse {
|
|
10
|
-
serverTime: number;
|
|
11
|
-
appToken: string;
|
|
12
|
-
token: string;
|
|
13
|
-
clientId: string;
|
|
14
|
-
}
|
|
15
|
-
export interface MediaUploadData {
|
|
16
|
-
url: string;
|
|
17
|
-
body: Blob;
|
|
18
|
-
}
|
|
19
|
-
export interface FetchParams {
|
|
20
|
-
apiUrl: string;
|
|
21
|
-
appToken: string;
|
|
22
|
-
signal?: AbortSignal;
|
|
23
|
-
}
|
|
24
|
-
export interface AuthFetchParams {
|
|
25
|
-
apiUrl: string;
|
|
26
|
-
clientToken: string | null;
|
|
27
|
-
appId: string;
|
|
28
|
-
}
|
|
29
|
-
export interface UploadMediaRequest {
|
|
30
|
-
etags: string[];
|
|
31
|
-
id: string;
|
|
32
|
-
}
|
|
33
|
-
export interface UploadedMedia {
|
|
34
|
-
id: string;
|
|
35
|
-
url: string;
|
|
36
|
-
}
|
package/dist/types/api.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type TypedEmitter from "typed-emitter";
|
|
2
|
-
import type { UserMediaHandlerEvents } from "./types/events";
|
|
3
|
-
declare const UserMediaHandler_base: new () => TypedEmitter<UserMediaHandlerEvents>;
|
|
4
|
-
export declare class UserMediaHandler extends UserMediaHandler_base {
|
|
5
|
-
private _facingMode;
|
|
6
|
-
private _stream;
|
|
7
|
-
private _mediaRequests;
|
|
8
|
-
requestMediaStream(): void;
|
|
9
|
-
releaseMediaStream(): void;
|
|
10
|
-
private closeMediaStream;
|
|
11
|
-
private updateMediaStream;
|
|
12
|
-
setFacingMode(facingMode: "user" | "environment"): void;
|
|
13
|
-
toggleFacingMode(): void;
|
|
14
|
-
}
|
|
15
|
-
export declare const userMediaHandler: UserMediaHandler;
|
|
16
|
-
export {};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import EventEmitter from "events";
|
|
2
|
-
export class UserMediaHandler extends EventEmitter {
|
|
3
|
-
_facingMode = "environment";
|
|
4
|
-
_stream = null;
|
|
5
|
-
_mediaRequests = 0;
|
|
6
|
-
requestMediaStream() {
|
|
7
|
-
this._mediaRequests++;
|
|
8
|
-
this.updateMediaStream();
|
|
9
|
-
}
|
|
10
|
-
releaseMediaStream() {
|
|
11
|
-
this._mediaRequests--;
|
|
12
|
-
if (this._mediaRequests <= 0) {
|
|
13
|
-
this.closeMediaStream();
|
|
14
|
-
this._mediaRequests = 0;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
closeMediaStream() {
|
|
18
|
-
if (!this._stream) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
this.emit("stream", null, this._facingMode, null);
|
|
22
|
-
this._stream.getTracks().forEach((track) => track.stop());
|
|
23
|
-
this._stream = null;
|
|
24
|
-
}
|
|
25
|
-
async updateMediaStream() {
|
|
26
|
-
this.closeMediaStream();
|
|
27
|
-
try {
|
|
28
|
-
this._stream = await navigator.mediaDevices.getUserMedia({
|
|
29
|
-
video: {
|
|
30
|
-
facingMode: this._facingMode,
|
|
31
|
-
frameRate: { ideal: 24, max: 30 },
|
|
32
|
-
},
|
|
33
|
-
audio: true,
|
|
34
|
-
});
|
|
35
|
-
this.emit("stream", null, this._facingMode, this._stream);
|
|
36
|
-
}
|
|
37
|
-
catch (err) {
|
|
38
|
-
this._stream = null;
|
|
39
|
-
if ((err + "").match(/^NotReadableError/)) {
|
|
40
|
-
await new Promise((resolve) => {
|
|
41
|
-
setTimeout(async () => {
|
|
42
|
-
await this.updateMediaStream();
|
|
43
|
-
resolve();
|
|
44
|
-
}, 1000);
|
|
45
|
-
});
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
this.emit("stream", err + "", this._facingMode, null);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
setFacingMode(facingMode) {
|
|
52
|
-
if (this._facingMode === facingMode) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
this._facingMode = facingMode;
|
|
56
|
-
this.updateMediaStream();
|
|
57
|
-
}
|
|
58
|
-
toggleFacingMode() {
|
|
59
|
-
this.setFacingMode(this._facingMode === "user" ? "environment" : "user");
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
export const userMediaHandler = new UserMediaHandler();
|
package/dist/utils.d.ts
DELETED
package/dist/utils.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export function getHeaders(token) {
|
|
2
|
-
return token
|
|
3
|
-
? new Headers({
|
|
4
|
-
Authorization: `Bearer ${token}`,
|
|
5
|
-
"Content-Type": "application/json",
|
|
6
|
-
})
|
|
7
|
-
: new Headers();
|
|
8
|
-
}
|
|
9
|
-
export function errorMessage(error) {
|
|
10
|
-
if (typeof error === "string")
|
|
11
|
-
return error;
|
|
12
|
-
if (typeof error !== "object" && typeof error !== "function")
|
|
13
|
-
return "Unknown error";
|
|
14
|
-
// TODO: Extend errors check
|
|
15
|
-
if (error instanceof Error) {
|
|
16
|
-
return error.message;
|
|
17
|
-
}
|
|
18
|
-
return "Unknown error";
|
|
19
|
-
}
|