@proappstore/sdk 1.16.5 → 1.16.7
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/auth.d.ts +75 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +223 -0
- package/dist/auth.js.map +1 -0
- package/dist/base-types.d.ts +22 -0
- package/dist/base-types.d.ts.map +1 -0
- package/dist/base-types.js +2 -0
- package/dist/base-types.js.map +1 -0
- package/dist/counters.d.ts +21 -0
- package/dist/counters.d.ts.map +1 -0
- package/dist/counters.js +57 -0
- package/dist/counters.js.map +1 -0
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.d.ts.map +1 -1
- package/dist/index.d.ts +23 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -8
- package/dist/index.js.map +1 -1
- package/dist/kv.d.ts +30 -0
- package/dist/kv.d.ts.map +1 -0
- package/dist/kv.js +123 -0
- package/dist/kv.js.map +1 -0
- package/dist/roles.d.ts +53 -0
- package/dist/roles.d.ts.map +1 -0
- package/dist/roles.js +121 -0
- package/dist/roles.js.map +1 -0
- package/dist/rooms.d.ts +68 -0
- package/dist/rooms.d.ts.map +1 -0
- package/dist/rooms.js +177 -0
- package/dist/rooms.js.map +1 -0
- package/dist/ui-primitives.d.ts +1 -1
- package/dist/ui-primitives.d.ts.map +1 -1
- package/package.json +1 -4
package/dist/kv.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Auth } from './auth.js';
|
|
2
|
+
export declare class Kv {
|
|
3
|
+
private readonly appId;
|
|
4
|
+
private readonly apiBase;
|
|
5
|
+
private readonly auth;
|
|
6
|
+
constructor(appId: string, apiBase: string, auth: Auth);
|
|
7
|
+
/** List all keys for this user. Optionally filter by prefix. */
|
|
8
|
+
list(opts?: {
|
|
9
|
+
prefix?: string;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}): Promise<string[]>;
|
|
12
|
+
/** Fetch multiple keys in parallel. Returns a Map of found key-value pairs (skips failures and missing keys). */
|
|
13
|
+
getMany<T = unknown>(keys: string[], opts?: {
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}): Promise<Map<string, T>>;
|
|
16
|
+
/** Get a value by key. Returns null if not found. */
|
|
17
|
+
get<T = unknown>(key: string, opts?: {
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}): Promise<T | null>;
|
|
20
|
+
/** Store a JSON-serializable value under the given key. */
|
|
21
|
+
set<T = unknown>(key: string, value: T, opts?: {
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
/** Delete a key. No-op if the key doesn't exist. */
|
|
25
|
+
delete(key: string, opts?: {
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
}): Promise<void>;
|
|
28
|
+
private request;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=kv.d.ts.map
|
package/dist/kv.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyBtC,qBAAa,EAAE;IAEX,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI;IAG7B,gEAAgE;IAC1D,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoB/E,iHAAiH;IAC3G,OAAO,CAAC,CAAC,GAAG,OAAO,EACvB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAiB1B,qDAAqD;IAC/C,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAQvF,2DAA2D;IACrD,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAc7F,oDAAoD;IAC9C,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAQ3D,OAAO;CAuBtB"}
|
package/dist/kv.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-user key-value store, scoped to (appId, userId).
|
|
3
|
+
*
|
|
4
|
+
* Limits (enforced server-side):
|
|
5
|
+
* - max 1MB total per user
|
|
6
|
+
* - max 100 keys per user
|
|
7
|
+
* - max 64KB per value
|
|
8
|
+
*
|
|
9
|
+
* Keys are non-empty strings ≤ 128 chars. We validate client-side so the
|
|
10
|
+
* server doesn't have to deal with edge-case URLs like `/kv/` or absurdly
|
|
11
|
+
* long path segments.
|
|
12
|
+
*/
|
|
13
|
+
const MAX_KEY_LENGTH = 128;
|
|
14
|
+
function assertValidKey(key) {
|
|
15
|
+
if (typeof key !== 'string' || key.length === 0) {
|
|
16
|
+
throw new Error('kv key must be a non-empty string.');
|
|
17
|
+
}
|
|
18
|
+
if (key.length > MAX_KEY_LENGTH) {
|
|
19
|
+
throw new Error(`kv key exceeds ${MAX_KEY_LENGTH} chars.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class Kv {
|
|
23
|
+
appId;
|
|
24
|
+
apiBase;
|
|
25
|
+
auth;
|
|
26
|
+
constructor(appId, apiBase, auth) {
|
|
27
|
+
this.appId = appId;
|
|
28
|
+
this.apiBase = apiBase;
|
|
29
|
+
this.auth = auth;
|
|
30
|
+
}
|
|
31
|
+
/** List all keys for this user. Optionally filter by prefix. */
|
|
32
|
+
async list(opts) {
|
|
33
|
+
const token = this.auth.token;
|
|
34
|
+
if (!token)
|
|
35
|
+
throw new Error('Not signed in.');
|
|
36
|
+
const url = new URL(`/v1/apps/${encodeURIComponent(this.appId)}/kv`, this.apiBase);
|
|
37
|
+
if (opts?.prefix)
|
|
38
|
+
url.searchParams.set('prefix', opts.prefix);
|
|
39
|
+
const listResponse = await fetch(url, {
|
|
40
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
41
|
+
...(opts?.signal && { signal: opts.signal }),
|
|
42
|
+
});
|
|
43
|
+
if (listResponse.status === 401) {
|
|
44
|
+
this.auth.handleUnauthorized();
|
|
45
|
+
throw new Error('Not signed in.');
|
|
46
|
+
}
|
|
47
|
+
if (!listResponse.ok)
|
|
48
|
+
throw new Error(`kv.list failed: ${listResponse.status}`);
|
|
49
|
+
let keys = (await listResponse.json());
|
|
50
|
+
// Client-side prefix filter as fallback if server doesn't support it yet
|
|
51
|
+
if (opts?.prefix)
|
|
52
|
+
keys = keys.filter((k) => k.startsWith(opts.prefix));
|
|
53
|
+
return keys;
|
|
54
|
+
}
|
|
55
|
+
/** Fetch multiple keys in parallel. Returns a Map of found key-value pairs (skips failures and missing keys). */
|
|
56
|
+
async getMany(keys, opts) {
|
|
57
|
+
for (const key of keys)
|
|
58
|
+
assertValidKey(key);
|
|
59
|
+
const results = new Map();
|
|
60
|
+
const settled = await Promise.allSettled(keys.map(async (key) => {
|
|
61
|
+
const stored = await this.get(key, opts);
|
|
62
|
+
if (stored !== null)
|
|
63
|
+
results.set(key, stored);
|
|
64
|
+
}));
|
|
65
|
+
// If ALL requests failed with auth error, re-throw so callers know
|
|
66
|
+
const allFailed = settled.every((s) => s.status === 'rejected');
|
|
67
|
+
if (allFailed && settled.length > 0) {
|
|
68
|
+
throw settled[0].reason;
|
|
69
|
+
}
|
|
70
|
+
return results;
|
|
71
|
+
}
|
|
72
|
+
/** Get a value by key. Returns null if not found. */
|
|
73
|
+
async get(key, opts) {
|
|
74
|
+
assertValidKey(key);
|
|
75
|
+
const getResponse = await this.request('GET', key, undefined, opts?.signal);
|
|
76
|
+
if (getResponse.status === 404)
|
|
77
|
+
return null;
|
|
78
|
+
if (!getResponse.ok)
|
|
79
|
+
throw new Error(`kv.get failed: ${getResponse.status}`);
|
|
80
|
+
return (await getResponse.json());
|
|
81
|
+
}
|
|
82
|
+
/** Store a JSON-serializable value under the given key. */
|
|
83
|
+
async set(key, value, opts) {
|
|
84
|
+
assertValidKey(key);
|
|
85
|
+
// JSON.stringify(undefined) returns undefined, which would store an empty
|
|
86
|
+
// body and break later get() calls. Reject up front instead.
|
|
87
|
+
if (value === undefined) {
|
|
88
|
+
throw new Error('kv.set: value is undefined. Use kv.delete(key) to remove a key.');
|
|
89
|
+
}
|
|
90
|
+
const setResponse = await this.request('PUT', key, JSON.stringify(value), opts?.signal);
|
|
91
|
+
if (!setResponse.ok) {
|
|
92
|
+
const text = await setResponse.text();
|
|
93
|
+
throw new Error(`kv.set failed (${setResponse.status}): ${text}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Delete a key. No-op if the key doesn't exist. */
|
|
97
|
+
async delete(key, opts) {
|
|
98
|
+
assertValidKey(key);
|
|
99
|
+
const deleteResponse = await this.request('DELETE', key, undefined, opts?.signal);
|
|
100
|
+
if (!deleteResponse.ok && deleteResponse.status !== 404) {
|
|
101
|
+
throw new Error(`kv.delete failed: ${deleteResponse.status}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async request(method, key, body, signal) {
|
|
105
|
+
const token = this.auth.token;
|
|
106
|
+
if (!token)
|
|
107
|
+
throw new Error('Not signed in.');
|
|
108
|
+
const url = new URL(`/v1/apps/${encodeURIComponent(this.appId)}/kv/${encodeURIComponent(key)}`, this.apiBase);
|
|
109
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
110
|
+
if (body !== undefined)
|
|
111
|
+
headers['Content-Type'] = 'application/json';
|
|
112
|
+
const init = { method, headers, ...(signal && { signal }) };
|
|
113
|
+
if (body !== undefined)
|
|
114
|
+
init.body = body;
|
|
115
|
+
const kvResponse = await fetch(url, init);
|
|
116
|
+
if (kvResponse.status === 401) {
|
|
117
|
+
this.auth.handleUnauthorized();
|
|
118
|
+
throw new Error('Not signed in.');
|
|
119
|
+
}
|
|
120
|
+
return kvResponse;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=kv.js.map
|
package/dist/kv.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.js","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"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"}
|
package/dist/roles.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
interface AuthLike {
|
|
2
|
+
token: string | null;
|
|
3
|
+
handleUnauthorized(): void;
|
|
4
|
+
}
|
|
5
|
+
export interface RoleAssignment {
|
|
6
|
+
userId: string;
|
|
7
|
+
roleName: string;
|
|
8
|
+
grantedBy: string | null;
|
|
9
|
+
grantedAt: number;
|
|
10
|
+
}
|
|
11
|
+
/** Default roles provided by the platform. Devs can add custom roles. */
|
|
12
|
+
export declare const DEFAULT_ROLES: readonly ["owner", "member", "moderator", "editor", "viewer"];
|
|
13
|
+
export type DefaultRole = (typeof DEFAULT_ROLES)[number];
|
|
14
|
+
/**
|
|
15
|
+
* App-level RBAC — assign, revoke, and check roles for users in your app.
|
|
16
|
+
*
|
|
17
|
+
* Default roles (no configuration needed):
|
|
18
|
+
* owner — auto-assigned to app creator, full control
|
|
19
|
+
* member — basic authenticated access
|
|
20
|
+
* moderator — content moderation, user management
|
|
21
|
+
* editor — CRUD on app data, not settings
|
|
22
|
+
* viewer — read-only access
|
|
23
|
+
*
|
|
24
|
+
* Custom roles: pass any string to assign/revoke/check.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* await app.roles.assign('gh:123', 'moderator')
|
|
28
|
+
* const has = await app.roles.check('moderator')
|
|
29
|
+
* const mods = await app.roles.list('moderator')
|
|
30
|
+
* await app.roles.revoke('gh:123', 'moderator')
|
|
31
|
+
*/
|
|
32
|
+
export declare class Roles {
|
|
33
|
+
private readonly appId;
|
|
34
|
+
private readonly apiBase;
|
|
35
|
+
private readonly auth;
|
|
36
|
+
constructor(appId: string, apiBase: string, auth: AuthLike);
|
|
37
|
+
/** Assign a role to a user. Caller must be app owner or admin. */
|
|
38
|
+
assign(userId: string, role: string): Promise<void>;
|
|
39
|
+
/** Revoke a role from a user. Caller must be app owner or admin. */
|
|
40
|
+
revoke(userId: string, role: string): Promise<void>;
|
|
41
|
+
/** Check if the current user has a specific role in this app. */
|
|
42
|
+
check(role: string): Promise<boolean>;
|
|
43
|
+
/** List all role assignments for this app. Caller must be app owner or admin. */
|
|
44
|
+
listAll(): Promise<RoleAssignment[]>;
|
|
45
|
+
/** List all users with a specific role. Caller must be app owner or admin. */
|
|
46
|
+
list(role: string): Promise<RoleAssignment[]>;
|
|
47
|
+
/** Get the current user's roles in this app. */
|
|
48
|
+
myRoles(): Promise<string[]>;
|
|
49
|
+
private post;
|
|
50
|
+
private del;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=roles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../src/roles.ts"],"names":[],"mappings":"AAAA,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,kBAAkB,IAAI,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yEAAyE;AACzE,eAAO,MAAM,aAAa,+DAAgE,CAAC;AAC3F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,KAAK;IAEd,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ;IAGjC,kEAAkE;IAC5D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD,oEAAoE;IAC9D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD,iEAAiE;IAC3D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAY3C,iFAAiF;IAC3E,OAAO,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAe1C,8EAA8E;IACxE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAKnD,gDAAgD;IAC1C,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAWpB,IAAI;YAkBJ,GAAG;CAiBlB"}
|
package/dist/roles.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/** Default roles provided by the platform. Devs can add custom roles. */
|
|
2
|
+
export const DEFAULT_ROLES = ['owner', 'member', 'moderator', 'editor', 'viewer'];
|
|
3
|
+
/**
|
|
4
|
+
* App-level RBAC — assign, revoke, and check roles for users in your app.
|
|
5
|
+
*
|
|
6
|
+
* Default roles (no configuration needed):
|
|
7
|
+
* owner — auto-assigned to app creator, full control
|
|
8
|
+
* member — basic authenticated access
|
|
9
|
+
* moderator — content moderation, user management
|
|
10
|
+
* editor — CRUD on app data, not settings
|
|
11
|
+
* viewer — read-only access
|
|
12
|
+
*
|
|
13
|
+
* Custom roles: pass any string to assign/revoke/check.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* await app.roles.assign('gh:123', 'moderator')
|
|
17
|
+
* const has = await app.roles.check('moderator')
|
|
18
|
+
* const mods = await app.roles.list('moderator')
|
|
19
|
+
* await app.roles.revoke('gh:123', 'moderator')
|
|
20
|
+
*/
|
|
21
|
+
export class Roles {
|
|
22
|
+
appId;
|
|
23
|
+
apiBase;
|
|
24
|
+
auth;
|
|
25
|
+
constructor(appId, apiBase, auth) {
|
|
26
|
+
this.appId = appId;
|
|
27
|
+
this.apiBase = apiBase;
|
|
28
|
+
this.auth = auth;
|
|
29
|
+
}
|
|
30
|
+
/** Assign a role to a user. Caller must be app owner or admin. */
|
|
31
|
+
async assign(userId, role) {
|
|
32
|
+
await this.post(`/v1/apps/${encodeURIComponent(this.appId)}/roles`, { userId, role });
|
|
33
|
+
}
|
|
34
|
+
/** Revoke a role from a user. Caller must be app owner or admin. */
|
|
35
|
+
async revoke(userId, role) {
|
|
36
|
+
await this.del(`/v1/apps/${encodeURIComponent(this.appId)}/roles`, { userId, role });
|
|
37
|
+
}
|
|
38
|
+
/** Check if the current user has a specific role in this app. */
|
|
39
|
+
async check(role) {
|
|
40
|
+
const token = this.auth.token;
|
|
41
|
+
if (!token)
|
|
42
|
+
return false;
|
|
43
|
+
const res = await fetch(`${this.apiBase}/v1/apps/${encodeURIComponent(this.appId)}/roles/check/${encodeURIComponent(role)}`, { headers: { Authorization: `Bearer ${token}` } });
|
|
44
|
+
if (!res.ok)
|
|
45
|
+
return false;
|
|
46
|
+
const data = (await res.json());
|
|
47
|
+
return data.has;
|
|
48
|
+
}
|
|
49
|
+
/** List all role assignments for this app. Caller must be app owner or admin. */
|
|
50
|
+
async listAll() {
|
|
51
|
+
const token = this.auth.token;
|
|
52
|
+
if (!token)
|
|
53
|
+
throw new Error('Not signed in.');
|
|
54
|
+
const res = await fetch(`${this.apiBase}/v1/apps/${encodeURIComponent(this.appId)}/roles`, {
|
|
55
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
56
|
+
});
|
|
57
|
+
if (res.status === 401) {
|
|
58
|
+
this.auth.handleUnauthorized();
|
|
59
|
+
throw new Error('Not signed in.');
|
|
60
|
+
}
|
|
61
|
+
if (!res.ok)
|
|
62
|
+
throw new Error(`roles.listAll failed: ${res.status}`);
|
|
63
|
+
const data = (await res.json());
|
|
64
|
+
return data.roles;
|
|
65
|
+
}
|
|
66
|
+
/** List all users with a specific role. Caller must be app owner or admin. */
|
|
67
|
+
async list(role) {
|
|
68
|
+
const all = await this.listAll();
|
|
69
|
+
return all.filter((r) => r.roleName === role);
|
|
70
|
+
}
|
|
71
|
+
/** Get the current user's roles in this app. */
|
|
72
|
+
async myRoles() {
|
|
73
|
+
const token = this.auth.token;
|
|
74
|
+
if (!token)
|
|
75
|
+
return [];
|
|
76
|
+
const res = await fetch(`${this.apiBase}/v1/apps/${encodeURIComponent(this.appId)}/roles/me`, {
|
|
77
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok)
|
|
80
|
+
return [];
|
|
81
|
+
const data = (await res.json());
|
|
82
|
+
return data.roles;
|
|
83
|
+
}
|
|
84
|
+
async post(path, body) {
|
|
85
|
+
const token = this.auth.token;
|
|
86
|
+
if (!token)
|
|
87
|
+
throw new Error('Not signed in.');
|
|
88
|
+
const res = await fetch(this.apiBase + path, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
|
91
|
+
body: JSON.stringify(body),
|
|
92
|
+
});
|
|
93
|
+
if (res.status === 401) {
|
|
94
|
+
this.auth.handleUnauthorized();
|
|
95
|
+
throw new Error('Not signed in.');
|
|
96
|
+
}
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
const text = await res.text().catch(() => '');
|
|
99
|
+
throw new Error(`${path} failed: ${res.status} ${text}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async del(path, body) {
|
|
103
|
+
const token = this.auth.token;
|
|
104
|
+
if (!token)
|
|
105
|
+
throw new Error('Not signed in.');
|
|
106
|
+
const res = await fetch(this.apiBase + path, {
|
|
107
|
+
method: 'DELETE',
|
|
108
|
+
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
|
109
|
+
body: JSON.stringify(body),
|
|
110
|
+
});
|
|
111
|
+
if (res.status === 401) {
|
|
112
|
+
this.auth.handleUnauthorized();
|
|
113
|
+
throw new Error('Not signed in.');
|
|
114
|
+
}
|
|
115
|
+
if (!res.ok) {
|
|
116
|
+
const text = await res.text().catch(() => '');
|
|
117
|
+
throw new Error(`${path} failed: ${res.status} ${text}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=roles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../src/roles.ts"],"names":[],"mappings":"AAYA,yEAAyE;AACzE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAG3F;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,KAAK;IAEG;IACA;IACA;IAHnB,YACmB,KAAa,EACb,OAAe,EACf,IAAc;QAFd,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QACf,SAAI,GAAJ,IAAI,CAAU;IAC9B,CAAC;IAEJ,kEAAkE;IAClE,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,IAAY;QACvC,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,IAAY;QACvC,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,iEAAiE;IACjE,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,GAAG,IAAI,CAAC,OAAO,YAAY,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,EACnG,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,EAAE,CAClD,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqB,CAAC;QACpD,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,YAAY,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;YACzF,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;SAC9C,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgC,CAAC;QAC/D,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,gDAAgD;IAChD,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,YAAY,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAC5F,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;QACvD,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAa;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YACjF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,YAAY,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,IAAa;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE;YAC3C,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YACjF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,YAAY,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF"}
|
package/dist/rooms.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Auth } from './auth.js';
|
|
2
|
+
import type { Unsubscribe } from './base-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Light realtime room — Durable-Object-backed WebSocket fan-out.
|
|
5
|
+
*
|
|
6
|
+
* Use cases: cursor presence, low-state multiplayer (Slither-style), chat-light.
|
|
7
|
+
* Not a multiplayer game server. Messages are not persisted.
|
|
8
|
+
*
|
|
9
|
+
* Limits (enforced server-side):
|
|
10
|
+
* - max 32 concurrent peers per room
|
|
11
|
+
* - max 100 messages/sec per peer
|
|
12
|
+
* - max 4KB per message
|
|
13
|
+
* - max 64 active rooms per app (LRU evicts the oldest)
|
|
14
|
+
* - rooms idle for 24h are auto-evicted
|
|
15
|
+
*/
|
|
16
|
+
export interface RoomPeer {
|
|
17
|
+
uid: string;
|
|
18
|
+
login: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RoomMessage<T = unknown> {
|
|
21
|
+
from: RoomPeer;
|
|
22
|
+
data: T;
|
|
23
|
+
at: number;
|
|
24
|
+
}
|
|
25
|
+
export type ConnectionState = 'connecting' | 'open' | 'closed' | 'error';
|
|
26
|
+
export declare class Rooms {
|
|
27
|
+
private readonly appId;
|
|
28
|
+
private readonly apiBase;
|
|
29
|
+
private readonly auth;
|
|
30
|
+
constructor(appId: string, apiBase: string, auth: Auth);
|
|
31
|
+
join(roomId: string): Room;
|
|
32
|
+
}
|
|
33
|
+
export declare class Room {
|
|
34
|
+
private readonly appId;
|
|
35
|
+
private readonly apiBase;
|
|
36
|
+
private readonly auth;
|
|
37
|
+
private readonly roomId;
|
|
38
|
+
private socket;
|
|
39
|
+
private listeners;
|
|
40
|
+
private peerListeners;
|
|
41
|
+
private stateListeners;
|
|
42
|
+
private _peers;
|
|
43
|
+
private connectionState;
|
|
44
|
+
private reconnectAttempt;
|
|
45
|
+
private reconnectTimer;
|
|
46
|
+
private explicitlyClosed;
|
|
47
|
+
/** Enable to log all WebSocket traffic to console. */
|
|
48
|
+
debug: boolean;
|
|
49
|
+
constructor(appId: string, apiBase: string, auth: Auth, roomId: string);
|
|
50
|
+
/** Current connection state. */
|
|
51
|
+
get state(): ConnectionState;
|
|
52
|
+
/** Underlying WebSocket readyState (or -1 if no socket). */
|
|
53
|
+
get socketState(): number;
|
|
54
|
+
/** Number of registered message listeners. */
|
|
55
|
+
get listenerCount(): number;
|
|
56
|
+
/** Current peer list (read-only snapshot). */
|
|
57
|
+
get peers(): RoomPeer[];
|
|
58
|
+
send<T>(data: T): void;
|
|
59
|
+
onMessage<T = unknown>(listener: (msg: RoomMessage<T>) => void): Unsubscribe;
|
|
60
|
+
onPeers(listener: (peers: RoomPeer[]) => void): Unsubscribe;
|
|
61
|
+
onConnectionState(listener: (state: ConnectionState) => void): Unsubscribe;
|
|
62
|
+
/** Permanently close the room. Stops any pending reconnect. */
|
|
63
|
+
close(): void;
|
|
64
|
+
private connect;
|
|
65
|
+
private scheduleReconnect;
|
|
66
|
+
private setState;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=rooms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rooms.d.ts","sourceRoot":"","sources":["../src/rooms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,CAAC,CAAC;IACR,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzE,qBAAa,KAAK;IAEd,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI;IAG7B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAG3B;AAKD,qBAAa,IAAI;IAeb,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAjBzB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,gBAAgB,CAAS;IAEjC,sDAAsD;IACtD,KAAK,UAAS;gBAGK,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM;IAKjC,gCAAgC;IAChC,IAAI,KAAK,IAAI,eAAe,CAE3B;IAED,4DAA4D;IAC5D,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,8CAA8C;IAC9C,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,8CAA8C;IAC9C,IAAI,KAAK,IAAI,QAAQ,EAAE,CAEtB;IAED,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAUtB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,WAAW;IAK5E,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,GAAG,WAAW;IAM3D,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,WAAW;IAM1E,+DAA+D;IAC/D,KAAK,IAAI,IAAI;IAcb,OAAO,CAAC,OAAO;IA8Df,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,QAAQ;CAKjB"}
|
package/dist/rooms.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
export class Rooms {
|
|
2
|
+
appId;
|
|
3
|
+
apiBase;
|
|
4
|
+
auth;
|
|
5
|
+
constructor(appId, apiBase, auth) {
|
|
6
|
+
this.appId = appId;
|
|
7
|
+
this.apiBase = apiBase;
|
|
8
|
+
this.auth = auth;
|
|
9
|
+
}
|
|
10
|
+
join(roomId) {
|
|
11
|
+
return new Room(this.appId, this.apiBase, this.auth, roomId);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const RECONNECT_BASE_MS = 1000;
|
|
15
|
+
const RECONNECT_MAX_MS = 30_000;
|
|
16
|
+
export class Room {
|
|
17
|
+
appId;
|
|
18
|
+
apiBase;
|
|
19
|
+
auth;
|
|
20
|
+
roomId;
|
|
21
|
+
socket = null;
|
|
22
|
+
listeners = new Set();
|
|
23
|
+
peerListeners = new Set();
|
|
24
|
+
stateListeners = new Set();
|
|
25
|
+
_peers = [];
|
|
26
|
+
connectionState = 'connecting';
|
|
27
|
+
reconnectAttempt = 0;
|
|
28
|
+
reconnectTimer = null;
|
|
29
|
+
explicitlyClosed = false;
|
|
30
|
+
/** Enable to log all WebSocket traffic to console. */
|
|
31
|
+
debug = false;
|
|
32
|
+
constructor(appId, apiBase, auth, roomId) {
|
|
33
|
+
this.appId = appId;
|
|
34
|
+
this.apiBase = apiBase;
|
|
35
|
+
this.auth = auth;
|
|
36
|
+
this.roomId = roomId;
|
|
37
|
+
this.connect();
|
|
38
|
+
}
|
|
39
|
+
/** Current connection state. */
|
|
40
|
+
get state() {
|
|
41
|
+
return this.connectionState;
|
|
42
|
+
}
|
|
43
|
+
/** Underlying WebSocket readyState (or -1 if no socket). */
|
|
44
|
+
get socketState() {
|
|
45
|
+
return this.socket?.readyState ?? -1;
|
|
46
|
+
}
|
|
47
|
+
/** Number of registered message listeners. */
|
|
48
|
+
get listenerCount() {
|
|
49
|
+
return this.listeners.size;
|
|
50
|
+
}
|
|
51
|
+
/** Current peer list (read-only snapshot). */
|
|
52
|
+
get peers() {
|
|
53
|
+
return this._peers;
|
|
54
|
+
}
|
|
55
|
+
send(data) {
|
|
56
|
+
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
57
|
+
if (this.debug)
|
|
58
|
+
console.warn('[rooms] send dropped — socket not open', this.connectionState);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const frame = JSON.stringify({ kind: 'msg', data });
|
|
62
|
+
if (this.debug)
|
|
63
|
+
console.log('[rooms] →', frame);
|
|
64
|
+
this.socket.send(frame);
|
|
65
|
+
}
|
|
66
|
+
onMessage(listener) {
|
|
67
|
+
this.listeners.add(listener);
|
|
68
|
+
return () => this.listeners.delete(listener);
|
|
69
|
+
}
|
|
70
|
+
onPeers(listener) {
|
|
71
|
+
this.peerListeners.add(listener);
|
|
72
|
+
listener(this._peers);
|
|
73
|
+
return () => this.peerListeners.delete(listener);
|
|
74
|
+
}
|
|
75
|
+
onConnectionState(listener) {
|
|
76
|
+
this.stateListeners.add(listener);
|
|
77
|
+
listener(this.connectionState);
|
|
78
|
+
return () => this.stateListeners.delete(listener);
|
|
79
|
+
}
|
|
80
|
+
/** Permanently close the room. Stops any pending reconnect. */
|
|
81
|
+
close() {
|
|
82
|
+
this.explicitlyClosed = true;
|
|
83
|
+
if (this.reconnectTimer !== null) {
|
|
84
|
+
clearTimeout(this.reconnectTimer);
|
|
85
|
+
this.reconnectTimer = null;
|
|
86
|
+
}
|
|
87
|
+
this.socket?.close();
|
|
88
|
+
this.socket = null;
|
|
89
|
+
this.setState('closed');
|
|
90
|
+
this.listeners.clear();
|
|
91
|
+
this.peerListeners.clear();
|
|
92
|
+
this.stateListeners.clear();
|
|
93
|
+
}
|
|
94
|
+
connect() {
|
|
95
|
+
const token = this.auth.token;
|
|
96
|
+
if (!token) {
|
|
97
|
+
// Auth state may have changed (sign-out). Stop trying.
|
|
98
|
+
this.setState('closed');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.setState('connecting');
|
|
102
|
+
const url = new URL(`/v1/apps/${encodeURIComponent(this.appId)}/rooms/${encodeURIComponent(this.roomId)}`, this.apiBase);
|
|
103
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
104
|
+
url.searchParams.set('token', token);
|
|
105
|
+
const socket = new WebSocket(url.toString());
|
|
106
|
+
this.socket = socket;
|
|
107
|
+
socket.addEventListener('open', () => {
|
|
108
|
+
this.reconnectAttempt = 0;
|
|
109
|
+
this.setState('open');
|
|
110
|
+
if (this.debug)
|
|
111
|
+
console.log(`[rooms] connected to ${this.roomId}`);
|
|
112
|
+
});
|
|
113
|
+
socket.addEventListener('message', (ev) => {
|
|
114
|
+
if (this.debug)
|
|
115
|
+
console.log('[rooms] ←', ev.data);
|
|
116
|
+
try {
|
|
117
|
+
const parsed = JSON.parse(ev.data);
|
|
118
|
+
if (parsed.kind === 'msg') {
|
|
119
|
+
if (this.debug)
|
|
120
|
+
console.log(`[rooms] msg from ${parsed.from.login}, ${this.listeners.size} listeners`);
|
|
121
|
+
for (const l of this.listeners) {
|
|
122
|
+
l({ from: parsed.from, data: parsed.data, at: parsed.at });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (parsed.kind === 'peers') {
|
|
126
|
+
this._peers = parsed.peers;
|
|
127
|
+
if (this.debug)
|
|
128
|
+
console.log(`[rooms] peers: ${this._peers.length}`);
|
|
129
|
+
for (const l of this.peerListeners)
|
|
130
|
+
l(this._peers);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
console.warn('[rooms] malformed frame', e);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
socket.addEventListener('close', (ev) => {
|
|
138
|
+
if (this.debug)
|
|
139
|
+
console.log(`[rooms] closed (code=${ev.code} reason=${ev.reason || 'none'})`);
|
|
140
|
+
if (this.socket === socket)
|
|
141
|
+
this.socket = null;
|
|
142
|
+
if (this.explicitlyClosed)
|
|
143
|
+
return;
|
|
144
|
+
this.setState('closed');
|
|
145
|
+
this.scheduleReconnect();
|
|
146
|
+
});
|
|
147
|
+
socket.addEventListener('error', () => {
|
|
148
|
+
// We let the close handler do the actual reconnect logic. error is
|
|
149
|
+
// informational and may or may not be followed by close (it always is
|
|
150
|
+
// in browsers per spec).
|
|
151
|
+
this.setState('error');
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
scheduleReconnect() {
|
|
155
|
+
if (this.reconnectTimer !== null)
|
|
156
|
+
return;
|
|
157
|
+
// Exponential backoff capped at 30s, with up to 1s of jitter so a
|
|
158
|
+
// backend hiccup doesn't produce a thundering herd of reconnects.
|
|
159
|
+
const backoff = Math.min(RECONNECT_MAX_MS, RECONNECT_BASE_MS * 2 ** this.reconnectAttempt);
|
|
160
|
+
const jitter = Math.random() * 1000;
|
|
161
|
+
this.reconnectAttempt++;
|
|
162
|
+
this.reconnectTimer = setTimeout(() => {
|
|
163
|
+
this.reconnectTimer = null;
|
|
164
|
+
if (this.explicitlyClosed)
|
|
165
|
+
return;
|
|
166
|
+
this.connect();
|
|
167
|
+
}, backoff + jitter);
|
|
168
|
+
}
|
|
169
|
+
setState(state) {
|
|
170
|
+
if (this.connectionState === state)
|
|
171
|
+
return;
|
|
172
|
+
this.connectionState = state;
|
|
173
|
+
for (const l of this.stateListeners)
|
|
174
|
+
l(state);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=rooms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rooms.js","sourceRoot":"","sources":["../src/rooms.ts"],"names":[],"mappings":"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"}
|
package/dist/ui-primitives.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { type ReactNode } from 'react';
|
|
9
9
|
import type { ProAppStore } from './index.js';
|
|
10
|
-
import type { User } from '
|
|
10
|
+
import type { User } from './base-types.js';
|
|
11
11
|
export interface AvatarProps {
|
|
12
12
|
user: User | null;
|
|
13
13
|
size?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-primitives.d.ts","sourceRoot":"","sources":["../src/ui-primitives.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAA4C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ui-primitives.d.ts","sourceRoot":"","sources":["../src/ui-primitives.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAA4C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,MAAM,CAAC,EAAE,IAAI,EAAE,IAAS,EAAE,EAAE,WAAW,2CAuBtD;AAMD,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,WAAW,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,YAAY,CAAC,EAAE,GAAG,EAAE,KAA6B,EAAE,EAAE,iBAAiB,2CAerF;AAMD,wBAAgB,WAAW,4CAwC1B;AAyBD,0EAA0E;AAC1E,wBAAgB,cAAc,4CA6C7B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,WAAW,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,WAAW,CAAC,EAAE,GAAG,EAAE,eAAsB,EAAE,QAAQ,EAAE,EAAE,gBAAgB,kDAkEtF;AAaD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,WAAW,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,WAAW,CAAC,EAAE,GAAG,EAAE,eAAsB,EAAE,EAAE,gBAAgB,2CAwG5E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proappstore/sdk",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.7",
|
|
4
4
|
"description": "Browser SDK for paid apps on proappstore.online — subscriptions, license keys, premium modules.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -33,9 +33,6 @@
|
|
|
33
33
|
"dist",
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"@freeappstore/sdk": "^0.8.0"
|
|
38
|
-
},
|
|
39
36
|
"peerDependencies": {
|
|
40
37
|
"react": "^18.0.0 || ^19.0.0"
|
|
41
38
|
},
|