@polymorfa/browser 0.1.0-dev.20260922094209
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/LICENSE +21 -0
- package/README.md +248 -0
- package/dist/calls/api.d.ts +22 -0
- package/dist/calls/api.d.ts.map +1 -0
- package/dist/calls/api.js +104 -0
- package/dist/calls/api.js.map +1 -0
- package/dist/calls/backend.d.ts +85 -0
- package/dist/calls/backend.d.ts.map +1 -0
- package/dist/calls/backend.js +141 -0
- package/dist/calls/backend.js.map +1 -0
- package/dist/calls/client.d.ts +56 -0
- package/dist/calls/client.d.ts.map +1 -0
- package/dist/calls/client.js +260 -0
- package/dist/calls/client.js.map +1 -0
- package/dist/calls/controller.d.ts +329 -0
- package/dist/calls/controller.d.ts.map +1 -0
- package/dist/calls/controller.js +1328 -0
- package/dist/calls/controller.js.map +1 -0
- package/dist/calls/diagnostics.d.ts +52 -0
- package/dist/calls/diagnostics.d.ts.map +1 -0
- package/dist/calls/diagnostics.js +188 -0
- package/dist/calls/diagnostics.js.map +1 -0
- package/dist/calls/index.d.ts +3 -0
- package/dist/calls/index.d.ts.map +1 -0
- package/dist/calls/index.js +5 -0
- package/dist/calls/index.js.map +1 -0
- package/dist/calls/internal.d.ts +8 -0
- package/dist/calls/internal.d.ts.map +1 -0
- package/dist/calls/internal.js +8 -0
- package/dist/calls/internal.js.map +1 -0
- package/dist/calls/media.d.ts +144 -0
- package/dist/calls/media.d.ts.map +1 -0
- package/dist/calls/media.js +512 -0
- package/dist/calls/media.js.map +1 -0
- package/dist/calls/signaling.d.ts +74 -0
- package/dist/calls/signaling.d.ts.map +1 -0
- package/dist/calls/signaling.js +169 -0
- package/dist/calls/signaling.js.map +1 -0
- package/dist/calls/socket.d.ts +95 -0
- package/dist/calls/socket.d.ts.map +1 -0
- package/dist/calls/socket.js +267 -0
- package/dist/calls/socket.js.map +1 -0
- package/dist/chat/composer.d.ts +59 -0
- package/dist/chat/composer.d.ts.map +1 -0
- package/dist/chat/composer.js +217 -0
- package/dist/chat/composer.js.map +1 -0
- package/dist/chat/conversation.d.ts +71 -0
- package/dist/chat/conversation.d.ts.map +1 -0
- package/dist/chat/conversation.js +204 -0
- package/dist/chat/conversation.js.map +1 -0
- package/dist/chat/index.d.ts +4 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/index.js +4 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/voice-recorder.d.ts +75 -0
- package/dist/chat/voice-recorder.d.ts.map +1 -0
- package/dist/chat/voice-recorder.js +346 -0
- package/dist/chat/voice-recorder.js.map +1 -0
- package/dist/controller.d.ts +16 -0
- package/dist/controller.d.ts.map +1 -0
- package/dist/controller.js +50 -0
- package/dist/controller.js.map +1 -0
- package/dist/diagnostics.d.ts +27 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +2 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/dropin/client.d.ts +82 -0
- package/dist/dropin/client.d.ts.map +1 -0
- package/dist/dropin/client.js +314 -0
- package/dist/dropin/client.js.map +1 -0
- package/dist/dropin/connect.d.ts +23 -0
- package/dist/dropin/connect.d.ts.map +1 -0
- package/dist/dropin/connect.js +54 -0
- package/dist/dropin/connect.js.map +1 -0
- package/dist/dropin/inbox.d.ts +131 -0
- package/dist/dropin/inbox.d.ts.map +1 -0
- package/dist/dropin/inbox.js +406 -0
- package/dist/dropin/inbox.js.map +1 -0
- package/dist/dropin/index.d.ts +5 -0
- package/dist/dropin/index.d.ts.map +1 -0
- package/dist/dropin/index.js +5 -0
- package/dist/dropin/index.js.map +1 -0
- package/dist/dropin/permissions.d.ts +29 -0
- package/dist/dropin/permissions.d.ts.map +1 -0
- package/dist/dropin/permissions.js +53 -0
- package/dist/dropin/permissions.js.map +1 -0
- package/dist/errors.d.ts +39 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +12 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +13 -0
- package/dist/internal.js.map +1 -0
- package/dist/messaging/client.d.ts +54 -0
- package/dist/messaging/client.d.ts.map +1 -0
- package/dist/messaging/client.js +153 -0
- package/dist/messaging/client.js.map +1 -0
- package/dist/messaging/composer.d.ts +12 -0
- package/dist/messaging/composer.d.ts.map +1 -0
- package/dist/messaging/composer.js +36 -0
- package/dist/messaging/composer.js.map +1 -0
- package/dist/messaging/index.d.ts +4 -0
- package/dist/messaging/index.d.ts.map +1 -0
- package/dist/messaging/index.js +3 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/messaging/types.d.ts +209 -0
- package/dist/messaging/types.d.ts.map +1 -0
- package/dist/messaging/types.js +2 -0
- package/dist/messaging/types.js.map +1 -0
- package/dist/templates/controller.d.ts +45 -0
- package/dist/templates/controller.d.ts.map +1 -0
- package/dist/templates/controller.js +298 -0
- package/dist/templates/controller.js.map +1 -0
- package/dist/templates/index.d.ts +4 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +3 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/transport.d.ts +7 -0
- package/dist/templates/transport.d.ts.map +1 -0
- package/dist/templates/transport.js +124 -0
- package/dist/templates/transport.js.map +1 -0
- package/dist/templates/types.d.ts +141 -0
- package/dist/templates/types.d.ts.map +1 -0
- package/dist/templates/types.js +2 -0
- package/dist/templates/types.js.map +1 -0
- package/dist/token.d.ts +37 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +152 -0
- package/dist/token.js.map +1 -0
- package/dist/transport.d.ts +53 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +328 -0
- package/dist/transport.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { ObservableController, } from "../controller.js";
|
|
2
|
+
import { BrowserConfigurationError, BrowserHttpError } from "../errors.js";
|
|
3
|
+
import { BrowserMessagingClient } from "../messaging/client.js";
|
|
4
|
+
import { isPolymorfaGrant, } from "./permissions.js";
|
|
5
|
+
/**
|
|
6
|
+
* Fetches client tokens from your server, refreshes them before they expire,
|
|
7
|
+
* and backs off after failures. It never chooses permissions: the token
|
|
8
|
+
* route decides, and `can()` only reports what the route granted.
|
|
9
|
+
*/
|
|
10
|
+
export class PolymorfaClient extends ObservableController {
|
|
11
|
+
tokenEndpoint;
|
|
12
|
+
/** The handler path the other routes share, for example `/api/polymorfa`. */
|
|
13
|
+
handlerPath;
|
|
14
|
+
baseUrl;
|
|
15
|
+
#fetch;
|
|
16
|
+
#now;
|
|
17
|
+
#random;
|
|
18
|
+
#refreshBeforeMs;
|
|
19
|
+
#maxBackoffMs;
|
|
20
|
+
#setTimeout;
|
|
21
|
+
#clearTimeout;
|
|
22
|
+
#token;
|
|
23
|
+
#pending;
|
|
24
|
+
#timer;
|
|
25
|
+
#started = false;
|
|
26
|
+
#messaging = new Map();
|
|
27
|
+
constructor(options = {}) {
|
|
28
|
+
const now = options.now ?? Date.now;
|
|
29
|
+
super({ status: "idle", failures: 0 }, now);
|
|
30
|
+
const endpoint = options.tokenEndpoint ?? "/api/polymorfa/token";
|
|
31
|
+
assertSameOriginPath(endpoint);
|
|
32
|
+
this.tokenEndpoint = endpoint;
|
|
33
|
+
this.handlerPath = endpoint.replace(/\/token\/?$/, "");
|
|
34
|
+
this.baseUrl = options.baseUrl;
|
|
35
|
+
const fetch = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
36
|
+
if (typeof fetch !== "function")
|
|
37
|
+
throw new BrowserConfigurationError("A fetch implementation is required.", "missing_fetch");
|
|
38
|
+
this.#fetch = fetch;
|
|
39
|
+
this.#now = now;
|
|
40
|
+
this.#random = options.random ?? Math.random;
|
|
41
|
+
this.#refreshBeforeMs = options.refreshBeforeMs ?? 60_000;
|
|
42
|
+
this.#maxBackoffMs = options.maxBackoffMs ?? 30_000;
|
|
43
|
+
this.#setTimeout =
|
|
44
|
+
options.setTimeout ??
|
|
45
|
+
((callback, ms) => globalThis.setTimeout(callback, ms));
|
|
46
|
+
this.#clearTimeout =
|
|
47
|
+
options.clearTimeout ??
|
|
48
|
+
((handle) => globalThis.clearTimeout(handle));
|
|
49
|
+
}
|
|
50
|
+
/** Fetch the first token. Safe to call more than once. */
|
|
51
|
+
start() {
|
|
52
|
+
if (this.#started)
|
|
53
|
+
return;
|
|
54
|
+
this.#started = true;
|
|
55
|
+
void this.#fetchToken().catch(() => undefined);
|
|
56
|
+
}
|
|
57
|
+
/** Whether the current grant allows `permission`. False until minted. */
|
|
58
|
+
can(permission) {
|
|
59
|
+
return this.getSnapshot().grant?.allow.includes(permission) === true;
|
|
60
|
+
}
|
|
61
|
+
/** Whether the grant covers a conversation. */
|
|
62
|
+
canRead(conversationId) {
|
|
63
|
+
const grant = this.getSnapshot().grant;
|
|
64
|
+
if (grant === undefined || !grant.allow.includes("read_messages"))
|
|
65
|
+
return false;
|
|
66
|
+
return (grant.conversations === "all" ||
|
|
67
|
+
grant.conversations.includes(conversationId));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Token provider for `BrowserTransport` and the Calls client. Returns the
|
|
71
|
+
* cached token while it is valid and waits for a fetch otherwise.
|
|
72
|
+
*/
|
|
73
|
+
getClientToken = async () => {
|
|
74
|
+
const current = this.#token;
|
|
75
|
+
if (current !== undefined && current.expiresAt - 5_000 > this.#now())
|
|
76
|
+
return current;
|
|
77
|
+
return this.#fetchToken();
|
|
78
|
+
};
|
|
79
|
+
/** Fetch a new token now, for example after the API answered `403`. */
|
|
80
|
+
async refresh() {
|
|
81
|
+
await this.#fetchToken(true);
|
|
82
|
+
}
|
|
83
|
+
/** Absolute URL path for a handler route, for example `url("events")`. */
|
|
84
|
+
url(route) {
|
|
85
|
+
return `${this.handlerPath}/${route.replace(/^\/+/, "")}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* GET or POST a JSON handler route. Checks the status and content type,
|
|
89
|
+
* so an HTML proxy error becomes a clear error instead of a parse failure.
|
|
90
|
+
*/
|
|
91
|
+
async request(route, init = {}) {
|
|
92
|
+
const response = await this.#fetch(this.url(route), {
|
|
93
|
+
method: init.method ?? "GET",
|
|
94
|
+
credentials: "same-origin",
|
|
95
|
+
headers: {
|
|
96
|
+
accept: "application/json",
|
|
97
|
+
...(init.body === undefined
|
|
98
|
+
? {}
|
|
99
|
+
: { "content-type": "application/json" }),
|
|
100
|
+
},
|
|
101
|
+
...(init.body === undefined ? {} : { body: JSON.stringify(init.body) }),
|
|
102
|
+
...(init.signal === undefined ? {} : { signal: init.signal }),
|
|
103
|
+
});
|
|
104
|
+
return readJson(response, route);
|
|
105
|
+
}
|
|
106
|
+
/** The fetch implementation this client uses, for same-origin helpers. */
|
|
107
|
+
get fetch() {
|
|
108
|
+
return this.#fetch;
|
|
109
|
+
}
|
|
110
|
+
/** A browser Messaging client for `session`, sharing this client's tokens. */
|
|
111
|
+
messaging(session) {
|
|
112
|
+
const resolved = session ?? this.getSnapshot().grant?.session;
|
|
113
|
+
if (resolved === undefined)
|
|
114
|
+
throw new BrowserConfigurationError("The grant names no session. Pass the conversation's session.", "missing_session");
|
|
115
|
+
let client = this.#messaging.get(resolved);
|
|
116
|
+
if (client === undefined) {
|
|
117
|
+
client = new BrowserMessagingClient({
|
|
118
|
+
session: resolved,
|
|
119
|
+
getClientToken: this.getClientToken,
|
|
120
|
+
fetch: this.#fetch,
|
|
121
|
+
...(this.baseUrl === undefined ? {} : { baseUrl: this.baseUrl }),
|
|
122
|
+
});
|
|
123
|
+
this.#messaging.set(resolved, client);
|
|
124
|
+
}
|
|
125
|
+
return client;
|
|
126
|
+
}
|
|
127
|
+
onDispose() {
|
|
128
|
+
if (this.#timer !== undefined)
|
|
129
|
+
this.#clearTimeout(this.#timer);
|
|
130
|
+
this.#timer = undefined;
|
|
131
|
+
this.#messaging.clear();
|
|
132
|
+
}
|
|
133
|
+
#fetchToken(force = false) {
|
|
134
|
+
if (this.#pending !== undefined && !force)
|
|
135
|
+
return this.#pending;
|
|
136
|
+
const promise = this.#load().finally(() => {
|
|
137
|
+
if (this.#pending === promise)
|
|
138
|
+
this.#pending = undefined;
|
|
139
|
+
});
|
|
140
|
+
this.#pending = promise;
|
|
141
|
+
return promise;
|
|
142
|
+
}
|
|
143
|
+
async #load() {
|
|
144
|
+
this.#started = true;
|
|
145
|
+
if (this.#timer !== undefined)
|
|
146
|
+
this.#clearTimeout(this.#timer);
|
|
147
|
+
this.#timer = undefined;
|
|
148
|
+
const previous = this.getSnapshot();
|
|
149
|
+
this.#safeTransition({
|
|
150
|
+
...fields(previous),
|
|
151
|
+
status: this.#token === undefined ? "loading" : "refreshing",
|
|
152
|
+
});
|
|
153
|
+
try {
|
|
154
|
+
const response = await this.#fetch(this.tokenEndpoint, {
|
|
155
|
+
method: "POST",
|
|
156
|
+
credentials: "same-origin",
|
|
157
|
+
headers: { accept: "application/json" },
|
|
158
|
+
});
|
|
159
|
+
const body = await readJson(response, "token");
|
|
160
|
+
const token = readToken(body, this.#now());
|
|
161
|
+
this.#token = token;
|
|
162
|
+
const refreshAt = this.#refreshAt(token.expiresAt);
|
|
163
|
+
this.#safeTransition({
|
|
164
|
+
status: "ready",
|
|
165
|
+
grant: token.grant,
|
|
166
|
+
expiresAt: token.expiresAt,
|
|
167
|
+
nextFetchAt: refreshAt,
|
|
168
|
+
failures: 0,
|
|
169
|
+
});
|
|
170
|
+
this.#schedule(refreshAt - this.#now());
|
|
171
|
+
return token;
|
|
172
|
+
}
|
|
173
|
+
catch (cause) {
|
|
174
|
+
const status = cause.status;
|
|
175
|
+
const failures = this.getSnapshot().failures + 1;
|
|
176
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
177
|
+
const current = fields(this.getSnapshot());
|
|
178
|
+
if (status === 401 || status === 403) {
|
|
179
|
+
// Signed out or refused: retrying would not change the answer.
|
|
180
|
+
this.#token = undefined;
|
|
181
|
+
this.#safeTransition({
|
|
182
|
+
status: "unauthenticated",
|
|
183
|
+
failures,
|
|
184
|
+
error: message,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
const delay = this.#backoff(failures);
|
|
189
|
+
this.#safeTransition({
|
|
190
|
+
...current,
|
|
191
|
+
status: "retrying",
|
|
192
|
+
failures,
|
|
193
|
+
nextFetchAt: this.#now() + delay,
|
|
194
|
+
error: message,
|
|
195
|
+
});
|
|
196
|
+
this.#schedule(delay);
|
|
197
|
+
}
|
|
198
|
+
throw cause;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
#refreshAt(expiresAt) {
|
|
202
|
+
const now = this.#now();
|
|
203
|
+
const lifetime = expiresAt - now;
|
|
204
|
+
// Short-lived tokens refresh at 80 % of their lifetime.
|
|
205
|
+
const lead = Math.min(this.#refreshBeforeMs, lifetime * 0.2);
|
|
206
|
+
return Math.max(now + 1_000, expiresAt - lead);
|
|
207
|
+
}
|
|
208
|
+
/** Exponential backoff with equal jitter: 1 s, 2 s, 4 s … capped. */
|
|
209
|
+
#backoff(failures) {
|
|
210
|
+
const ceiling = Math.min(this.#maxBackoffMs, 1_000 * 2 ** Math.min(failures - 1, 16));
|
|
211
|
+
return Math.round(ceiling / 2 + (this.#random() * ceiling) / 2);
|
|
212
|
+
}
|
|
213
|
+
#schedule(delay) {
|
|
214
|
+
if (this.#timer !== undefined)
|
|
215
|
+
this.#clearTimeout(this.#timer);
|
|
216
|
+
this.#timer = this.#setTimeout(() => {
|
|
217
|
+
this.#timer = undefined;
|
|
218
|
+
void this.#fetchToken(true).catch(() => undefined);
|
|
219
|
+
}, Math.max(0, delay));
|
|
220
|
+
}
|
|
221
|
+
#safeTransition(next) {
|
|
222
|
+
try {
|
|
223
|
+
this.transition(next);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// Disposed while a fetch was in flight.
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function fields(snapshot) {
|
|
231
|
+
const { revision: _revision, updatedAt: _updatedAt, ...rest } = snapshot;
|
|
232
|
+
void _revision;
|
|
233
|
+
void _updatedAt;
|
|
234
|
+
return rest;
|
|
235
|
+
}
|
|
236
|
+
function readToken(value, now) {
|
|
237
|
+
const token = value;
|
|
238
|
+
if (token === null ||
|
|
239
|
+
typeof token !== "object" ||
|
|
240
|
+
typeof token.value !== "string" ||
|
|
241
|
+
!token.value.startsWith("pmfa_ct_") ||
|
|
242
|
+
token.value.length <= "pmfa_ct_".length ||
|
|
243
|
+
token.audience !== "browser" ||
|
|
244
|
+
typeof token.expiresAt !== "number" ||
|
|
245
|
+
!Number.isFinite(token.expiresAt))
|
|
246
|
+
throw new BrowserConfigurationError("The token route returned an invalid client token.", "invalid_token_response");
|
|
247
|
+
if (token.expiresAt <= now)
|
|
248
|
+
throw new BrowserConfigurationError("The token route returned an expired client token.", "expired_client_token");
|
|
249
|
+
if (!isPolymorfaGrant(token.grant))
|
|
250
|
+
throw new BrowserConfigurationError("The token route returned no grant. Serve it with createPolymorfaHandler.", "invalid_token_response");
|
|
251
|
+
return Object.freeze({
|
|
252
|
+
value: token.value,
|
|
253
|
+
audience: "browser",
|
|
254
|
+
expiresAt: token.expiresAt,
|
|
255
|
+
scopes: Object.freeze([...token.grant.allow]),
|
|
256
|
+
grant: Object.freeze({
|
|
257
|
+
...token.grant,
|
|
258
|
+
allow: Object.freeze([...token.grant.allow]),
|
|
259
|
+
conversations: token.grant.conversations === "all"
|
|
260
|
+
? "all"
|
|
261
|
+
: Object.freeze([...token.grant.conversations]),
|
|
262
|
+
}),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
/** Reads a JSON handler response, rejecting HTML and non-2xx answers. */
|
|
266
|
+
export async function readJson(response, route) {
|
|
267
|
+
const type = response.headers.get("content-type") ?? "";
|
|
268
|
+
const isJson = /^application\/([a-z0-9.+-]*\+)?json\b/i.test(type);
|
|
269
|
+
let body;
|
|
270
|
+
if (isJson) {
|
|
271
|
+
try {
|
|
272
|
+
body = await response.json();
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
body = undefined;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (!response.ok) {
|
|
279
|
+
const error = body
|
|
280
|
+
?.error;
|
|
281
|
+
throw new BrowserHttpError(typeof error?.message === "string"
|
|
282
|
+
? error.message
|
|
283
|
+
: `The ${route} route answered ${response.status}.`, {
|
|
284
|
+
category: response.status === 401
|
|
285
|
+
? "authentication"
|
|
286
|
+
: response.status === 403
|
|
287
|
+
? "authorization"
|
|
288
|
+
: response.status === 404
|
|
289
|
+
? "not_found"
|
|
290
|
+
: response.status >= 500
|
|
291
|
+
? "server"
|
|
292
|
+
: "http",
|
|
293
|
+
status: response.status,
|
|
294
|
+
code: typeof error?.code === "string" ? error.code : "route_failed",
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (!isJson)
|
|
298
|
+
throw new BrowserConfigurationError(`The ${route} route returned ${type || "no content type"} instead of JSON. Check that the handler is mounted at this path.`, "invalid_route_response");
|
|
299
|
+
return body;
|
|
300
|
+
}
|
|
301
|
+
function assertSameOriginPath(path) {
|
|
302
|
+
if (!path.startsWith("/") ||
|
|
303
|
+
path.startsWith("//") ||
|
|
304
|
+
path.includes("\\") ||
|
|
305
|
+
URL.canParse(path))
|
|
306
|
+
throw new BrowserConfigurationError("tokenEndpoint must be a same-origin path such as /api/polymorfa/token.", "invalid_token_route");
|
|
307
|
+
}
|
|
308
|
+
/** Creates a client and starts fetching its first token. */
|
|
309
|
+
export function createPolymorfaClient(options = {}) {
|
|
310
|
+
const client = new PolymorfaClient(options);
|
|
311
|
+
client.start();
|
|
312
|
+
return client;
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/dropin/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PolymorfaClient } from "./client.js";
|
|
2
|
+
export interface ConnectWhatsAppResult {
|
|
3
|
+
/** Hosted QuickLink URL. Polymorfa hosts the pairing UI. */
|
|
4
|
+
readonly url: string;
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly expiresAt: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface ConnectWhatsAppOptions {
|
|
9
|
+
/**
|
|
10
|
+
* `redirect` (default) navigates this tab, `popup` opens a new tab. Open
|
|
11
|
+
* the popup in the click handler so browsers do not block it.
|
|
12
|
+
*/
|
|
13
|
+
readonly target?: "redirect" | "popup";
|
|
14
|
+
readonly signal?: AbortSignal;
|
|
15
|
+
/** Replaces navigation, for tests and custom flows. */
|
|
16
|
+
readonly open?: (url: string) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Asks your handler to create a QuickLink on the server, then opens the
|
|
20
|
+
* hosted URL. The pairing UI is never embedded in your page.
|
|
21
|
+
*/
|
|
22
|
+
export declare function connectWhatsApp(client: PolymorfaClient, options?: ConnectWhatsAppOptions): Promise<ConnectWhatsAppResult>;
|
|
23
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/dropin/connect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAuChC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { BrowserConfigurationError } from "../errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Asks your handler to create a QuickLink on the server, then opens the
|
|
4
|
+
* hosted URL. The pairing UI is never embedded in your page.
|
|
5
|
+
*/
|
|
6
|
+
export async function connectWhatsApp(client, options = {}) {
|
|
7
|
+
// Open the popup synchronously so it counts as user-initiated.
|
|
8
|
+
const popup = options.target === "popup" && options.open === undefined
|
|
9
|
+
? globalThis.open?.("about:blank", "_blank")
|
|
10
|
+
: undefined;
|
|
11
|
+
try {
|
|
12
|
+
const result = await client.request("connect", {
|
|
13
|
+
method: "POST",
|
|
14
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
15
|
+
});
|
|
16
|
+
const link = result.data;
|
|
17
|
+
if (link === undefined ||
|
|
18
|
+
typeof link.url !== "string" ||
|
|
19
|
+
!isHttpsUrl(link.url) ||
|
|
20
|
+
typeof link.id !== "string")
|
|
21
|
+
throw new BrowserConfigurationError("The connect route returned an invalid QuickLink.", "invalid_connect_response");
|
|
22
|
+
const value = {
|
|
23
|
+
url: link.url,
|
|
24
|
+
id: link.id,
|
|
25
|
+
expiresAt: typeof link.expiresAt === "string" ? link.expiresAt : null,
|
|
26
|
+
};
|
|
27
|
+
if (options.open !== undefined)
|
|
28
|
+
options.open(value.url);
|
|
29
|
+
else if (popup) {
|
|
30
|
+
popup.opener = null;
|
|
31
|
+
popup.location.href = value.url;
|
|
32
|
+
}
|
|
33
|
+
else
|
|
34
|
+
globalThis.location?.assign(value.url);
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
catch (cause) {
|
|
38
|
+
popup?.close();
|
|
39
|
+
throw cause;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function isHttpsUrl(value) {
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL(value);
|
|
45
|
+
return (url.protocol === "https:" ||
|
|
46
|
+
// Local development against a sandbox API.
|
|
47
|
+
(url.protocol === "http:" &&
|
|
48
|
+
(url.hostname === "localhost" || url.hostname === "127.0.0.1")));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/dropin/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAqBzD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAuB,EACvB,UAAkC,EAAE;IAEpC,+DAA+D;IAC/D,MAAM,KAAK,GACT,OAAO,CAAC,MAAM,KAAK,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QACtD,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;QAC5C,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAEhC,SAAS,EAAE;YACZ,MAAM,EAAE,MAAM;YACd,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;SACpE,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IACE,IAAI,KAAK,SAAS;YAClB,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ;YAC5B,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;YACrB,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ;YAE3B,MAAM,IAAI,yBAAyB,CACjC,kDAAkD,EAClD,0BAA0B,CAC3B,CAAC;QACJ,MAAM,KAAK,GAA0B;YACnC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,SAAS,EAAE,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;SACtE,CAAC;QACF,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;aACnD,IAAI,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;YACpB,KAAK,CAAC,QAAQ,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC;QAClC,CAAC;;YAAM,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,KAAK,EAAE,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,CACL,GAAG,CAAC,QAAQ,KAAK,QAAQ;YACzB,2CAA2C;YAC3C,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO;gBACvB,CAAC,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC,CAClE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { ConversationDataSource } from "../chat/conversation.js";
|
|
2
|
+
import { ConversationController } from "../chat/conversation.js";
|
|
3
|
+
import { ObservableController, type ControllerSnapshot } from "../controller.js";
|
|
4
|
+
import type { PolymorfaClient } from "./client.js";
|
|
5
|
+
/** One row of the conversation list. */
|
|
6
|
+
export interface InboxConversation {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
/** Session that owns the conversation; defaults to the grant's session. */
|
|
9
|
+
readonly session?: string;
|
|
10
|
+
readonly name?: string;
|
|
11
|
+
readonly phoneNumber?: string;
|
|
12
|
+
readonly avatarUrl?: string;
|
|
13
|
+
readonly lastMessage?: {
|
|
14
|
+
readonly text: string;
|
|
15
|
+
readonly createdAt: number;
|
|
16
|
+
readonly direction: "inbound" | "outbound";
|
|
17
|
+
};
|
|
18
|
+
/** Epoch milliseconds of the newest activity. */
|
|
19
|
+
readonly lastActivity: number;
|
|
20
|
+
readonly unreadCount: number;
|
|
21
|
+
}
|
|
22
|
+
/** What the contact panel shows. */
|
|
23
|
+
export interface InboxContact {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly name?: string;
|
|
26
|
+
readonly phoneNumber?: string;
|
|
27
|
+
readonly avatarUrl?: string;
|
|
28
|
+
readonly about?: string;
|
|
29
|
+
readonly email?: string;
|
|
30
|
+
/** Your own fields, shown as label and value rows. */
|
|
31
|
+
readonly fields?: readonly {
|
|
32
|
+
readonly label: string;
|
|
33
|
+
readonly value: string;
|
|
34
|
+
}[];
|
|
35
|
+
}
|
|
36
|
+
export interface InboxConversationPage {
|
|
37
|
+
readonly conversations: readonly InboxConversation[];
|
|
38
|
+
readonly nextCursor?: string;
|
|
39
|
+
}
|
|
40
|
+
export type InboxChange =
|
|
41
|
+
/** Replace or add a whole row. */
|
|
42
|
+
{
|
|
43
|
+
readonly type: "conversation";
|
|
44
|
+
readonly conversation: InboxConversation;
|
|
45
|
+
}
|
|
46
|
+
/** A new message: moves the row to the top and bumps its unread count. */
|
|
47
|
+
| {
|
|
48
|
+
readonly type: "activity";
|
|
49
|
+
readonly conversationId: string;
|
|
50
|
+
readonly session?: string;
|
|
51
|
+
readonly name?: string;
|
|
52
|
+
readonly phoneNumber?: string;
|
|
53
|
+
readonly lastMessage: NonNullable<InboxConversation["lastMessage"]>;
|
|
54
|
+
} | {
|
|
55
|
+
readonly type: "remove";
|
|
56
|
+
readonly conversationId: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Where `<Inbox/>` reads from. `createHandlerInboxSource` reads your
|
|
60
|
+
* handler's history and events routes; `@polymorfa/store` offers a local
|
|
61
|
+
* cache on top of it. Implement it yourself for any other backend.
|
|
62
|
+
*/
|
|
63
|
+
export interface InboxDataSource {
|
|
64
|
+
listConversations(cursor?: string, signal?: AbortSignal): Promise<InboxConversationPage>;
|
|
65
|
+
/** The message source for one conversation. Called once per open. */
|
|
66
|
+
conversation(conversation: InboxConversation): ConversationDataSource;
|
|
67
|
+
contact?(conversation: InboxConversation, signal?: AbortSignal): Promise<InboxContact | undefined>;
|
|
68
|
+
subscribe?(listener: (change: InboxChange) => void): () => void;
|
|
69
|
+
/** Release shared connections. */
|
|
70
|
+
close?(): void;
|
|
71
|
+
}
|
|
72
|
+
export interface InboxSnapshot extends ControllerSnapshot {
|
|
73
|
+
readonly status: "idle" | "loading" | "ready" | "loading_more" | "error";
|
|
74
|
+
readonly conversations: readonly InboxConversation[];
|
|
75
|
+
readonly selectedId?: string;
|
|
76
|
+
readonly hasMore: boolean;
|
|
77
|
+
readonly cursor?: string;
|
|
78
|
+
readonly error?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Framework-neutral state for an inbox: the conversation list, the selected
|
|
82
|
+
* conversation and one `ConversationController` per opened conversation.
|
|
83
|
+
*/
|
|
84
|
+
export declare class InboxController extends ObservableController<InboxSnapshot> {
|
|
85
|
+
#private;
|
|
86
|
+
readonly source: InboxDataSource;
|
|
87
|
+
constructor(source: InboxDataSource, options?: {
|
|
88
|
+
now?: () => number;
|
|
89
|
+
});
|
|
90
|
+
load(): Promise<void>;
|
|
91
|
+
loadMore(): Promise<void>;
|
|
92
|
+
/** Select a conversation, or pass `undefined` to go back to the list. */
|
|
93
|
+
select(conversationId: string | undefined): void;
|
|
94
|
+
get selected(): InboxConversation | undefined;
|
|
95
|
+
/** The shared controller for a conversation, created and loaded on first use. */
|
|
96
|
+
conversation(conversation: InboxConversation): ConversationController;
|
|
97
|
+
protected onDispose(): void;
|
|
98
|
+
}
|
|
99
|
+
/** A webhook event envelope as the handler's events route relays it. */
|
|
100
|
+
export interface RelayedEvent {
|
|
101
|
+
readonly id: string;
|
|
102
|
+
readonly session: string;
|
|
103
|
+
readonly event: string;
|
|
104
|
+
readonly timestamp: string;
|
|
105
|
+
readonly payload: unknown;
|
|
106
|
+
}
|
|
107
|
+
export interface HandlerInboxSourceOptions {
|
|
108
|
+
/** Read live updates from the handler's `events` route. Default true. */
|
|
109
|
+
readonly live?: boolean;
|
|
110
|
+
/** `EventSource` constructor, for tests and non-browser runtimes. */
|
|
111
|
+
readonly EventSource?: new (url: string, init?: {
|
|
112
|
+
withCredentials?: boolean;
|
|
113
|
+
}) => EventSourceLike;
|
|
114
|
+
}
|
|
115
|
+
export interface EventSourceLike {
|
|
116
|
+
addEventListener(type: string, listener: (event: {
|
|
117
|
+
data: string;
|
|
118
|
+
lastEventId?: string;
|
|
119
|
+
}) => void): void;
|
|
120
|
+
close(): void;
|
|
121
|
+
onerror?: ((event: unknown) => void) | null;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The default `<Inbox/>` source: history from your handler's `history`
|
|
125
|
+
* routes, live changes from its `events` route, and sends straight to the
|
|
126
|
+
* Polymorfa API with the client token (the API enforces `send_message`).
|
|
127
|
+
*/
|
|
128
|
+
export declare function createHandlerInboxSource(client: PolymorfaClient, options?: HandlerInboxSourceOptions): InboxDataSource;
|
|
129
|
+
/** The conversation an event belongs to, as the store reducers read it. */
|
|
130
|
+
export declare function relayedConversationId(event: RelayedEvent): string | undefined;
|
|
131
|
+
//# sourceMappingURL=inbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/dropin/inbox.ts"],"names":[],"mappings":"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"}
|