@kokimoki/app 0.5.2 → 0.6.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/fields.d.ts +8 -0
- package/dist/fields.js +13 -0
- package/dist/kokimoki-client.d.ts +8 -2
- package/dist/kokimoki-client.js +43 -5
- package/dist/types/events.d.ts +2 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/package.json +2 -1
- package/dist/types/tasks.d.ts +0 -43
- package/dist/types/tasks.js +0 -1
package/dist/fields.d.ts
CHANGED
|
@@ -54,6 +54,14 @@ export declare class IntegerField extends Field<number> {
|
|
|
54
54
|
default: number;
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
export declare class FloatField extends Field<number> {
|
|
58
|
+
value: number;
|
|
59
|
+
constructor(value: number, options?: FieldOptions);
|
|
60
|
+
get schema(): {
|
|
61
|
+
type: string;
|
|
62
|
+
default: number;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
57
65
|
export declare class FormGroup<T extends Record<string, Field<any>>, O extends Record<string, Field<any>>> extends Field<{
|
|
58
66
|
[key in keyof T]: T[key]["value"];
|
|
59
67
|
} & Partial<{
|
package/dist/fields.js
CHANGED
|
@@ -83,6 +83,19 @@ export class IntegerField extends Field {
|
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
+
export class FloatField extends Field {
|
|
87
|
+
value;
|
|
88
|
+
constructor(value, options = defaultFieldOptions) {
|
|
89
|
+
super(options);
|
|
90
|
+
this.value = value;
|
|
91
|
+
}
|
|
92
|
+
get schema() {
|
|
93
|
+
return {
|
|
94
|
+
type: "number",
|
|
95
|
+
default: this.value,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
86
99
|
export class FormGroup extends Field {
|
|
87
100
|
requiredFields;
|
|
88
101
|
optionalFields;
|
|
@@ -6,9 +6,10 @@ import type { KokimokiClientEvents } from "./types/events";
|
|
|
6
6
|
import type { Upload } from "./types/upload";
|
|
7
7
|
import type { Paginated } from "./types/common";
|
|
8
8
|
declare const KokimokiClient_base: new <T>() => TypedEmitter<KokimokiClientEvents<T>>;
|
|
9
|
-
export declare class KokimokiClient<StatelessDataT = any> extends KokimokiClient_base<StatelessDataT> {
|
|
9
|
+
export declare class KokimokiClient<StatelessDataT = any, ClientContextT = any> extends KokimokiClient_base<StatelessDataT> {
|
|
10
10
|
readonly host: string;
|
|
11
11
|
readonly appId: string;
|
|
12
|
+
readonly code: string;
|
|
12
13
|
private _wsUrl;
|
|
13
14
|
private _apiUrl;
|
|
14
15
|
private _id?;
|
|
@@ -16,13 +17,18 @@ export declare class KokimokiClient<StatelessDataT = any> extends KokimokiClient
|
|
|
16
17
|
private _apiHeaders?;
|
|
17
18
|
private _providers;
|
|
18
19
|
private _serverTimeOffset;
|
|
19
|
-
|
|
20
|
+
private _clientContext?;
|
|
21
|
+
private _lastPong;
|
|
22
|
+
private _connected;
|
|
23
|
+
constructor(host: string, appId: string, code?: string);
|
|
20
24
|
get id(): string;
|
|
21
25
|
get token(): string;
|
|
22
26
|
get apiUrl(): string;
|
|
23
27
|
get apiHeaders(): Headers;
|
|
28
|
+
get clientContext(): NonNullable<ClientContextT>;
|
|
24
29
|
connect(): Promise<void>;
|
|
25
30
|
serverTimestamp(): number;
|
|
31
|
+
private receivePong;
|
|
26
32
|
setProvider<T extends DocTypeDescription>(name: string, store: SyncedStore<T>): Promise<void>;
|
|
27
33
|
removeProvider(name: string): void;
|
|
28
34
|
getProvider(name: string): HocuspocusProvider | undefined;
|
package/dist/kokimoki-client.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { HocuspocusProvider } from "@hocuspocus/provider";
|
|
2
2
|
import EventEmitter from "events";
|
|
3
|
+
import { KOKIMOKI_APP_VERSION } from "./version";
|
|
3
4
|
export class KokimokiClient extends EventEmitter {
|
|
4
5
|
host;
|
|
5
6
|
appId;
|
|
7
|
+
code;
|
|
6
8
|
_wsUrl;
|
|
7
9
|
_apiUrl;
|
|
8
10
|
_id;
|
|
@@ -10,10 +12,14 @@ export class KokimokiClient extends EventEmitter {
|
|
|
10
12
|
_apiHeaders;
|
|
11
13
|
_providers = new Map();
|
|
12
14
|
_serverTimeOffset = 0;
|
|
13
|
-
|
|
15
|
+
_clientContext;
|
|
16
|
+
_lastPong = 0;
|
|
17
|
+
_connected = false;
|
|
18
|
+
constructor(host, appId, code = "") {
|
|
14
19
|
super();
|
|
15
20
|
this.host = host;
|
|
16
21
|
this.appId = appId;
|
|
22
|
+
this.code = code;
|
|
17
23
|
// Set up the URLs
|
|
18
24
|
const secure = this.host.indexOf(":") === -1;
|
|
19
25
|
this._wsUrl = `ws${secure ? "s" : ""}://${this.host}`;
|
|
@@ -43,23 +49,30 @@ export class KokimokiClient extends EventEmitter {
|
|
|
43
49
|
}
|
|
44
50
|
return this._apiHeaders;
|
|
45
51
|
}
|
|
52
|
+
get clientContext() {
|
|
53
|
+
if (!this._clientContext) {
|
|
54
|
+
throw new Error("Client not connected");
|
|
55
|
+
}
|
|
56
|
+
return this._clientContext;
|
|
57
|
+
}
|
|
46
58
|
async connect() {
|
|
47
59
|
// Fetch the auth token
|
|
48
60
|
let clientToken = localStorage.getItem("KM_TOKEN");
|
|
49
61
|
const startTime = Date.now();
|
|
50
|
-
const res = await fetch(`${this.apiUrl}/auth/token?appId=${this.appId}`, {
|
|
62
|
+
const res = await fetch(`${this.apiUrl}/auth/token?appId=${this.appId}&code=${this.code}`, {
|
|
51
63
|
method: "GET",
|
|
52
64
|
headers: new Headers({
|
|
53
65
|
"Content-Type": "application/json",
|
|
54
66
|
Authorization: `Bearer ${clientToken}`,
|
|
55
67
|
}),
|
|
56
68
|
});
|
|
57
|
-
const { clientId, appToken, serverTime, token } = await res.json();
|
|
69
|
+
const { clientId, appToken, serverTime, token, clientContext } = await res.json();
|
|
58
70
|
const endTime = Date.now();
|
|
59
71
|
const ping = Math.round((endTime - startTime) / 2);
|
|
60
72
|
this._id = clientId;
|
|
61
73
|
this._token = appToken;
|
|
62
74
|
this._serverTimeOffset = Date.now() - serverTime - ping;
|
|
75
|
+
this._clientContext = clientContext;
|
|
63
76
|
localStorage.setItem("KM_TOKEN", token);
|
|
64
77
|
// Set up the auth headers
|
|
65
78
|
this._apiHeaders = new Headers({
|
|
@@ -71,11 +84,28 @@ export class KokimokiClient extends EventEmitter {
|
|
|
71
84
|
this._providers.forEach((provider) => {
|
|
72
85
|
provider.sendStateless("ping");
|
|
73
86
|
});
|
|
74
|
-
|
|
87
|
+
// Emit disconnected event if no receiver has replied to the ping
|
|
88
|
+
if (this._connected &&
|
|
89
|
+
this._providers.size &&
|
|
90
|
+
this._lastPong < Date.now() - 10000) {
|
|
91
|
+
this.emit("disconnected");
|
|
92
|
+
this._connected = false;
|
|
93
|
+
}
|
|
94
|
+
}, 10000);
|
|
95
|
+
// Emit initial connected event
|
|
96
|
+
this.emit("connected");
|
|
97
|
+
this._connected = true;
|
|
75
98
|
}
|
|
76
99
|
serverTimestamp() {
|
|
77
100
|
return Date.now() - this._serverTimeOffset;
|
|
78
101
|
}
|
|
102
|
+
receivePong() {
|
|
103
|
+
this._lastPong = Date.now();
|
|
104
|
+
if (!this._connected) {
|
|
105
|
+
this.emit("connected");
|
|
106
|
+
this._connected = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
79
109
|
// Realtime database
|
|
80
110
|
async setProvider(name, store) {
|
|
81
111
|
const provider = new HocuspocusProvider({
|
|
@@ -83,10 +113,16 @@ export class KokimokiClient extends EventEmitter {
|
|
|
83
113
|
name: `${this.appId}/${name}`,
|
|
84
114
|
document: store.doc,
|
|
85
115
|
token: this.token,
|
|
116
|
+
parameters: {
|
|
117
|
+
clientVersion: KOKIMOKI_APP_VERSION,
|
|
118
|
+
},
|
|
86
119
|
});
|
|
87
|
-
this._providers.set(name, provider);
|
|
88
120
|
// Handle incoming stateless messages
|
|
89
121
|
provider.on("stateless", (e) => {
|
|
122
|
+
if (e.payload === "pong") {
|
|
123
|
+
this.receivePong();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
90
126
|
const payload = JSON.parse(e.payload);
|
|
91
127
|
this.emit("stateless", name, payload.from, payload.data);
|
|
92
128
|
});
|
|
@@ -98,6 +134,8 @@ export class KokimokiClient extends EventEmitter {
|
|
|
98
134
|
};
|
|
99
135
|
provider.on("synced", handler);
|
|
100
136
|
});
|
|
137
|
+
this.receivePong();
|
|
138
|
+
this._providers.set(name, provider);
|
|
101
139
|
}
|
|
102
140
|
removeProvider(name) {
|
|
103
141
|
const provider = this._providers.get(name);
|
package/dist/types/events.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const KOKIMOKI_APP_VERSION = "0.6.0";
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const KOKIMOKI_APP_VERSION = "0.6.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kokimoki/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Kokimoki app",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
12
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
13
|
+
"prebuild": "node -p \"'export const KOKIMOKI_APP_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > src/version.ts",
|
|
13
14
|
"build": "tsc",
|
|
14
15
|
"dev": "tsc -w",
|
|
15
16
|
"docs": "typedoc src/index.ts"
|
package/dist/types/tasks.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export interface Answer<T = any> {
|
|
2
|
-
value?: T;
|
|
3
|
-
correct: boolean;
|
|
4
|
-
}
|
|
5
|
-
export interface TaskBase {
|
|
6
|
-
id: string;
|
|
7
|
-
text: string;
|
|
8
|
-
points: number;
|
|
9
|
-
metadata?: Record<string, any>;
|
|
10
|
-
}
|
|
11
|
-
export interface TaskOption {
|
|
12
|
-
text: string;
|
|
13
|
-
correct: boolean;
|
|
14
|
-
}
|
|
15
|
-
export interface MultipleChoiceTask extends TaskBase {
|
|
16
|
-
type: "multiple-choice";
|
|
17
|
-
answers: TaskOption[];
|
|
18
|
-
}
|
|
19
|
-
export interface SingleChoiceTask extends TaskBase {
|
|
20
|
-
type: "single-choice";
|
|
21
|
-
answers: TaskOption[];
|
|
22
|
-
}
|
|
23
|
-
export interface TextTask extends TaskBase {
|
|
24
|
-
type: "text";
|
|
25
|
-
answer: string;
|
|
26
|
-
}
|
|
27
|
-
export interface TextSurveyTask extends TaskBase {
|
|
28
|
-
type: "text-survey";
|
|
29
|
-
}
|
|
30
|
-
export interface NumericTask extends TaskBase {
|
|
31
|
-
type: "numeric";
|
|
32
|
-
answer: number;
|
|
33
|
-
}
|
|
34
|
-
export interface PhotoTask extends TaskBase {
|
|
35
|
-
type: "photo";
|
|
36
|
-
}
|
|
37
|
-
export interface VideoTask extends TaskBase {
|
|
38
|
-
type: "video";
|
|
39
|
-
}
|
|
40
|
-
export interface InfoTask extends TaskBase {
|
|
41
|
-
type: "info";
|
|
42
|
-
}
|
|
43
|
-
export type Task = MultipleChoiceTask | SingleChoiceTask | TextTask | NumericTask | TextSurveyTask | PhotoTask | VideoTask | InfoTask;
|
package/dist/types/tasks.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|