@kokimoki/app 0.1.0 → 0.2.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/index.d.ts +2 -5
- package/dist/index.js +2 -5
- package/dist/kokimoki-client.d.ts +5 -4
- package/dist/kokimoki-client.js +22 -29
- package/dist/kokimoki-storage.d.ts +13 -0
- package/dist/kokimoki-storage.js +63 -0
- package/dist/types/common.d.ts +4 -0
- package/dist/types/upload.d.ts +12 -0
- package/dist/types/upload.js +1 -0
- package/dist/user-media-handler.d.ts +1 -0
- package/dist/user-media-handler.js +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { KokimokiClient } from "./kokimoki-client";
|
|
2
|
-
import { UserMediaHandler } from "./user-media-handler";
|
|
3
|
-
export * from "./types/api";
|
|
4
1
|
export * from "./types/tasks";
|
|
5
2
|
export * from "./types/common";
|
|
6
3
|
export * from "./types/events";
|
|
4
|
+
export * from "./types/upload";
|
|
7
5
|
export * from "./fields";
|
|
8
6
|
export * from "./kokimoki-client";
|
|
9
7
|
export * from "./synced-store";
|
|
10
|
-
export
|
|
11
|
-
export declare const userMediaHandler: UserMediaHandler;
|
|
8
|
+
export * from "./user-media-handler";
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { KokimokiClient } from "./kokimoki-client";
|
|
2
|
-
import { UserMediaHandler } from "./user-media-handler";
|
|
3
|
-
export * from "./types/api";
|
|
4
1
|
export * from "./types/tasks";
|
|
5
2
|
export * from "./types/common";
|
|
6
3
|
export * from "./types/events";
|
|
4
|
+
export * from "./types/upload";
|
|
7
5
|
export * from "./fields";
|
|
8
6
|
export * from "./kokimoki-client";
|
|
9
7
|
export * from "./synced-store";
|
|
10
|
-
export
|
|
11
|
-
export const userMediaHandler = new UserMediaHandler();
|
|
8
|
+
export * from "./user-media-handler";
|
|
@@ -2,7 +2,6 @@ import { HocuspocusProvider } from "@hocuspocus/provider";
|
|
|
2
2
|
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
|
-
import type { UploadedMedia } from "./types/api";
|
|
6
5
|
import type { KokimokiClientEvents } from "./types/events";
|
|
7
6
|
declare const KokimokiClient_base: new <T>() => TypedEmitter<KokimokiClientEvents<T>>;
|
|
8
7
|
export declare class KokimokiClient<StatelessDataT = any> extends KokimokiClient_base<StatelessDataT> {
|
|
@@ -10,12 +9,14 @@ export declare class KokimokiClient<StatelessDataT = any> extends KokimokiClient
|
|
|
10
9
|
private _appId?;
|
|
11
10
|
private _wsUrl?;
|
|
12
11
|
private _apiUrl?;
|
|
13
|
-
private _id
|
|
14
|
-
private _token
|
|
12
|
+
private _id?;
|
|
13
|
+
private _token?;
|
|
15
14
|
private _providers;
|
|
16
15
|
constructor();
|
|
17
16
|
get id(): string;
|
|
17
|
+
get appId(): string;
|
|
18
18
|
get token(): string;
|
|
19
|
+
get apiUrl(): string;
|
|
19
20
|
connect(host: string, appId: string): Promise<void>;
|
|
20
21
|
setProvider<T extends DocTypeDescription>(name: string, store: SyncedStore<T>): Promise<void>;
|
|
21
22
|
removeProvider(name: string): void;
|
|
@@ -23,6 +24,6 @@ export declare class KokimokiClient<StatelessDataT = any> extends KokimokiClient
|
|
|
23
24
|
serverTimestamp(): number;
|
|
24
25
|
sendStatelessToClient(room: string, clientId: string, data: StatelessDataT): void;
|
|
25
26
|
sendStatelessToRoom(room: string, data: StatelessDataT, self?: boolean): void;
|
|
26
|
-
mediaUpload(blob: Blob): Promise<UploadedMedia>;
|
|
27
27
|
}
|
|
28
|
+
export declare const kmClient: KokimokiClient<any>;
|
|
28
29
|
export {};
|
package/dist/kokimoki-client.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { HocuspocusProvider } from "@hocuspocus/provider";
|
|
2
2
|
import EventEmitter from "events";
|
|
3
|
-
import { sendMediaUpload } from "./api/sendMediaUpload";
|
|
4
|
-
import { getETags } from "./api/getETags";
|
|
5
|
-
import { uploadMedia } from "./api/uploadMedia";
|
|
6
|
-
import { errorMessage } from "./utils";
|
|
7
|
-
import { fetchAuth } from "./api/fetchAuth";
|
|
8
3
|
export class KokimokiClient extends EventEmitter {
|
|
9
4
|
serverTimeOffset = 0;
|
|
10
5
|
_appId;
|
|
11
6
|
_wsUrl;
|
|
12
7
|
_apiUrl;
|
|
13
|
-
_id
|
|
14
|
-
_token
|
|
8
|
+
_id;
|
|
9
|
+
_token;
|
|
15
10
|
_providers = new Map();
|
|
16
11
|
constructor() {
|
|
17
12
|
super();
|
|
@@ -22,12 +17,24 @@ export class KokimokiClient extends EventEmitter {
|
|
|
22
17
|
}
|
|
23
18
|
return this._id;
|
|
24
19
|
}
|
|
20
|
+
get appId() {
|
|
21
|
+
if (!this._appId) {
|
|
22
|
+
throw new Error("Client not connected");
|
|
23
|
+
}
|
|
24
|
+
return this._appId;
|
|
25
|
+
}
|
|
25
26
|
get token() {
|
|
26
27
|
if (!this._token) {
|
|
27
28
|
throw new Error("Client not connected");
|
|
28
29
|
}
|
|
29
30
|
return this._token;
|
|
30
31
|
}
|
|
32
|
+
get apiUrl() {
|
|
33
|
+
if (!this._apiUrl) {
|
|
34
|
+
throw new Error("Client not connected");
|
|
35
|
+
}
|
|
36
|
+
return this._apiUrl;
|
|
37
|
+
}
|
|
31
38
|
async connect(host, appId) {
|
|
32
39
|
this._appId = appId;
|
|
33
40
|
// Set up the URLs
|
|
@@ -37,11 +44,14 @@ export class KokimokiClient extends EventEmitter {
|
|
|
37
44
|
// Fetch the auth token
|
|
38
45
|
let clientToken = localStorage.getItem("KM_TOKEN");
|
|
39
46
|
const startTime = Date.now();
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
const res = await fetch(`${this.apiUrl}/auth/token?appId=${appId}`, {
|
|
48
|
+
method: "GET",
|
|
49
|
+
headers: new Headers({
|
|
50
|
+
"Content-Type": "application/json",
|
|
51
|
+
Authorization: `Bearer ${clientToken}`,
|
|
52
|
+
}),
|
|
44
53
|
});
|
|
54
|
+
const { clientId, appToken, serverTime, token } = await res.json();
|
|
45
55
|
const endTime = Date.now();
|
|
46
56
|
const ping = Math.round((endTime - startTime) / 2);
|
|
47
57
|
this._id = clientId;
|
|
@@ -102,22 +112,5 @@ export class KokimokiClient extends EventEmitter {
|
|
|
102
112
|
}
|
|
103
113
|
provider.sendStateless(JSON.stringify({ data, self }));
|
|
104
114
|
}
|
|
105
|
-
async mediaUpload(blob) {
|
|
106
|
-
if (!this._apiUrl) {
|
|
107
|
-
throw new Error("Client not connected");
|
|
108
|
-
}
|
|
109
|
-
try {
|
|
110
|
-
const uploadData = await sendMediaUpload(blob, {
|
|
111
|
-
apiUrl: this._apiUrl,
|
|
112
|
-
appToken: this.token,
|
|
113
|
-
});
|
|
114
|
-
const { id } = uploadData;
|
|
115
|
-
const etags = await getETags(blob, uploadData);
|
|
116
|
-
const { url } = await uploadMedia({ id, etags }, { apiUrl: this._apiUrl, appToken: this.token });
|
|
117
|
-
return { url, id };
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
throw new Error(`Error while uploading media: ${errorMessage(error)}`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
115
|
}
|
|
116
|
+
export const kmClient = new KokimokiClient();
|
|
@@ -0,0 +1,13 @@
|
|
|
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;
|
|
@@ -0,0 +1,63 @@
|
|
|
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/common.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|