@securitydept/client 0.3.0-beta.3 → 0.3.0-beta.6

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 (60) hide show
  1. package/README.md +6 -0
  2. package/dist/create-99Ksgl_O.mjs +952 -0
  3. package/dist/create-99Ksgl_O.mjs.map +1 -0
  4. package/dist/handle-TnxwtQ4T.mjs +634 -0
  5. package/dist/handle-TnxwtQ4T.mjs.map +1 -0
  6. package/dist/index-Cg_iY2yY.d.mts +608 -0
  7. package/dist/index-DmIapvr-.d.mts +1669 -0
  8. package/dist/index-O1A3CdBV.d.mts +119 -0
  9. package/dist/index.d.mts +3 -353
  10. package/dist/index.mjs +1127 -364
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/router-DUh3bhLy.mjs +245 -0
  13. package/dist/router-DUh3bhLy.mjs.map +1 -0
  14. package/dist/rx/index.d.mts +68 -0
  15. package/dist/rx/index.mjs +2 -0
  16. package/dist/rx-B3OU17wu.mjs +1105 -0
  17. package/dist/rx-B3OU17wu.mjs.map +1 -0
  18. package/dist/server/index.d.mts +20 -0
  19. package/dist/server/index.mjs +29 -0
  20. package/dist/server/index.mjs.map +1 -0
  21. package/dist/test/index.d.mts +101 -0
  22. package/dist/test/index.mjs +270 -0
  23. package/dist/test/index.mjs.map +1 -0
  24. package/dist/uri-string-BPNbIMgv.mjs +300 -0
  25. package/dist/uri-string-BPNbIMgv.mjs.map +1 -0
  26. package/dist/web/index.d.mts +93 -363
  27. package/dist/web/index.mjs +335 -428
  28. package/dist/web/index.mjs.map +1 -1
  29. package/dist/webext/index.d.mts +73 -0
  30. package/dist/webext/index.mjs +231 -0
  31. package/dist/webext/index.mjs.map +1 -0
  32. package/package.json +28 -21
  33. package/dist/auth-coordination/index.d.mts +0 -198
  34. package/dist/auth-coordination/index.mjs +0 -107
  35. package/dist/auth-coordination/index.mjs.map +0 -1
  36. package/dist/client-environment-CaumNmir.mjs +0 -812
  37. package/dist/client-environment-CaumNmir.mjs.map +0 -1
  38. package/dist/client-environment-CdHtVxKW.d.mts +0 -401
  39. package/dist/events/index.d.mts +0 -2
  40. package/dist/events/index.mjs +0 -2
  41. package/dist/events-BUlfsRfl.mjs +0 -127
  42. package/dist/events-BUlfsRfl.mjs.map +0 -1
  43. package/dist/index-C4xlKhG7.d.mts +0 -102
  44. package/dist/index-COUt5x9Z.d.mts +0 -39
  45. package/dist/persistence/index.d.mts +0 -3
  46. package/dist/persistence/index.mjs +0 -2
  47. package/dist/persistence/web/index.d.mts +0 -16
  48. package/dist/persistence/web/index.mjs +0 -2
  49. package/dist/persistence-CSB8770k.mjs +0 -108
  50. package/dist/persistence-CSB8770k.mjs.map +0 -1
  51. package/dist/planner-host-BTWie0lo.mjs +0 -197
  52. package/dist/planner-host-BTWie0lo.mjs.map +0 -1
  53. package/dist/planner-host-DN9dRsQx.d.mts +0 -190
  54. package/dist/types-BJqUdH2e.d.mts +0 -32
  55. package/dist/types-BwcnUGNl.d.mts +0 -52
  56. package/dist/web-DQmMqZnR.mjs +0 -51
  57. package/dist/web-DQmMqZnR.mjs.map +0 -1
  58. package/dist/web-router/index.d.mts +0 -259
  59. package/dist/web-router/index.mjs +0 -395
  60. package/dist/web-router/index.mjs.map +0 -1
@@ -0,0 +1,634 @@
1
+ import { A as RxEventSubject, D as RxStateSignal, F as SYMBOL_DISPOSE, G as UserRecovery, H as ClientErrorKind, V as ClientError, W as ErrorPresentationTone, h as createAsyncSchedulerWithTimestampProvider } from "./rx-B3OU17wu.mjs";
2
+ import { B as validateWithSchemaSync } from "./create-99Ksgl_O.mjs";
3
+ import { BehaviorSubject, ReplaySubject, Subject, catchError, delayWhen, distinctUntilChanged, exhaustMap, filter, from, map, merge, of, shareReplay, take, takeUntil, timeout, timer } from "rxjs";
4
+ import { type } from "arktype";
5
+ //#region src/errors/presentation-descriptor.ts
6
+ const DEFAULT_RECOVERY_LABELS = {
7
+ [UserRecovery.None]: "",
8
+ [UserRecovery.Retry]: "Try again",
9
+ [UserRecovery.RestartFlow]: "Restart flow",
10
+ [UserRecovery.Reauthenticate]: "Sign in again",
11
+ [UserRecovery.ContactSupport]: "Contact support"
12
+ };
13
+ const userRecoveryValues = new Set(Object.values(UserRecovery));
14
+ const clientErrorKindValues = new Set(Object.values(ClientErrorKind));
15
+ function readErrorPresentationDescriptor(error, options = {}) {
16
+ const clientError = error instanceof ClientError ? error : coerceClientErrorLike(error);
17
+ if (!clientError) return {
18
+ code: null,
19
+ kind: null,
20
+ title: options.fallbackTitle ?? "Operation failed",
21
+ description: options.fallbackDescription ?? "An unexpected error prevented the operation from completing.",
22
+ recovery: UserRecovery.None,
23
+ retryable: false,
24
+ tone: ErrorPresentationTone.Danger,
25
+ primaryAction: null
26
+ };
27
+ const code = clientError.presentation?.code ?? clientError.code;
28
+ const codePresentation = code ? options.codePresentations?.[code] : void 0;
29
+ const recovery = clientError.presentation?.recovery ?? codePresentation?.recovery ?? clientError.recovery;
30
+ const generic = readGenericPresentation(clientError.kind);
31
+ return {
32
+ code,
33
+ kind: clientError.kind,
34
+ source: clientError.source,
35
+ title: codePresentation?.title ?? generic.title,
36
+ description: clientError.presentation?.message ?? codePresentation?.description ?? generic.description,
37
+ recovery,
38
+ retryable: clientError.retryable,
39
+ tone: codePresentation?.tone ?? readClientErrorTone(clientError.kind, recovery),
40
+ primaryAction: readPrimaryAction(recovery, options)
41
+ };
42
+ }
43
+ function readGenericPresentation(kind) {
44
+ switch (kind) {
45
+ case ClientErrorKind.Unauthenticated: return {
46
+ title: "Authentication required",
47
+ description: "Sign in again to continue."
48
+ };
49
+ case ClientErrorKind.Unauthorized: return {
50
+ title: "Access denied",
51
+ description: "You do not have permission to complete this operation."
52
+ };
53
+ case ClientErrorKind.Cancelled: return {
54
+ title: "Operation cancelled",
55
+ description: "The operation was cancelled before it completed."
56
+ };
57
+ case ClientErrorKind.Timeout: return {
58
+ title: "Request timed out",
59
+ description: "The operation did not complete in time."
60
+ };
61
+ case ClientErrorKind.Configuration: return {
62
+ title: "Configuration error",
63
+ description: "The client is not configured to complete this operation."
64
+ };
65
+ case ClientErrorKind.Storage: return {
66
+ title: "Storage failed",
67
+ description: "The client could not access required stored data."
68
+ };
69
+ case ClientErrorKind.Transport: return {
70
+ title: "Network request failed",
71
+ description: "The client could not reach the service."
72
+ };
73
+ case ClientErrorKind.Server: return {
74
+ title: "Server request failed",
75
+ description: "The service could not complete the request."
76
+ };
77
+ case ClientErrorKind.Protocol: return {
78
+ title: "Invalid response",
79
+ description: "The service response did not satisfy the expected protocol."
80
+ };
81
+ case ClientErrorKind.Authorization: return {
82
+ title: "Authorization failed",
83
+ description: "The authorization flow could not be completed."
84
+ };
85
+ default: return {
86
+ title: "Operation failed",
87
+ description: "The operation could not be completed."
88
+ };
89
+ }
90
+ }
91
+ function readClientErrorTone(kind, recovery) {
92
+ if (kind === ClientErrorKind.Cancelled) return ErrorPresentationTone.Neutral;
93
+ if (kind === ClientErrorKind.Unauthenticated || kind === ClientErrorKind.Timeout || kind === ClientErrorKind.Transport || kind === ClientErrorKind.Server || recovery === UserRecovery.Retry || recovery === UserRecovery.RestartFlow || recovery === UserRecovery.Reauthenticate) return ErrorPresentationTone.Warning;
94
+ return ErrorPresentationTone.Danger;
95
+ }
96
+ function coerceClientErrorLike(error) {
97
+ if (typeof error !== "object" || error === null) return null;
98
+ const candidate = error;
99
+ if (typeof candidate.kind !== "string" || !clientErrorKindValues.has(candidate.kind)) return null;
100
+ return {
101
+ code: typeof candidate.code === "string" ? candidate.code : null,
102
+ kind: candidate.kind,
103
+ recovery: typeof candidate.recovery === "string" && userRecoveryValues.has(candidate.recovery) ? candidate.recovery : UserRecovery.None,
104
+ retryable: candidate.retryable === true,
105
+ source: typeof candidate.source === "string" ? candidate.source : void 0,
106
+ presentation: isErrorPresentation(candidate.presentation) ? candidate.presentation : void 0
107
+ };
108
+ }
109
+ function isErrorPresentation(value) {
110
+ return typeof value === "object" && value !== null && typeof value.code === "string" && typeof value.message === "string" && typeof value.recovery === "string" && userRecoveryValues.has(value.recovery);
111
+ }
112
+ function readPrimaryAction(recovery, options) {
113
+ if (recovery === UserRecovery.None) return null;
114
+ const label = options.recoveryLabels?.[recovery] ?? DEFAULT_RECOVERY_LABELS[recovery];
115
+ if (!label) return null;
116
+ return {
117
+ recovery,
118
+ label,
119
+ href: options.recoveryLinks?.[recovery] ?? null
120
+ };
121
+ }
122
+ //#endregion
123
+ //#region src/signals/signal.ts
124
+ /**
125
+ * Minimal writable signal implementation.
126
+ * `set()` always publishes a write. Equality-based value-version suppression is
127
+ * handled by the underlying Rx signal for computed dependency validation.
128
+ */
129
+ function createSignal(initial, options) {
130
+ return RxStateSignal.fromInitialValue(initial, options);
131
+ }
132
+ /**
133
+ * Create a read-only view of a writable signal.
134
+ */
135
+ function readonlySignal(signal) {
136
+ return signal;
137
+ }
138
+ //#endregion
139
+ //#region src/popup/errors.ts
140
+ const PopupErrorCode = {
141
+ Blocked: "popup.blocked",
142
+ Closed: "popup.closed_by_user"
143
+ };
144
+ function readPopupErrorPresentationDescriptor(error, options = {}) {
145
+ return readErrorPresentationDescriptor(error, {
146
+ ...options,
147
+ codePresentations: {
148
+ [PopupErrorCode.Blocked]: {
149
+ title: "Popup was blocked",
150
+ description: "The browser blocked the popup window. Allow popups for this site, then try again.",
151
+ recovery: UserRecovery.Retry,
152
+ tone: ErrorPresentationTone.Warning
153
+ },
154
+ [PopupErrorCode.Closed]: {
155
+ title: "Popup was closed",
156
+ description: "The popup window was closed before the operation completed. Start the flow again.",
157
+ recovery: UserRecovery.RestartFlow,
158
+ tone: ErrorPresentationTone.Warning
159
+ },
160
+ ...options.codePresentations
161
+ }
162
+ });
163
+ }
164
+ //#endregion
165
+ //#region src/protocol/json-rpc/types.ts
166
+ const JsonRpcIdSchema = type("string | number");
167
+ const JsonRpcErrorPayloadSchema = type({
168
+ code: "number",
169
+ message: "string",
170
+ data: "unknown?"
171
+ });
172
+ const JsonRpcRequestMessageSchema = type({
173
+ jsonrpc: "\"2.0\"",
174
+ id: JsonRpcIdSchema,
175
+ method: "string",
176
+ params: "unknown?"
177
+ });
178
+ const JsonRpcNotificationMessageSchema = type({
179
+ jsonrpc: "\"2.0\"",
180
+ method: "string",
181
+ params: "unknown?"
182
+ });
183
+ const JsonRpcSuccessResponseMessageSchema = type({
184
+ jsonrpc: "\"2.0\"",
185
+ id: JsonRpcIdSchema,
186
+ result: "unknown"
187
+ });
188
+ const JsonRpcErrorResponseMessageSchema = type({
189
+ jsonrpc: "\"2.0\"",
190
+ id: JsonRpcIdSchema,
191
+ error: JsonRpcErrorPayloadSchema
192
+ });
193
+ const JsonRpcMessageSchema = JsonRpcRequestMessageSchema.or(JsonRpcNotificationMessageSchema).or(JsonRpcSuccessResponseMessageSchema).or(JsonRpcErrorResponseMessageSchema);
194
+ //#endregion
195
+ //#region src/protocol/json-rpc/create.ts
196
+ function createJsonRpcClient(options) {
197
+ return new JsonRpcClient(options);
198
+ }
199
+ function createJsonRpcServer(options) {
200
+ return new JsonRpcServer(options);
201
+ }
202
+ function createJsonRpcServerAndClient(options) {
203
+ return new JsonRpcServerAndClient(options);
204
+ }
205
+ var JsonRpcClient = class {
206
+ options;
207
+ onNotification;
208
+ notificationSubject = new RxEventSubject();
209
+ pendingRequests = /* @__PURE__ */ new Map();
210
+ disposed = false;
211
+ nextRequestId = 1;
212
+ constructor(options) {
213
+ this.options = options;
214
+ this.onNotification = this.notificationSubject;
215
+ }
216
+ request(method, params, requestOptions = {}) {
217
+ if (this.disposed) return Promise.reject(createJsonRpcDisposedError("client"));
218
+ const id = this.nextRequestId++;
219
+ const timeoutMs = requestOptions.timeoutMs ?? this.options.defaultRequestTimeoutMs;
220
+ return new Promise((resolve, reject) => {
221
+ const pendingRequest = {
222
+ method,
223
+ reject,
224
+ resolve
225
+ };
226
+ if (timeoutMs !== void 0) pendingRequest.timeoutHandle = this.options.time.setTimeout(() => {
227
+ this.pendingRequests.delete(id);
228
+ reject(/* @__PURE__ */ new Error(`JSON-RPC request timed out for ${method}.`));
229
+ }, timeoutMs);
230
+ this.pendingRequests.set(id, pendingRequest);
231
+ try {
232
+ this.options.send({
233
+ jsonrpc: "2.0",
234
+ id,
235
+ method,
236
+ params
237
+ });
238
+ } catch (error) {
239
+ this.clearPendingRequest(id);
240
+ reject(error);
241
+ }
242
+ });
243
+ }
244
+ notify(method, params) {
245
+ if (this.disposed) return;
246
+ this.options.send({
247
+ jsonrpc: "2.0",
248
+ method,
249
+ params
250
+ });
251
+ }
252
+ receive(message) {
253
+ if (this.disposed) return;
254
+ for (const parsedMessage of parseIncomingMessages(message)) {
255
+ if (isJsonRpcResponseMessage(parsedMessage)) {
256
+ this.resolvePendingRequest(parsedMessage);
257
+ continue;
258
+ }
259
+ if (isJsonRpcNotificationMessage(parsedMessage)) this.notificationSubject.next({
260
+ method: parsedMessage.method,
261
+ params: parsedMessage.params
262
+ });
263
+ }
264
+ }
265
+ rejectAllPendingRequests(reason) {
266
+ for (const [id, pendingRequest] of this.pendingRequests) {
267
+ this.clearPendingRequest(id);
268
+ pendingRequest.reject(reason);
269
+ }
270
+ }
271
+ dispose() {
272
+ if (this.disposed) return;
273
+ this.disposed = true;
274
+ this.rejectAllPendingRequests(/* @__PURE__ */ new Error("JSON-RPC client disposed."));
275
+ this.notificationSubject.complete();
276
+ }
277
+ [SYMBOL_DISPOSE]() {
278
+ this.dispose();
279
+ }
280
+ resolvePendingRequest(message) {
281
+ const pendingRequest = this.pendingRequests.get(message.id);
282
+ if (!pendingRequest) return;
283
+ this.clearPendingRequest(message.id);
284
+ if ("error" in message) {
285
+ pendingRequest.reject(/* @__PURE__ */ new Error(`JSON-RPC request failed for ${pendingRequest.method}: ${message.error.message}`));
286
+ return;
287
+ }
288
+ pendingRequest.resolve(message.result);
289
+ }
290
+ clearPendingRequest(id) {
291
+ const pendingRequest = this.pendingRequests.get(id);
292
+ if (!pendingRequest) return;
293
+ if (pendingRequest.timeoutHandle !== void 0) this.options.time.clearTimeout(pendingRequest.timeoutHandle);
294
+ this.pendingRequests.delete(id);
295
+ }
296
+ };
297
+ var JsonRpcServer = class {
298
+ options;
299
+ onRequest;
300
+ onNotification;
301
+ requestSubject = new RxEventSubject();
302
+ notificationSubject = new RxEventSubject();
303
+ disposed = false;
304
+ constructor(options) {
305
+ this.options = options;
306
+ this.onRequest = this.requestSubject;
307
+ this.onNotification = this.notificationSubject;
308
+ }
309
+ notify(method, params) {
310
+ if (this.disposed) return;
311
+ this.options.send({
312
+ jsonrpc: "2.0",
313
+ method,
314
+ params
315
+ });
316
+ }
317
+ receive(message) {
318
+ if (this.disposed) return;
319
+ for (const parsedMessage of parseIncomingMessages(message)) {
320
+ if (isJsonRpcRequestMessage(parsedMessage)) {
321
+ this.requestSubject.next({
322
+ id: parsedMessage.id,
323
+ method: parsedMessage.method,
324
+ params: parsedMessage.params
325
+ });
326
+ continue;
327
+ }
328
+ if (isJsonRpcNotificationMessage(parsedMessage)) this.notificationSubject.next({
329
+ method: parsedMessage.method,
330
+ params: parsedMessage.params
331
+ });
332
+ }
333
+ }
334
+ respondSuccess(id, result) {
335
+ if (this.disposed) return;
336
+ this.options.send({
337
+ jsonrpc: "2.0",
338
+ id,
339
+ result
340
+ });
341
+ }
342
+ respondError(id, error) {
343
+ if (this.disposed) return;
344
+ this.options.send({
345
+ jsonrpc: "2.0",
346
+ id,
347
+ error
348
+ });
349
+ }
350
+ dispose() {
351
+ if (this.disposed) return;
352
+ this.disposed = true;
353
+ this.requestSubject.complete();
354
+ this.notificationSubject.complete();
355
+ }
356
+ [SYMBOL_DISPOSE]() {
357
+ this.dispose();
358
+ }
359
+ };
360
+ var JsonRpcServerAndClient = class {
361
+ onNotification;
362
+ onRequest;
363
+ client;
364
+ server;
365
+ disposed = false;
366
+ constructor(options) {
367
+ this.client = new JsonRpcClient(options);
368
+ this.server = new JsonRpcServer(options);
369
+ this.onNotification = this.server.onNotification;
370
+ this.onRequest = this.server.onRequest;
371
+ }
372
+ request(method, params, options) {
373
+ return this.client.request(method, params, options);
374
+ }
375
+ notify(method, params) {
376
+ this.client.notify(method, params);
377
+ }
378
+ receive(message) {
379
+ for (const parsedMessage of parseIncomingMessages(message)) {
380
+ if (isJsonRpcResponseMessage(parsedMessage)) {
381
+ this.client.receive(parsedMessage);
382
+ continue;
383
+ }
384
+ this.server.receive(parsedMessage);
385
+ }
386
+ }
387
+ rejectAllPendingRequests(reason) {
388
+ this.client.rejectAllPendingRequests(reason);
389
+ }
390
+ respondSuccess(id, result) {
391
+ this.server.respondSuccess(id, result);
392
+ }
393
+ respondError(id, error) {
394
+ this.server.respondError(id, error);
395
+ }
396
+ dispose() {
397
+ if (this.disposed) return;
398
+ this.disposed = true;
399
+ this.client.dispose();
400
+ this.server.dispose();
401
+ }
402
+ [SYMBOL_DISPOSE]() {
403
+ this.dispose();
404
+ }
405
+ };
406
+ function parseIncomingMessages(message) {
407
+ if (!Array.isArray(message)) return parseJsonRpcMessage(message);
408
+ const parsedMessages = [];
409
+ for (const entry of message) parsedMessages.push(...parseJsonRpcMessage(entry));
410
+ return parsedMessages;
411
+ }
412
+ function parseJsonRpcMessage(message) {
413
+ const result = validateWithSchemaSync(JsonRpcMessageSchema, message);
414
+ return result.success ? [result.value] : [];
415
+ }
416
+ function isJsonRpcRequestMessage(message) {
417
+ return "method" in message && "id" in message;
418
+ }
419
+ function isJsonRpcResponseMessage(message) {
420
+ return "id" in message && !("method" in message);
421
+ }
422
+ function isJsonRpcNotificationMessage(message) {
423
+ return "method" in message && !("id" in message);
424
+ }
425
+ function createJsonRpcDisposedError(role) {
426
+ return /* @__PURE__ */ new Error(`JSON-RPC ${role} disposed.`);
427
+ }
428
+ //#endregion
429
+ //#region src/popup/session.ts
430
+ const PopupSessionControlMethod = {
431
+ Ready: "securitydept.popup.session.ready",
432
+ Ping: "securitydept.popup.session.ping",
433
+ Pong: "securitydept.popup.session.pong"
434
+ };
435
+ const DEFAULT_READY_TIMEOUT_MS = 1e4;
436
+ const DEFAULT_HEARTBEAT_INTERVAL_MS = 5e3;
437
+ const DEFAULT_HEARTBEAT_TIMEOUT_MS = 15e3;
438
+ var PopupClientSession = class {
439
+ failure = createSignal(null);
440
+ isActive = createSignal(false);
441
+ init$ = new ReplaySubject();
442
+ destroyed = createSignal(false);
443
+ destroyed$ = from(this.destroyed).pipe(distinctUntilChanged(), filter(Boolean), shareReplay(1));
444
+ constructor(options) {
445
+ const timestampScheduler = createAsyncSchedulerWithTimestampProvider(options.time);
446
+ const ready$ = new Subject();
447
+ const pong$ = new Subject();
448
+ const closed$ = from(options.closedStream).pipe(filter(Boolean));
449
+ const ping$ = merge(ready$.pipe(filter(Boolean)), pong$.pipe(filter(Boolean))).pipe(delayWhen(() => timer(options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS, timestampScheduler)));
450
+ from(this.init$).pipe(exhaustMap(() => from(options.jsonRpc.onNotification).pipe(filter(function isReadyNotification(event) {
451
+ return event.method === PopupSessionControlMethod.Ready;
452
+ }), take(1), timeout({
453
+ each: options.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS,
454
+ scheduler: timestampScheduler
455
+ }), map(() => true), catchError(() => of(false)))), takeUntil(this.destroyed$)).subscribe(ready$);
456
+ ping$.pipe(exhaustMap(() => from(options.jsonRpc.onNotification).pipe(filter(function isPongNotification(event) {
457
+ return event.method === PopupSessionControlMethod.Pong;
458
+ }), take(1), timeout({
459
+ first: options.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS,
460
+ scheduler: timestampScheduler
461
+ }), map(() => true), catchError(() => of(false)))), takeUntil(this.destroyed$)).subscribe(pong$);
462
+ merge(closed$.pipe(map(() => new ClientError({
463
+ kind: ClientErrorKind.Authorization,
464
+ code: PopupErrorCode.Closed,
465
+ message: "Popup window was closed before completing the login flow.",
466
+ recovery: UserRecovery.RestartFlow,
467
+ source: "popup"
468
+ }))), ready$.pipe(map((success) => !success ? new ClientError({
469
+ kind: ClientErrorKind.Protocol,
470
+ message: "Did not receive ready notification from popup within the expected time.",
471
+ recovery: UserRecovery.RestartFlow,
472
+ source: "popup"
473
+ }) : null)), pong$.pipe(map((success) => !success ? new ClientError({
474
+ kind: ClientErrorKind.Protocol,
475
+ message: "Did not receive pong notification from popup within the expected time.",
476
+ recovery: UserRecovery.RestartFlow,
477
+ source: "popup"
478
+ }) : null))).pipe(takeUntil(this.destroyed$), shareReplay({
479
+ bufferSize: 1,
480
+ refCount: false
481
+ })).subscribe((error) => this.failure.set(error));
482
+ merge(closed$.pipe(map(() => false)), ready$.pipe(map(Boolean)), pong$.pipe(map(Boolean))).pipe(takeUntil(this.destroyed$)).subscribe((nextIsActive) => {
483
+ this.isActive.set(nextIsActive);
484
+ });
485
+ }
486
+ init() {
487
+ this.init$.next(true);
488
+ }
489
+ dispose() {
490
+ this.destroyed.set(true);
491
+ }
492
+ [SYMBOL_DISPOSE]() {
493
+ this.dispose();
494
+ }
495
+ };
496
+ var PopupServerSession = class {
497
+ init$ = new ReplaySubject();
498
+ destroyed$$ = new BehaviorSubject(false);
499
+ destroyed$ = this.destroyed$$.pipe(distinctUntilChanged(), filter(Boolean), shareReplay(1));
500
+ constructor(options) {
501
+ const ready$ = from(this.init$);
502
+ const pong$ = from(options.jsonRpc.onNotification).pipe(filter(function isPing(event) {
503
+ return event.method === PopupSessionControlMethod.Ping;
504
+ }));
505
+ merge(ready$.pipe(map(function createReadyNotify() {
506
+ return { method: PopupSessionControlMethod.Ready };
507
+ })), pong$.pipe(map(function createPongNotify() {
508
+ return { method: PopupSessionControlMethod.Pong };
509
+ }))).pipe(takeUntil(this.destroyed$)).subscribe((event) => {
510
+ options.jsonRpc.notify(event.method, event.params);
511
+ });
512
+ }
513
+ init() {
514
+ this.init$.next(true);
515
+ }
516
+ dispose() {
517
+ this.destroyed$$.next(true);
518
+ }
519
+ [SYMBOL_DISPOSE]() {
520
+ this.dispose();
521
+ }
522
+ };
523
+ //#endregion
524
+ //#region src/popup/handle.ts
525
+ /**
526
+ * popup opener
527
+ */
528
+ var PopupClientWindowHandle = class {
529
+ messaging;
530
+ disposed = false;
531
+ jsonRpc;
532
+ session;
533
+ incomingSubscription;
534
+ closePopup;
535
+ constructor(options) {
536
+ this.messaging = options.messaging;
537
+ this.closePopup = options.close;
538
+ this.jsonRpc = createJsonRpcClient({
539
+ send: (message) => {
540
+ options.messaging.outgoing.next(message);
541
+ },
542
+ time: options.time
543
+ });
544
+ this.session = new PopupClientSession({
545
+ jsonRpc: this.jsonRpc,
546
+ time: options.time,
547
+ closedStream: options.closedStream
548
+ });
549
+ this.incomingSubscription = options.messaging.incoming.subscribe({ next: (message) => {
550
+ this.jsonRpc.receive(message);
551
+ } });
552
+ this.session.init();
553
+ }
554
+ get onNotification() {
555
+ return this.jsonRpc.onNotification;
556
+ }
557
+ get failure() {
558
+ return this.session.failure;
559
+ }
560
+ get isActive() {
561
+ return this.session.isActive;
562
+ }
563
+ async notify(method, params) {
564
+ this.jsonRpc.notify(method, params);
565
+ }
566
+ request(method, params, options) {
567
+ return this.jsonRpc.request(method, params, options);
568
+ }
569
+ close() {
570
+ this.closePopup();
571
+ }
572
+ dispose() {
573
+ if (this.disposed) return;
574
+ this.disposed = true;
575
+ this.session.dispose();
576
+ this.jsonRpc.dispose();
577
+ this.incomingSubscription.unsubscribe();
578
+ this.messaging.outgoing.complete();
579
+ }
580
+ [SYMBOL_DISPOSE]() {
581
+ this.dispose();
582
+ }
583
+ };
584
+ /**
585
+ * popup target
586
+ */
587
+ var PopupServerWindowHandle = class {
588
+ messaging;
589
+ disposed = false;
590
+ jsonRpc;
591
+ session;
592
+ incomingSubscription;
593
+ closePopup;
594
+ constructor(options) {
595
+ this.messaging = options.messaging;
596
+ this.closePopup = options.close;
597
+ this.jsonRpc = createJsonRpcServer({ send: (message) => {
598
+ options.messaging.outgoing.next(message);
599
+ } });
600
+ this.session = new PopupServerSession({ jsonRpc: this.jsonRpc });
601
+ this.incomingSubscription = options.messaging.incoming.subscribe({ next: (message) => {
602
+ this.jsonRpc.receive(message);
603
+ } });
604
+ this.session.init();
605
+ }
606
+ get onNotification() {
607
+ return this.jsonRpc.onNotification;
608
+ }
609
+ get onRequest() {
610
+ return this.jsonRpc.onRequest;
611
+ }
612
+ notify(method, params) {
613
+ this.jsonRpc.notify(method, params);
614
+ return Promise.resolve();
615
+ }
616
+ close() {
617
+ this.closePopup();
618
+ }
619
+ dispose() {
620
+ if (this.disposed) return;
621
+ this.disposed = true;
622
+ this.session.dispose();
623
+ this.jsonRpc.dispose();
624
+ this.incomingSubscription.unsubscribe();
625
+ this.messaging.outgoing.complete();
626
+ }
627
+ [SYMBOL_DISPOSE]() {
628
+ this.dispose();
629
+ }
630
+ };
631
+ //#endregion
632
+ export { createJsonRpcServerAndClient as a, createSignal as c, createJsonRpcServer as i, readonlySignal as l, PopupServerWindowHandle as n, PopupErrorCode as o, createJsonRpcClient as r, readPopupErrorPresentationDescriptor as s, PopupClientWindowHandle as t, readErrorPresentationDescriptor as u };
633
+
634
+ //# sourceMappingURL=handle-TnxwtQ4T.mjs.map