@awesomate/sdk 0.17.0 → 0.18.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 +6 -4
- package/dist/index.js +59 -18
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* Docs: https://hub.awesomate.ai/docs/sdk/
|
|
25
25
|
*/
|
|
26
26
|
/** This package's version, sent to the hub with every server call. */
|
|
27
|
-
export declare const VERSION = "0.
|
|
27
|
+
export declare const VERSION = "0.18.1";
|
|
28
28
|
/** Augmented by the generated awesomate.d.ts, so each kind's rows are typed. */
|
|
29
29
|
export interface Kinds {
|
|
30
30
|
}
|
|
@@ -290,7 +290,7 @@ export declare class AwesomateClient {
|
|
|
290
290
|
move: (from: string, to: string) => Promise<FileEntry>;
|
|
291
291
|
/** Move a file from private/ or temp/ to the same place under public/, and answer its public_url. Anyone with the address can open it. */
|
|
292
292
|
makePublic: (path: string) => Promise<FileEntry>;
|
|
293
|
-
/** Move a file out of public/ into private/. Its public address stops serving it
|
|
293
|
+
/** Move a file out of public/ into private/. Its public address stops serving it within seconds (a browser that already opened it may keep its own copy for a while). */
|
|
294
294
|
makePrivate: (path: string) => Promise<FileEntry>;
|
|
295
295
|
/** Move to the trash. Not erased, and no longer counted toward the Files space. */
|
|
296
296
|
remove: (path: string) => Promise<{
|
|
@@ -830,7 +830,7 @@ export interface HereHandle {
|
|
|
830
830
|
* stopped (on send or blur). Without another call, typing ends on its own after a few seconds.
|
|
831
831
|
*/
|
|
832
832
|
typing(on: boolean): void;
|
|
833
|
-
/** Close the record: the others stop seeing this person on it. */
|
|
833
|
+
/** Close the record: the others stop seeing this person on it once every part of the page that opened it has left. */
|
|
834
834
|
leave(): void;
|
|
835
835
|
}
|
|
836
836
|
/** What live() calls. */
|
|
@@ -1007,7 +1007,9 @@ export declare class AwesomateAppClient {
|
|
|
1007
1007
|
* Open a record (a job's conversation) for who-is-here: onPeople gets everyone else who has it
|
|
1008
1008
|
* open with their tab in front, and who is typing, at first and on every change; the app's
|
|
1009
1009
|
* assistant appears while it writes a reply. The hub checks this person may read the record, and
|
|
1010
|
-
* keeps checking; onError hears a refusal. Shares the one live connection.
|
|
1010
|
+
* keeps checking; onError hears a refusal. Shares the one live connection. Two parts of a page (a
|
|
1011
|
+
* thread and a sidebar) can open the same record: each hears onPeople, and it stays open until both
|
|
1012
|
+
* have left. Returns typing() and leave().
|
|
1011
1013
|
*/
|
|
1012
1014
|
here(recordId: string, onPeople: (people: HerePerson[]) => void, onError?: (err: AwesomateError) => void): HereHandle;
|
|
1013
1015
|
}
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* Docs: https://hub.awesomate.ai/docs/sdk/
|
|
25
25
|
*/
|
|
26
26
|
/** This package's version, sent to the hub with every server call. */
|
|
27
|
-
export const VERSION = '0.
|
|
27
|
+
export const VERSION = '0.18.1';
|
|
28
28
|
const DEFAULT_BASE = 'https://hub.awesomate.ai';
|
|
29
29
|
const ERROR_CODES = ['unauthenticated', 'forbidden', 'not_found', 'validation', 'consent_blocked', 'rate_limited', 'conflict', 'unavailable'];
|
|
30
30
|
/**
|
|
@@ -220,7 +220,7 @@ export class AwesomateClient {
|
|
|
220
220
|
throw new AwesomateError('validation', 'Name a file inside the folder.', 0, 'path');
|
|
221
221
|
return this.files.move(path, `public/${rest.join('/')}`);
|
|
222
222
|
},
|
|
223
|
-
/** Move a file out of public/ into private/. Its public address stops serving it
|
|
223
|
+
/** Move a file out of public/ into private/. Its public address stops serving it within seconds (a browser that already opened it may keep its own copy for a while). */
|
|
224
224
|
makePrivate: async (path) => {
|
|
225
225
|
const [top, ...rest] = path.replace(/^\/+/, '').split('/');
|
|
226
226
|
if (top !== 'public' || !rest.length)
|
|
@@ -799,7 +799,9 @@ export class AwesomateAppClient {
|
|
|
799
799
|
* Open a record (a job's conversation) for who-is-here: onPeople gets everyone else who has it
|
|
800
800
|
* open with their tab in front, and who is typing, at first and on every change; the app's
|
|
801
801
|
* assistant appears while it writes a reply. The hub checks this person may read the record, and
|
|
802
|
-
* keeps checking; onError hears a refusal. Shares the one live connection.
|
|
802
|
+
* keeps checking; onError hears a refusal. Shares the one live connection. Two parts of a page (a
|
|
803
|
+
* thread and a sidebar) can open the same record: each hears onPeople, and it stays open until both
|
|
804
|
+
* have left. Returns typing() and leave().
|
|
803
805
|
*/
|
|
804
806
|
here(recordId, onPeople, onError) {
|
|
805
807
|
return this.liveSocket().join(recordId, onPeople, onError);
|
|
@@ -842,32 +844,57 @@ class LiveSocket {
|
|
|
842
844
|
if (this.ready && typeof d?.visibilityState === 'string')
|
|
843
845
|
this.send({ type: 'presence', visible: d.visibilityState === 'visible' });
|
|
844
846
|
}
|
|
845
|
-
/**
|
|
847
|
+
/**
|
|
848
|
+
* Records open with here(), one per record id however many parts of the page opened it: the hub
|
|
849
|
+
* hears `here on` once and `here off` when the last of them leaves, and every one of them gets
|
|
850
|
+
* onPeople. Typing is the person's, so one resend clock per record, shared by them all.
|
|
851
|
+
*/
|
|
846
852
|
rooms = new Map();
|
|
847
853
|
get wanted() {
|
|
848
854
|
return this.entries.size > 0 || this.rooms.size > 0;
|
|
849
855
|
}
|
|
850
856
|
join(id, onPeople, onError) {
|
|
851
|
-
const
|
|
852
|
-
this.rooms.
|
|
853
|
-
if (
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
+
const listener = { onPeople, onError };
|
|
858
|
+
let room = this.rooms.get(id);
|
|
859
|
+
if (room) {
|
|
860
|
+
room.listeners.add(listener);
|
|
861
|
+
// Already open: the hub sends nothing new for a second join, so hand over who it last said was there.
|
|
862
|
+
const people = room.people;
|
|
863
|
+
if (people)
|
|
864
|
+
queueMicrotask(() => { if (this.rooms.get(id)?.listeners.has(listener))
|
|
865
|
+
onPeople(people); });
|
|
866
|
+
}
|
|
867
|
+
else {
|
|
868
|
+
room = { listeners: new Set([listener]), typingSentAt: 0, people: null };
|
|
869
|
+
this.rooms.set(id, room);
|
|
870
|
+
if (this.ready)
|
|
871
|
+
this.send({ type: 'here', id, on: true });
|
|
872
|
+
else if (!this.ws && !this.connecting)
|
|
873
|
+
void this.connect();
|
|
874
|
+
}
|
|
875
|
+
const open = () => {
|
|
876
|
+
const r = this.rooms.get(id);
|
|
877
|
+
return r?.listeners.has(listener) ? r : undefined;
|
|
878
|
+
};
|
|
857
879
|
return {
|
|
858
880
|
typing: (on) => {
|
|
859
|
-
|
|
881
|
+
const r = open();
|
|
882
|
+
if (!r || !this.ready)
|
|
860
883
|
return;
|
|
861
884
|
const now = Date.now();
|
|
862
|
-
if (on && now -
|
|
885
|
+
if (on && now - r.typingSentAt < TYPING_RESEND_MS)
|
|
863
886
|
return;
|
|
864
|
-
if (!on && !
|
|
887
|
+
if (!on && !r.typingSentAt)
|
|
865
888
|
return;
|
|
866
|
-
|
|
889
|
+
r.typingSentAt = on ? now : 0;
|
|
867
890
|
this.send({ type: 'typing', id, on });
|
|
868
891
|
},
|
|
869
892
|
leave: () => {
|
|
870
|
-
|
|
893
|
+
const r = open();
|
|
894
|
+
if (!r)
|
|
895
|
+
return;
|
|
896
|
+
r.listeners.delete(listener);
|
|
897
|
+
if (r.listeners.size)
|
|
871
898
|
return;
|
|
872
899
|
this.rooms.delete(id);
|
|
873
900
|
if (this.ready)
|
|
@@ -948,7 +975,13 @@ class LiveSocket {
|
|
|
948
975
|
return;
|
|
949
976
|
}
|
|
950
977
|
if (f.type === 'people' && typeof f.id === 'string') {
|
|
951
|
-
this.rooms.get(f.id)
|
|
978
|
+
const room = this.rooms.get(f.id);
|
|
979
|
+
if (!room)
|
|
980
|
+
return;
|
|
981
|
+
const people = Array.isArray(f.people) ? f.people : [];
|
|
982
|
+
room.people = people;
|
|
983
|
+
for (const l of [...room.listeners])
|
|
984
|
+
l.onPeople(people);
|
|
952
985
|
return;
|
|
953
986
|
}
|
|
954
987
|
if (f.type === 'error' && typeof f.id === 'string' && f.id.startsWith('here:')) {
|
|
@@ -958,7 +991,9 @@ class LiveSocket {
|
|
|
958
991
|
return;
|
|
959
992
|
this.rooms.delete(id);
|
|
960
993
|
const code = ERROR_CODES.includes(String(f.code)) ? f.code : 'unavailable';
|
|
961
|
-
|
|
994
|
+
const err = new AwesomateError(code, String(f.message ?? 'Refused.'), 0, undefined, String(f.code));
|
|
995
|
+
for (const l of room.listeners)
|
|
996
|
+
l.onError?.(err);
|
|
962
997
|
if (!this.wanted)
|
|
963
998
|
this.shut();
|
|
964
999
|
return;
|
|
@@ -1013,6 +1048,8 @@ class LiveSocket {
|
|
|
1013
1048
|
if (this.retry)
|
|
1014
1049
|
clearTimeout(this.retry);
|
|
1015
1050
|
this.pinger = this.retry = null;
|
|
1051
|
+
for (const room of this.rooms.values())
|
|
1052
|
+
room.people = null;
|
|
1016
1053
|
if (ws && ws.readyState <= 1) {
|
|
1017
1054
|
try {
|
|
1018
1055
|
ws.send(JSON.stringify({ type: 'bye' }));
|
|
@@ -1039,6 +1076,9 @@ class LiveSocket {
|
|
|
1039
1076
|
if (this.pinger)
|
|
1040
1077
|
clearInterval(this.pinger);
|
|
1041
1078
|
this.pinger = null;
|
|
1079
|
+
// Who was there is the old connection's word: a part opening a record now waits for the new one.
|
|
1080
|
+
for (const room of this.rooms.values())
|
|
1081
|
+
room.people = null;
|
|
1042
1082
|
if (this.stopped || !this.wanted)
|
|
1043
1083
|
return;
|
|
1044
1084
|
if (code === 4401) {
|
|
@@ -1060,7 +1100,8 @@ class LiveSocket {
|
|
|
1060
1100
|
for (const e of all)
|
|
1061
1101
|
e.handlers.onError?.(err);
|
|
1062
1102
|
for (const r of rooms)
|
|
1063
|
-
r.
|
|
1103
|
+
for (const l of r.listeners)
|
|
1104
|
+
l.onError?.(err);
|
|
1064
1105
|
this.shut();
|
|
1065
1106
|
}
|
|
1066
1107
|
shut() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awesomate/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.1",
|
|
4
4
|
"description": "Your own Awesomate data from Node and the browser: query contacts and app data with generated types, and sign your app's own users in",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|