@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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +248 -0
  3. package/dist/calls/api.d.ts +22 -0
  4. package/dist/calls/api.d.ts.map +1 -0
  5. package/dist/calls/api.js +104 -0
  6. package/dist/calls/api.js.map +1 -0
  7. package/dist/calls/backend.d.ts +85 -0
  8. package/dist/calls/backend.d.ts.map +1 -0
  9. package/dist/calls/backend.js +141 -0
  10. package/dist/calls/backend.js.map +1 -0
  11. package/dist/calls/client.d.ts +56 -0
  12. package/dist/calls/client.d.ts.map +1 -0
  13. package/dist/calls/client.js +260 -0
  14. package/dist/calls/client.js.map +1 -0
  15. package/dist/calls/controller.d.ts +329 -0
  16. package/dist/calls/controller.d.ts.map +1 -0
  17. package/dist/calls/controller.js +1328 -0
  18. package/dist/calls/controller.js.map +1 -0
  19. package/dist/calls/diagnostics.d.ts +52 -0
  20. package/dist/calls/diagnostics.d.ts.map +1 -0
  21. package/dist/calls/diagnostics.js +188 -0
  22. package/dist/calls/diagnostics.js.map +1 -0
  23. package/dist/calls/index.d.ts +3 -0
  24. package/dist/calls/index.d.ts.map +1 -0
  25. package/dist/calls/index.js +5 -0
  26. package/dist/calls/index.js.map +1 -0
  27. package/dist/calls/internal.d.ts +8 -0
  28. package/dist/calls/internal.d.ts.map +1 -0
  29. package/dist/calls/internal.js +8 -0
  30. package/dist/calls/internal.js.map +1 -0
  31. package/dist/calls/media.d.ts +144 -0
  32. package/dist/calls/media.d.ts.map +1 -0
  33. package/dist/calls/media.js +512 -0
  34. package/dist/calls/media.js.map +1 -0
  35. package/dist/calls/signaling.d.ts +74 -0
  36. package/dist/calls/signaling.d.ts.map +1 -0
  37. package/dist/calls/signaling.js +169 -0
  38. package/dist/calls/signaling.js.map +1 -0
  39. package/dist/calls/socket.d.ts +95 -0
  40. package/dist/calls/socket.d.ts.map +1 -0
  41. package/dist/calls/socket.js +267 -0
  42. package/dist/calls/socket.js.map +1 -0
  43. package/dist/chat/composer.d.ts +59 -0
  44. package/dist/chat/composer.d.ts.map +1 -0
  45. package/dist/chat/composer.js +217 -0
  46. package/dist/chat/composer.js.map +1 -0
  47. package/dist/chat/conversation.d.ts +71 -0
  48. package/dist/chat/conversation.d.ts.map +1 -0
  49. package/dist/chat/conversation.js +204 -0
  50. package/dist/chat/conversation.js.map +1 -0
  51. package/dist/chat/index.d.ts +4 -0
  52. package/dist/chat/index.d.ts.map +1 -0
  53. package/dist/chat/index.js +4 -0
  54. package/dist/chat/index.js.map +1 -0
  55. package/dist/chat/voice-recorder.d.ts +75 -0
  56. package/dist/chat/voice-recorder.d.ts.map +1 -0
  57. package/dist/chat/voice-recorder.js +346 -0
  58. package/dist/chat/voice-recorder.js.map +1 -0
  59. package/dist/controller.d.ts +16 -0
  60. package/dist/controller.d.ts.map +1 -0
  61. package/dist/controller.js +50 -0
  62. package/dist/controller.js.map +1 -0
  63. package/dist/diagnostics.d.ts +27 -0
  64. package/dist/diagnostics.d.ts.map +1 -0
  65. package/dist/diagnostics.js +2 -0
  66. package/dist/diagnostics.js.map +1 -0
  67. package/dist/dropin/client.d.ts +82 -0
  68. package/dist/dropin/client.d.ts.map +1 -0
  69. package/dist/dropin/client.js +314 -0
  70. package/dist/dropin/client.js.map +1 -0
  71. package/dist/dropin/connect.d.ts +23 -0
  72. package/dist/dropin/connect.d.ts.map +1 -0
  73. package/dist/dropin/connect.js +54 -0
  74. package/dist/dropin/connect.js.map +1 -0
  75. package/dist/dropin/inbox.d.ts +131 -0
  76. package/dist/dropin/inbox.d.ts.map +1 -0
  77. package/dist/dropin/inbox.js +406 -0
  78. package/dist/dropin/inbox.js.map +1 -0
  79. package/dist/dropin/index.d.ts +5 -0
  80. package/dist/dropin/index.d.ts.map +1 -0
  81. package/dist/dropin/index.js +5 -0
  82. package/dist/dropin/index.js.map +1 -0
  83. package/dist/dropin/permissions.d.ts +29 -0
  84. package/dist/dropin/permissions.d.ts.map +1 -0
  85. package/dist/dropin/permissions.js +53 -0
  86. package/dist/dropin/permissions.js.map +1 -0
  87. package/dist/errors.d.ts +39 -0
  88. package/dist/errors.d.ts.map +1 -0
  89. package/dist/errors.js +41 -0
  90. package/dist/errors.js.map +1 -0
  91. package/dist/index.d.ts +11 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +10 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/internal.d.ts +12 -0
  96. package/dist/internal.d.ts.map +1 -0
  97. package/dist/internal.js +13 -0
  98. package/dist/internal.js.map +1 -0
  99. package/dist/messaging/client.d.ts +54 -0
  100. package/dist/messaging/client.d.ts.map +1 -0
  101. package/dist/messaging/client.js +153 -0
  102. package/dist/messaging/client.js.map +1 -0
  103. package/dist/messaging/composer.d.ts +12 -0
  104. package/dist/messaging/composer.d.ts.map +1 -0
  105. package/dist/messaging/composer.js +36 -0
  106. package/dist/messaging/composer.js.map +1 -0
  107. package/dist/messaging/index.d.ts +4 -0
  108. package/dist/messaging/index.d.ts.map +1 -0
  109. package/dist/messaging/index.js +3 -0
  110. package/dist/messaging/index.js.map +1 -0
  111. package/dist/messaging/types.d.ts +209 -0
  112. package/dist/messaging/types.d.ts.map +1 -0
  113. package/dist/messaging/types.js +2 -0
  114. package/dist/messaging/types.js.map +1 -0
  115. package/dist/templates/controller.d.ts +45 -0
  116. package/dist/templates/controller.d.ts.map +1 -0
  117. package/dist/templates/controller.js +298 -0
  118. package/dist/templates/controller.js.map +1 -0
  119. package/dist/templates/index.d.ts +4 -0
  120. package/dist/templates/index.d.ts.map +1 -0
  121. package/dist/templates/index.js +3 -0
  122. package/dist/templates/index.js.map +1 -0
  123. package/dist/templates/transport.d.ts +7 -0
  124. package/dist/templates/transport.d.ts.map +1 -0
  125. package/dist/templates/transport.js +124 -0
  126. package/dist/templates/transport.js.map +1 -0
  127. package/dist/templates/types.d.ts +141 -0
  128. package/dist/templates/types.d.ts.map +1 -0
  129. package/dist/templates/types.js +2 -0
  130. package/dist/templates/types.js.map +1 -0
  131. package/dist/token.d.ts +37 -0
  132. package/dist/token.d.ts.map +1 -0
  133. package/dist/token.js +152 -0
  134. package/dist/token.js.map +1 -0
  135. package/dist/transport.d.ts +53 -0
  136. package/dist/transport.d.ts.map +1 -0
  137. package/dist/transport.js +328 -0
  138. package/dist/transport.js.map +1 -0
  139. package/package.json +45 -0
@@ -0,0 +1,346 @@
1
+ import { ObservableController, } from "../controller.js";
2
+ const CANDIDATE_TYPES = [
3
+ "audio/webm;codecs=opus",
4
+ "audio/webm",
5
+ "audio/ogg;codecs=opus",
6
+ "audio/ogg",
7
+ "audio/mp4",
8
+ ];
9
+ function environment(options) {
10
+ const scope = globalThis;
11
+ return {
12
+ mediaDevices: options.mediaDevices ?? scope.navigator?.mediaDevices,
13
+ Recorder: options.MediaRecorder ?? scope.MediaRecorder,
14
+ Audio: options.AudioContext === null
15
+ ? undefined
16
+ : (options.AudioContext ??
17
+ scope.AudioContext ??
18
+ scope.webkitAudioContext),
19
+ };
20
+ }
21
+ function errorKind(cause) {
22
+ const name = cause?.name;
23
+ if (name === "NotAllowedError" || name === "SecurityError")
24
+ return "permission-denied";
25
+ if (name === "NotFoundError" || name === "OverconstrainedError")
26
+ return "unavailable";
27
+ return "failed";
28
+ }
29
+ /**
30
+ * Records a voice note from the microphone with `getUserMedia` and
31
+ * `MediaRecorder`, publishing status, elapsed time, and input level.
32
+ * `stop()` resolves with the recording as a `File`; `cancel()` discards it.
33
+ * Microphone tracks stop whenever recording ends and on `dispose()`.
34
+ */
35
+ export class VoiceNoteRecorder extends ObservableController {
36
+ #options;
37
+ #clock;
38
+ #stream;
39
+ #recorder;
40
+ #audio;
41
+ #frame;
42
+ #timer;
43
+ #chunks = [];
44
+ #startedAt = 0;
45
+ #lastPublish = 0;
46
+ #attempt = 0;
47
+ #finish;
48
+ constructor(options = {}) {
49
+ super({ status: "idle", elapsed: 0, level: 0 }, options.now);
50
+ this.#options = options;
51
+ this.#clock = options.now ?? Date.now;
52
+ }
53
+ /** Whether this environment can record: `getUserMedia` and `MediaRecorder`. */
54
+ static isSupported(options = {}) {
55
+ const { mediaDevices, Recorder } = environment(options);
56
+ return (typeof mediaDevices?.getUserMedia === "function" &&
57
+ typeof Recorder === "function");
58
+ }
59
+ /** Ask for the microphone and start recording. Resolves once recording. */
60
+ async start() {
61
+ this.assertActive();
62
+ const status = this.getSnapshot().status;
63
+ if (status === "requesting" || status === "recording")
64
+ return;
65
+ const { mediaDevices, Recorder, Audio } = environment(this.#options);
66
+ if (typeof mediaDevices?.getUserMedia !== "function" || !Recorder) {
67
+ this.#fail("unavailable");
68
+ return;
69
+ }
70
+ const attempt = ++this.#attempt;
71
+ this.transition({ status: "requesting", elapsed: 0, level: 0 });
72
+ let stream;
73
+ try {
74
+ stream = await mediaDevices.getUserMedia({ audio: true });
75
+ }
76
+ catch (cause) {
77
+ if (attempt === this.#attempt && !this.#disposed())
78
+ this.#fail(errorKind(cause));
79
+ return;
80
+ }
81
+ if (attempt !== this.#attempt || this.#disposed()) {
82
+ stopTracks(stream);
83
+ return;
84
+ }
85
+ const mimeType = CANDIDATE_TYPES.find((type) => Recorder.isTypeSupported?.(type) === true);
86
+ let recorder;
87
+ try {
88
+ recorder = new Recorder(stream, mimeType === undefined ? undefined : { mimeType });
89
+ }
90
+ catch {
91
+ stopTracks(stream);
92
+ this.#fail("failed");
93
+ return;
94
+ }
95
+ this.#stream = stream;
96
+ this.#recorder = recorder;
97
+ this.#chunks = [];
98
+ recorder.ondataavailable = (event) => {
99
+ if (event.data.size > 0)
100
+ this.#chunks.push(event.data);
101
+ };
102
+ recorder.onstop = () => this.#finalize(recorder);
103
+ recorder.onerror = () => {
104
+ this.#release();
105
+ this.#resolve(undefined);
106
+ if (!this.#disposed())
107
+ this.#fail("failed");
108
+ };
109
+ try {
110
+ recorder.start(250);
111
+ }
112
+ catch {
113
+ this.#release();
114
+ this.#fail("failed");
115
+ return;
116
+ }
117
+ this.#startedAt = this.#clock();
118
+ const container = containerType(recorder.mimeType || mimeType);
119
+ this.transition({
120
+ status: "recording",
121
+ elapsed: 0,
122
+ level: 0,
123
+ ...(container === undefined ? {} : { mimeType: container }),
124
+ });
125
+ this.#startMeter(stream, Audio);
126
+ }
127
+ /**
128
+ * Stop recording and resolve with the voice note, or `undefined` when
129
+ * nothing was recording or the recorder produced no audio.
130
+ */
131
+ stop() {
132
+ const recorder = this.#recorder;
133
+ if (recorder === undefined || this.getSnapshot().status !== "recording")
134
+ return Promise.resolve(undefined);
135
+ const current = this.getSnapshot();
136
+ this.transition({
137
+ status: "stopping",
138
+ elapsed: this.#clock() - this.#startedAt,
139
+ level: 0,
140
+ ...(current.mimeType === undefined ? {} : { mimeType: current.mimeType }),
141
+ });
142
+ this.#stopMeter();
143
+ return new Promise((resolve) => {
144
+ this.#finish = resolve;
145
+ try {
146
+ if (recorder.state === "inactive")
147
+ this.#finalize(recorder);
148
+ else
149
+ recorder.stop();
150
+ }
151
+ catch {
152
+ this.#finalize(recorder);
153
+ }
154
+ });
155
+ }
156
+ /** Discard the recording, or abandon a pending permission request. */
157
+ cancel() {
158
+ this.#attempt += 1;
159
+ const recorder = this.#recorder;
160
+ this.#chunks = [];
161
+ if (recorder !== undefined) {
162
+ recorder.ondataavailable = null;
163
+ recorder.onstop = null;
164
+ recorder.onerror = null;
165
+ try {
166
+ if (recorder.state !== "inactive")
167
+ recorder.stop();
168
+ }
169
+ catch {
170
+ // Already stopped.
171
+ }
172
+ }
173
+ this.#release();
174
+ this.#resolve(undefined);
175
+ if (!this.#disposed())
176
+ this.transition({ status: "idle", elapsed: 0, level: 0 });
177
+ }
178
+ onDispose() {
179
+ this.#attempt += 1;
180
+ const recorder = this.#recorder;
181
+ if (recorder !== undefined) {
182
+ recorder.onstop = null;
183
+ recorder.onerror = null;
184
+ recorder.ondataavailable = null;
185
+ try {
186
+ if (recorder.state !== "inactive")
187
+ recorder.stop();
188
+ }
189
+ catch {
190
+ // Already stopped.
191
+ }
192
+ }
193
+ this.#release();
194
+ this.#resolve(undefined);
195
+ }
196
+ #disposedFlag = false;
197
+ #disposed() {
198
+ return this.#disposedFlag;
199
+ }
200
+ dispose() {
201
+ this.#disposedFlag = true;
202
+ super.dispose();
203
+ }
204
+ #finalize(recorder) {
205
+ if (this.#recorder !== recorder)
206
+ return;
207
+ const reported = recorder.mimeType;
208
+ const type = reported === undefined || reported === ""
209
+ ? (this.getSnapshot().mimeType ?? "audio/webm")
210
+ : containerType(reported);
211
+ if (type === undefined) {
212
+ // Never relabel audio in a container the upload path cannot name.
213
+ this.#chunks = [];
214
+ this.#release();
215
+ this.#resolve(undefined);
216
+ if (!this.#disposed())
217
+ this.#fail("failed");
218
+ return;
219
+ }
220
+ const blob = new Blob(this.#chunks, { type });
221
+ this.#chunks = [];
222
+ this.#release();
223
+ const file = blob.size === 0
224
+ ? undefined
225
+ : new File([blob], voiceNoteName(type, this.#clock()), { type });
226
+ if (!this.#disposed())
227
+ this.transition({ status: "idle", elapsed: 0, level: 0 });
228
+ this.#resolve(file);
229
+ }
230
+ #resolve(file) {
231
+ const finish = this.#finish;
232
+ this.#finish = undefined;
233
+ finish?.(file);
234
+ }
235
+ #fail(error) {
236
+ this.transition({ status: "error", elapsed: 0, level: 0, error });
237
+ }
238
+ #startMeter(stream, Audio) {
239
+ let read;
240
+ if (Audio !== undefined) {
241
+ try {
242
+ const audio = new Audio();
243
+ const analyser = audio.createAnalyser();
244
+ analyser.fftSize = 512;
245
+ audio.createMediaStreamSource(stream).connect(analyser);
246
+ const samples = new Uint8Array(analyser.frequencyBinCount);
247
+ this.#audio = audio;
248
+ read = () => {
249
+ analyser.getByteTimeDomainData(samples);
250
+ let sum = 0;
251
+ for (const sample of samples) {
252
+ const centered = (sample - 128) / 128;
253
+ sum += centered * centered;
254
+ }
255
+ return Math.min(1, Math.sqrt(sum / samples.length) * 3);
256
+ };
257
+ }
258
+ catch {
259
+ read = undefined;
260
+ }
261
+ }
262
+ const raf = this.#options.requestAnimationFrame ??
263
+ (typeof requestAnimationFrame === "function"
264
+ ? (callback) => requestAnimationFrame(callback)
265
+ : undefined);
266
+ const interval = this.#options.updateInterval ?? 50;
267
+ const tick = () => {
268
+ if (this.getSnapshot().status !== "recording")
269
+ return;
270
+ const now = this.#clock();
271
+ if (now - this.#lastPublish >= interval) {
272
+ this.#lastPublish = now;
273
+ const current = this.getSnapshot();
274
+ this.transition({
275
+ status: "recording",
276
+ elapsed: now - this.#startedAt,
277
+ level: read === undefined ? 0 : read(),
278
+ ...(current.mimeType === undefined
279
+ ? {}
280
+ : { mimeType: current.mimeType }),
281
+ });
282
+ }
283
+ };
284
+ if (raf !== undefined) {
285
+ const loop = () => {
286
+ tick();
287
+ if (this.#recorder !== undefined && !this.#disposed())
288
+ this.#frame = raf(loop);
289
+ };
290
+ this.#frame = raf(loop);
291
+ }
292
+ else
293
+ this.#timer = setInterval(tick, Math.max(interval, 250));
294
+ }
295
+ #stopMeter() {
296
+ if (this.#frame !== undefined) {
297
+ const cancel = this.#options.cancelAnimationFrame ??
298
+ (typeof cancelAnimationFrame === "function"
299
+ ? (handle) => cancelAnimationFrame(handle)
300
+ : undefined);
301
+ cancel?.(this.#frame);
302
+ this.#frame = undefined;
303
+ }
304
+ if (this.#timer !== undefined) {
305
+ clearInterval(this.#timer);
306
+ this.#timer = undefined;
307
+ }
308
+ const audio = this.#audio;
309
+ this.#audio = undefined;
310
+ audio?.close().catch(() => undefined);
311
+ }
312
+ #release() {
313
+ this.#stopMeter();
314
+ if (this.#stream !== undefined)
315
+ stopTracks(this.#stream);
316
+ this.#stream = undefined;
317
+ this.#recorder = undefined;
318
+ }
319
+ }
320
+ function stopTracks(stream) {
321
+ for (const track of stream.getTracks())
322
+ track.stop();
323
+ }
324
+ /** Recording containers the SDK can upload, with their file extensions. */
325
+ const CONTAINER_EXTENSIONS = new Map([
326
+ ["audio/webm", "webm"],
327
+ ["audio/ogg", "ogg"],
328
+ ["audio/mp4", "m4a"],
329
+ ]);
330
+ /** The allowlisted container for a reported type, or `undefined`. */
331
+ function containerType(type) {
332
+ if (type === undefined || type === "")
333
+ return undefined;
334
+ const base = type.split(";", 1)[0]?.trim().toLowerCase() ?? "";
335
+ return CONTAINER_EXTENSIONS.has(base) ? base : undefined;
336
+ }
337
+ /**
338
+ * `voice-note-<ISO time>.webm` (`.ogg` or `.m4a` for those containers), with
339
+ * `:` replaced for portability.
340
+ */
341
+ export function voiceNoteName(type, time = Date.now()) {
342
+ const stamp = new Date(time).toISOString().replace(/[:.]/g, "-");
343
+ const container = containerType(type) ?? "audio/webm";
344
+ return `voice-note-${stamp}.${CONTAINER_EXTENSIONS.get(container) ?? "webm"}`;
345
+ }
346
+ //# sourceMappingURL=voice-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-recorder.js","sourceRoot":"","sources":["../../src/chat/voice-recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface ControllerSnapshot {
2
+ readonly revision: number;
3
+ readonly updatedAt: number;
4
+ }
5
+ export type ControllerListener = () => void;
6
+ export declare abstract class ObservableController<TSnapshot extends ControllerSnapshot> {
7
+ #private;
8
+ protected constructor(initial: Omit<TSnapshot, "revision" | "updatedAt">, now?: () => number);
9
+ getSnapshot: () => TSnapshot;
10
+ subscribe: (listener: ControllerListener) => (() => void);
11
+ protected transition(next: Omit<TSnapshot, "revision" | "updatedAt">): void;
12
+ protected assertActive(): void;
13
+ dispose(): void;
14
+ protected onDispose(): void;
15
+ }
16
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC;AAE5C,8BAAsB,oBAAoB,CACxC,SAAS,SAAS,kBAAkB;;IAOpC,SAAS,aACP,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,WAAW,CAAC,EAClD,GAAG,GAAE,MAAM,MAAiB;IAU9B,WAAW,QAAO,SAAS,CAAmB;IAE9C,SAAS,GAAI,UAAU,kBAAkB,KAAG,CAAC,MAAM,IAAI,CAAC,CAItD;IAEF,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,WAAW,CAAC,GAAG,IAAI;IAU3E,SAAS,CAAC,YAAY,IAAI,IAAI;IAK9B,OAAO,IAAI,IAAI;IAOf,SAAS,CAAC,SAAS,IAAI,IAAI;CAC5B"}
@@ -0,0 +1,50 @@
1
+ export class ObservableController {
2
+ #listeners = new Set();
3
+ #now;
4
+ #snapshot;
5
+ #disposed = false;
6
+ constructor(initial, now = Date.now) {
7
+ this.#now = now;
8
+ this.#snapshot = deepFreeze({
9
+ ...initial,
10
+ revision: 0,
11
+ updatedAt: now(),
12
+ });
13
+ }
14
+ getSnapshot = () => this.#snapshot;
15
+ subscribe = (listener) => {
16
+ this.assertActive();
17
+ this.#listeners.add(listener);
18
+ return () => this.#listeners.delete(listener);
19
+ };
20
+ transition(next) {
21
+ this.assertActive();
22
+ this.#snapshot = deepFreeze({
23
+ ...next,
24
+ revision: this.#snapshot.revision + 1,
25
+ updatedAt: this.#now(),
26
+ });
27
+ for (const listener of [...this.#listeners])
28
+ listener();
29
+ }
30
+ assertActive() {
31
+ if (this.#disposed)
32
+ throw new Error(`${this.constructor.name} is disposed.`);
33
+ }
34
+ dispose() {
35
+ if (this.#disposed)
36
+ return;
37
+ this.#disposed = true;
38
+ this.#listeners.clear();
39
+ this.onDispose();
40
+ }
41
+ onDispose() { }
42
+ }
43
+ function deepFreeze(value) {
44
+ if (typeof value !== "object" || value === null || Object.isFrozen(value))
45
+ return value;
46
+ for (const child of Object.values(value))
47
+ deepFreeze(child);
48
+ return Object.freeze(value);
49
+ }
50
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"AAOA,MAAM,OAAgB,oBAAoB;IAG/B,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC3C,IAAI,CAAe;IAC5B,SAAS,CAAY;IACrB,SAAS,GAAG,KAAK,CAAC;IAElB,YACE,OAAkD,EAClD,MAAoB,IAAI,CAAC,GAAG;QAE5B,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC;YAC1B,GAAG,OAAO;YACV,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,GAAG,EAAE;SACjB,CAAc,CAAC;IAClB,CAAC;IAED,WAAW,GAAG,GAAc,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;IAE9C,SAAS,GAAG,CAAC,QAA4B,EAAgB,EAAE;QACzD,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC,CAAC;IAEQ,UAAU,CAAC,IAA+C;QAClE,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC;YAC1B,GAAG,IAAI;YACP,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,CAAC;YACrC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE;SACvB,CAAc,CAAC;QAChB,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;YAAE,QAAQ,EAAE,CAAC;IAC1D,CAAC;IAES,YAAY;QACpB,IAAI,IAAI,CAAC,SAAS;YAChB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,eAAe,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAES,SAAS,KAAU,CAAC;CAC/B;AAED,SAAS,UAAU,CAAI,KAAQ;IAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { BrowserErrorCategory } from "./errors.js";
2
+ interface BrowserDiagnosticBase {
3
+ readonly timestamp: number;
4
+ readonly method: string;
5
+ readonly path: string;
6
+ readonly attempt: number;
7
+ }
8
+ export interface BrowserRequestStartedDiagnostic extends BrowserDiagnosticBase {
9
+ readonly type: "request.started";
10
+ }
11
+ export interface BrowserRequestCompletedDiagnostic extends BrowserDiagnosticBase {
12
+ readonly type: "request.completed";
13
+ readonly status: number;
14
+ readonly durationMs: number;
15
+ readonly requestId?: string;
16
+ }
17
+ export interface BrowserRequestFailedDiagnostic extends BrowserDiagnosticBase {
18
+ readonly type: "request.failed";
19
+ readonly durationMs: number;
20
+ readonly category: BrowserErrorCategory;
21
+ readonly status?: number;
22
+ readonly requestId?: string;
23
+ }
24
+ export type BrowserDiagnosticEvent = BrowserRequestStartedDiagnostic | BrowserRequestCompletedDiagnostic | BrowserRequestFailedDiagnostic;
25
+ export type BrowserDiagnosticSink = (event: BrowserDiagnosticEvent) => void;
26
+ export {};
27
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,+BAAgC,SAAQ,qBAAqB;IAC5E,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;CAClC;AAED,MAAM,WAAW,iCAAkC,SAAQ,qBAAqB;IAC9E,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,8BAA+B,SAAQ,qBAAqB;IAC3E,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,sBAAsB,GAC9B,+BAA+B,GAC/B,iCAAiC,GACjC,8BAA8B,CAAC;AAEnC,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ import { ObservableController, type ControllerSnapshot } from "../controller.js";
2
+ import { BrowserMessagingClient } from "../messaging/client.js";
3
+ import type { ClientToken } from "../token.js";
4
+ import { type PolymorfaGrant, type PolymorfaPermission } from "./permissions.js";
5
+ export type PolymorfaClientStatus = "idle" | "loading" | "ready" | "refreshing" | "retrying" | "unauthenticated" | "error";
6
+ export interface PolymorfaClientSnapshot extends ControllerSnapshot {
7
+ readonly status: PolymorfaClientStatus;
8
+ /** Present once a token has been minted. */
9
+ readonly grant?: PolymorfaGrant;
10
+ /** Epoch milliseconds when the current token expires. */
11
+ readonly expiresAt?: number;
12
+ /** Epoch milliseconds of the next scheduled fetch. */
13
+ readonly nextFetchAt?: number;
14
+ /** Failed attempts since the last success. */
15
+ readonly failures: number;
16
+ readonly error?: string;
17
+ }
18
+ export interface PolymorfaClientOptions {
19
+ /**
20
+ * Same-origin path of your handler's token route. Default
21
+ * `/api/polymorfa/token`. The other drop-in routes live next to it.
22
+ */
23
+ readonly tokenEndpoint?: string;
24
+ /** Polymorfa API origin for direct client-token calls. */
25
+ readonly baseUrl?: string;
26
+ /** Refresh this long before expiry. Default 60 s. */
27
+ readonly refreshBeforeMs?: number;
28
+ /** Longest wait between failed attempts. Default 30 s. */
29
+ readonly maxBackoffMs?: number;
30
+ readonly fetch?: typeof globalThis.fetch;
31
+ readonly now?: () => number;
32
+ readonly random?: () => number;
33
+ readonly setTimeout?: (callback: () => void, ms: number) => unknown;
34
+ readonly clearTimeout?: (handle: unknown) => void;
35
+ }
36
+ /**
37
+ * Fetches client tokens from your server, refreshes them before they expire,
38
+ * and backs off after failures. It never chooses permissions: the token
39
+ * route decides, and `can()` only reports what the route granted.
40
+ */
41
+ export declare class PolymorfaClient extends ObservableController<PolymorfaClientSnapshot> {
42
+ #private;
43
+ readonly tokenEndpoint: string;
44
+ /** The handler path the other routes share, for example `/api/polymorfa`. */
45
+ readonly handlerPath: string;
46
+ readonly baseUrl: string | undefined;
47
+ constructor(options?: PolymorfaClientOptions);
48
+ /** Fetch the first token. Safe to call more than once. */
49
+ start(): void;
50
+ /** Whether the current grant allows `permission`. False until minted. */
51
+ can(permission: PolymorfaPermission): boolean;
52
+ /** Whether the grant covers a conversation. */
53
+ canRead(conversationId: string): boolean;
54
+ /**
55
+ * Token provider for `BrowserTransport` and the Calls client. Returns the
56
+ * cached token while it is valid and waits for a fetch otherwise.
57
+ */
58
+ getClientToken: () => Promise<ClientToken>;
59
+ /** Fetch a new token now, for example after the API answered `403`. */
60
+ refresh(): Promise<void>;
61
+ /** Absolute URL path for a handler route, for example `url("events")`. */
62
+ url(route: string): string;
63
+ /**
64
+ * GET or POST a JSON handler route. Checks the status and content type,
65
+ * so an HTML proxy error becomes a clear error instead of a parse failure.
66
+ */
67
+ request<T>(route: string, init?: {
68
+ readonly method?: "GET" | "POST";
69
+ readonly body?: unknown;
70
+ readonly signal?: AbortSignal;
71
+ }): Promise<T>;
72
+ /** The fetch implementation this client uses, for same-origin helpers. */
73
+ get fetch(): typeof globalThis.fetch;
74
+ /** A browser Messaging client for `session`, sharing this client's tokens. */
75
+ messaging(session?: string): BrowserMessagingClient;
76
+ protected onDispose(): void;
77
+ }
78
+ /** Reads a JSON handler response, rejecting HTML and non-2xx answers. */
79
+ export declare function readJson<T>(response: Response, route: string): Promise<T>;
80
+ /** Creates a client and starts fetching its first token. */
81
+ export declare function createPolymorfaClient(options?: PolymorfaClientOptions): PolymorfaClient;
82
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/dropin/client.ts"],"names":[],"mappings":"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"}