@fkn/lib 0.9.54 → 0.9.55

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.
@@ -544,24 +544,111 @@ type MountDescriptor = {
544
544
  };
545
545
  type RoomPermission = 'send' | 'receive' | 'remove' | 'block';
546
546
  type RoomPermissions = Readonly<Record<RoomPermission, boolean>>;
547
- /** What a member gets unless an override says otherwise. `maxMessageBytes` is measured on the wire: nonce plus ciphertext, base64url. */
547
+ /**
548
+ * What a member gets unless an override says otherwise. `maxMessageBytes` is measured on the wire: the
549
+ * envelope's text when there is one, plus the nonce and the ciphertext in base64url.
550
+ */
548
551
  type RoomDefaults = Readonly<{
549
552
  send: boolean;
550
553
  receive: boolean;
551
554
  maxMessageBytes: number;
552
555
  }>;
556
+ /** Plain JSON, as an envelope holds it. */
557
+ type RoomJson = null | boolean | number | string | readonly RoomJson[] | {
558
+ readonly [key: string]: RoomJson;
559
+ };
560
+ /**
561
+ * The plain part of a message in a room with a schema: a JSON object whose `type` names one of the room's
562
+ * types, at most 2,048 characters as `JSON.stringify` writes it. It is not sealed: FKN checks it against
563
+ * the room's schema, and FKN and every member who receives the message read it. Put nothing in it that
564
+ * is not theirs to read; what is, goes in the message's text, which is sealed as in any room.
565
+ */
566
+ type RoomEnvelope = {
567
+ readonly type: string;
568
+ readonly [field: string]: RoomJson;
569
+ };
553
570
  /** A participant as this room sees them. The id is fresh in every room. */
554
571
  type RoomMember = {
555
572
  id: string;
556
573
  permissions: RoomPermissions;
557
574
  maxMessageBytes: number;
558
575
  };
576
+ /**
577
+ * `text` is the sealed part, opened. `envelope` is the plain part, null for a message sent without one:
578
+ * in a room with no schema, or before the room had one. A message whose sealed part does not open under
579
+ * its own envelope is never delivered, so FKN cannot change an envelope or move a text under another.
580
+ */
559
581
  type RoomMessage = {
560
582
  seq: number;
561
583
  from: string;
562
584
  at: number;
563
585
  text: string;
586
+ envelope: RoomEnvelope | null;
564
587
  };
588
+ /** One type of message a room takes, and its rules. */
589
+ type RoomType = Readonly<{
590
+ /**
591
+ * The JSON Schema (draft 2020-12) the whole envelope must fit, `type` included: what `z.toJSONSchema`
592
+ * writes for a `z.object` of plain fields. Taken: `type` (a name or a list naming each type once),
593
+ * `properties`, `required` (each name once, and only names its `properties` declare),
594
+ * `additionalProperties`, `minProperties`, `maxProperties`, `items`, `prefixItems`, `minItems`,
595
+ * `maxItems`, `minLength`, `maxLength`, `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`,
596
+ * `multipleOf`, `const` and `enum` (at most 64 values) of strings, numbers, booleans or null, `true`
597
+ * and `false` as subschemas, `$schema` naming draft 2020-12, and the annotations `title`,
598
+ * `description`, `$comment`, `deprecated`, `readOnly`, `writeOnly`, `examples` and `default`; at most
599
+ * 64 subschemas, nested at most 256 levels deep. Refused `invalid` (`rooms: the schema is not one a
600
+ * room can take`): every combinator, so the `anyOf` zod writes for `.nullable()` or `z.union` over a
601
+ * field with a bound or a literal (use `.optional()`, or declare each member as its own type; over bare
602
+ * fields zod writes a type list, which is taken), `z.record`, `.regex()`, `z.email()`, `.meta({ id })`
603
+ * and recursive schemas; and a field named after anything a plain object already has, such as
604
+ * `constructor` or `toString`.
605
+ */
606
+ envelope: Readonly<Record<string, unknown>>;
607
+ /**
608
+ * Who may send it. `members`, the default: anyone the room lets send. `accounts`: only members signed
609
+ * in to an FKN account; a guest is refused `denied` (`rooms: sending this needs an account`), whatever
610
+ * it was granted. `owner`: the owner alone (`denied`, `rooms: only the owner sends this type`), and on
611
+ * a room claimed under an app's scope only through the app that claimed it (`denied`, `rooms: only the
612
+ * app that claimed the room can change it`). The owner passes every rule; a member the room does not
613
+ * let send sends no type at all.
614
+ */
615
+ send?: 'owner' | 'accounts' | 'members';
616
+ /**
617
+ * The most one such message may be on the wire, its envelope and its sealed text together, 1 to
618
+ * 33,554,432, refused `too-large` (`rooms: the message is too large`) past it, the owner's too. The
619
+ * member's own `maxMessageBytes` applies as well.
620
+ */
621
+ maxBytes?: number;
622
+ /**
623
+ * At most this many messages, or bytes on the wire, of this type waiting in the room per account,
624
+ * among those it sent in the last 30 days; each a whole number from 1 to 500,000,000, at least one of
625
+ * the two, and only with `send: 'accounts'`. The owner is not counted, and nothing is counted in a room
626
+ * that keeps no messages. At the limit a send, or an edit that grows a message, is refused `full`
627
+ * (`rooms: you have as many of these here as the room allows`) until one of them is deleted or 30 days
628
+ * pass since it was sent; an edit does not restart the 30 days. A limit set later counts only what is
629
+ * sent after it. To count, the room keeps beside each counted message a code made from the sender's
630
+ * account and the room key, never the account id, until the message is deleted or for 30 days at most.
631
+ */
632
+ perAccount?: Readonly<{
633
+ messages?: number;
634
+ bytes?: number;
635
+ }>;
636
+ }>;
637
+ /**
638
+ * The types a room's messages may have, 1 to 16, each named with 1 to 32 of `a` to `z`, `0` to `9` and
639
+ * `-`, a letter first; at most 16,384 characters as JSON. `version` is the app's own number, a whole
640
+ * number from 1 to 2,147,483,647: `setSchema` replaces the room's schema only with a higher one, so set
641
+ * it on every open and raise it to change the schema. `maxStoredBytes` is the most the room keeps, 1 to
642
+ * 500,000,000, counted as the mailbox counts: past it a send, or an edit that grows a message, is
643
+ * refused `storage` (`rooms: the mailbox is full`), nothing is ever evicted, and the owner's own cap from
644
+ * fkn.app still applies, the smaller winning. A room keeps its schema until the room itself ends, and
645
+ * messages already stored are never checked again.
646
+ */
647
+ type RoomSchema = Readonly<{
648
+ version: number;
649
+ types: Readonly<Record<string, RoomType>>;
650
+ maxStoredBytes?: number;
651
+ }>;
565
652
  /**
566
653
  * What a claimed room's mailbox holds, as the room last said. Null for a room that keeps no messages:
567
654
  * one nobody has claimed, or a claim whose mailbox is off. `cap` is the most it stores: 500 MB, or the
@@ -604,6 +691,11 @@ type RoomEvent =
604
691
  type: 'defaults';
605
692
  defaults: RoomDefaults;
606
693
  } |
694
+ /** the room's schema was replaced by one of a higher `version`, from the next send on */
695
+ {
696
+ type: 'schema';
697
+ schema: RoomSchema;
698
+ } |
607
699
  /**
608
700
  * the room was claimed, released (by its app, or by the account in its fkn.app settings) or
609
701
  * dissolved, or its mailbox was turned off or on; `owner` is the owner's member id, or '' while a
@@ -632,6 +724,14 @@ type RoomOpenOptions = {
632
724
  /** honoured only by the join that brings the room into being */
633
725
  members?: number;
634
726
  defaults?: Partial<RoomDefaults>;
727
+ /**
728
+ * Honoured only by the join that brings the room into being, as `defaults` is: an existing room keeps
729
+ * its own, and `setSchema` changes it. One the room cannot take refuses the open `invalid` (`rooms: the
730
+ * schema is not one a room can take`) and no room is left behind. An fkn.app older than room schemas
731
+ * refuses the open `unavailable` (`rooms: room schemas are not available`), after leaving the room it
732
+ * joined, so a room nobody else is in ends rather than stay without the schema.
733
+ */
734
+ schema?: RoomSchema;
635
735
  /** the room key, 32 bytes base64url, minted when absent. Deriving one from something people already share is how a name becomes a rendezvous. */
636
736
  key?: string;
637
737
  /**
@@ -757,18 +857,41 @@ type RoomHandle = {
757
857
  * handle without it rather than store what the app asked it not to.
758
858
  */
759
859
  mailboxSwitch?: true;
860
+ /**
861
+ * set by a broker that carries room schemas: `schema` on a join, `setSchema`, and an envelope on `send`
862
+ * and `edit`. A broker older than that drops the option and the envelope, so the lib refuses all three
863
+ * on a handle without it rather than send a typed message untyped.
864
+ */
865
+ schemas?: true;
760
866
  defaults: () => Promise<RoomDefaults>;
761
867
  members: () => Promise<RoomMember[]>;
762
- /** sealed before it leaves the browser and refused, never truncated, past this member's `maxMessageBytes` on the wire */
763
- send: (text: string) => Promise<RoomsFail | {
868
+ /** the room's schema as the room last said, null for a room without one */
869
+ schema: () => Promise<RoomSchema | null>;
870
+ /**
871
+ * sealed before it leaves the browser and refused, never truncated, past this member's
872
+ * `maxMessageBytes` on the wire, or the type's `maxBytes`. `envelope` is the envelope's JSON text, as
873
+ * the lib wrote it: sent byte for byte in plain beside the sealed text, which is sealed with it.
874
+ */
875
+ send: (text: string, envelope?: string) => Promise<RoomsFail | {
764
876
  ok: true;
765
877
  }>;
766
878
  /**
767
- * a stored message's text, replaced: the sender's own, or any as the owner. From another app of the
768
- * claim's account on a room claimed under an app's scope, `denied` (`rooms: only the app that claimed
769
- * the room can change it`), the account's own messages included, as `claim` says.
879
+ * a stored message's text, replaced: the sender's own, or any as the owner. Checked as a send is, and
880
+ * `envelope` as on `send`, keeping the message's type. From another app of the claim's account on a
881
+ * room claimed under an app's scope, `denied` (`rooms: only the app that claimed the room can change
882
+ * it`), the account's own messages included, as `claim` says.
883
+ */
884
+ edit: (seq: number, text: string, envelope?: string) => Promise<RoomsFail | {
885
+ ok: true;
886
+ }>;
887
+ /**
888
+ * the room's schema, replaced by one of a higher `version`; the same one answers `{ ok: true }` and
889
+ * changes nothing, and a lower one, or another schema at the same one, is refused `invalid` (`rooms:
890
+ * the room holds a newer schema`). From the owner only (`denied`, `rooms: not the room owner`); from
891
+ * another app of the claim's account on a room claimed under an app's scope, `denied` (`rooms: only the
892
+ * app that claimed the room can change it`), as `claim` says.
770
893
  */
771
- edit: (seq: number, text: string) => Promise<RoomsFail | {
894
+ setSchema: (schema: RoomSchema) => Promise<RoomsFail | {
772
895
  ok: true;
773
896
  }>;
774
897
  /**
@@ -1301,4 +1424,4 @@ type Resolvers = {
1301
1424
  hideInstallPrompt: () => void;
1302
1425
  };
1303
1426
  //#endregion
1304
- export { RoomHandle as $, MiddleGotoOptions as A, SurfaceRect as At, ProxyFetch as B, WINDOW_JAR_MODE_TIMEOUT_MS as Bt, FrameMessageRelay as C, StorageProgress as Ct, IpFamily as D, StoredHandle as Dt, InstalledPackage as E, StorageQuota as Et, PackageResult as F, UdpDatagram as Ft, Radii as G, ProxyFetchInput as H, WriteData as Ht, PackagesErrorCode as I, UdpSocketOptions as It, RoomClaimOptions as J, Resolvers as K, PackagesFail as L, UdpSocketResult as Lt, OverlayRect as M, TcpSocketListenerResult as Mt, OverlayState as N, TcpSocketOptions as Nt, JAR_ANCHOR_MESSAGE as O, StoredObject as Ot, PackageQuery as P, TcpSocketResult as Pt, RoomEvent as Q, PickOptions as R, WINDOW_HANDSHAKE_TIMEOUT_MS as Rt, FrameFetchScope as S, StorageFail as St, InstallOptions as T, StoragePutWire as Tt, Quota as U, JarSeed as Ut, ProxyFetchInit as V, WindowMiddleControl as Vt, ROOM_TEMPORARY_MS as W, JarSeedCookie as Wt, RoomDefaults as X, RoomCreateOptions as Y, RoomEnd as Z, DnsLookup as _, ShellFrameMessage as _t, AccountChange as a, RoomPermission as at, FrameConsentAnswer as b, StorageEntry as bt, AdoptRequest as c, RoomsFail as ct, ConflictRequest as d, SHELL_FRAME_MESSAGE as dt, RoomJoinOptions as et, ConflictSide as f, SHELL_JAR_MESSAGE as ft, DisplayLevel as g, ShellControl as gt, DisplayCause as h, SetOverlayHost as ht, Account as i, RoomOpenOptions as it, MountDescriptor as j, TcpSocketListenerOptions as jt, MiddleControl as k, StoredPage as kt, AdoptState as l, SHELL_ATTACH_ERROR as lt, ConnectOptions as m, STORAGE_REFUSALS as mt, ATTACH_WINDOW_KEY as n, RoomMember as nt, AccountPinOptions as o, RoomPermissions as ot, ConnectAvailability as p, SHELL_JAR_UNREACHABLE as pt, RoomBacklog as q, ATTACH_WINDOW_MESSAGE as r, RoomMessage as rt, AddressLookupResult as s, RoomsErrorCode as st, ATTACH_FRAME_KEY as t, RoomMailbox as tt, ConflictChoice as u, SHELL_CONTROL_KEY as ut, EncryptionState as v, ShellGotoOptions as vt, HiddenSurface as w, StoragePutOptions as wt, FrameConsentRequest as x, StorageErrorCode as xt, FRAME_MESSAGE as y, ShellJarUnreachable as yt, Placement as z, WINDOW_HELLO_TIMEOUT_MS as zt };
1427
+ export { RoomEvent as $, MiddleGotoOptions as A, StorageQuota as At, ProxyFetch as B, UdpSocketOptions as Bt, FrameMessageRelay as C, ShellJarUnreachable as Ct, IpFamily as D, StorageProgress as Dt, InstalledPackage as E, StorageFail as Et, PackageResult as F, TcpSocketListenerOptions as Ft, Radii as G, WindowMiddleControl as Gt, ProxyFetchInput as H, WINDOW_HANDSHAKE_TIMEOUT_MS as Ht, PackagesErrorCode as I, TcpSocketListenerResult as It, RoomClaimOptions as J, JarSeedCookie as Jt, Resolvers as K, WriteData as Kt, PackagesFail as L, TcpSocketOptions as Lt, OverlayRect as M, StoredObject as Mt, OverlayState as N, StoredPage as Nt, JAR_ANCHOR_MESSAGE as O, StoragePutOptions as Ot, PackageQuery as P, SurfaceRect as Pt, RoomEnvelope as Q, PickOptions as R, TcpSocketResult as Rt, FrameFetchScope as S, ShellGotoOptions as St, InstallOptions as T, StorageErrorCode as Tt, Quota as U, WINDOW_HELLO_TIMEOUT_MS as Ut, ProxyFetchInit as V, UdpSocketResult as Vt, ROOM_TEMPORARY_MS as W, WINDOW_JAR_MODE_TIMEOUT_MS as Wt, RoomDefaults as X, RoomCreateOptions as Y, RoomEnd as Z, DnsLookup as _, SHELL_JAR_UNREACHABLE as _t, AccountChange as a, RoomMessage as at, FrameConsentAnswer as b, ShellControl as bt, AdoptRequest as c, RoomPermissions as ct, ConflictRequest as d, RoomsErrorCode as dt, RoomHandle as et, ConflictSide as f, RoomsFail as ft, DisplayLevel as g, SHELL_JAR_MESSAGE as gt, DisplayCause as h, SHELL_FRAME_MESSAGE as ht, Account as i, RoomMember as it, MountDescriptor as j, StoredHandle as jt, MiddleControl as k, StoragePutWire as kt, AdoptState as l, RoomSchema as lt, ConnectOptions as m, SHELL_CONTROL_KEY as mt, ATTACH_WINDOW_KEY as n, RoomJson as nt, AccountPinOptions as o, RoomOpenOptions as ot, ConnectAvailability as p, SHELL_ATTACH_ERROR as pt, RoomBacklog as q, JarSeed as qt, ATTACH_WINDOW_MESSAGE as r, RoomMailbox as rt, AddressLookupResult as s, RoomPermission as st, ATTACH_FRAME_KEY as t, RoomJoinOptions as tt, ConflictChoice as u, RoomType as ut, EncryptionState as v, STORAGE_REFUSALS as vt, HiddenSurface as w, StorageEntry as wt, FrameConsentRequest as x, ShellFrameMessage as xt, FRAME_MESSAGE as y, SetOverlayHost as yt, Placement as z, UdpDatagram as zt };
package/contract.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { d as CookieMatchWire, u as ClearCookiesWire } from "./index-BQ5OZQhf.js";
2
- import { $ as RoomHandle, A as MiddleGotoOptions, At as SurfaceRect, B as ProxyFetch, Bt as WINDOW_JAR_MODE_TIMEOUT_MS, C as FrameMessageRelay, Ct as StorageProgress, D as IpFamily, Dt as StoredHandle, E as InstalledPackage, Et as StorageQuota, F as PackageResult, Ft as UdpDatagram, G as Radii, H as ProxyFetchInput, Ht as WriteData, I as PackagesErrorCode, It as UdpSocketOptions, J as RoomClaimOptions, K as Resolvers, L as PackagesFail, Lt as UdpSocketResult, M as OverlayRect, Mt as TcpSocketListenerResult, N as OverlayState, Nt as TcpSocketOptions, O as JAR_ANCHOR_MESSAGE, Ot as StoredObject, P as PackageQuery, Pt as TcpSocketResult, Q as RoomEvent, R as PickOptions, Rt as WINDOW_HANDSHAKE_TIMEOUT_MS, S as FrameFetchScope, St as StorageFail, T as InstallOptions, Tt as StoragePutWire, U as Quota, Ut as JarSeed, V as ProxyFetchInit, Vt as WindowMiddleControl, W as ROOM_TEMPORARY_MS, Wt as JarSeedCookie, X as RoomDefaults, Y as RoomCreateOptions, Z as RoomEnd, _ as DnsLookup, _t as ShellFrameMessage, a as AccountChange, at as RoomPermission, b as FrameConsentAnswer, bt as StorageEntry, c as AdoptRequest, ct as RoomsFail, d as ConflictRequest, dt as SHELL_FRAME_MESSAGE, et as RoomJoinOptions, f as ConflictSide, ft as SHELL_JAR_MESSAGE, g as DisplayLevel, gt as ShellControl, h as DisplayCause, ht as SetOverlayHost, i as Account, it as RoomOpenOptions, j as MountDescriptor, jt as TcpSocketListenerOptions, k as MiddleControl, kt as StoredPage, l as AdoptState, lt as SHELL_ATTACH_ERROR, m as ConnectOptions, mt as STORAGE_REFUSALS, n as ATTACH_WINDOW_KEY, nt as RoomMember, o as AccountPinOptions, ot as RoomPermissions, p as ConnectAvailability, pt as SHELL_JAR_UNREACHABLE, q as RoomBacklog, r as ATTACH_WINDOW_MESSAGE, rt as RoomMessage, s as AddressLookupResult, st as RoomsErrorCode, t as ATTACH_FRAME_KEY, tt as RoomMailbox, u as ConflictChoice, ut as SHELL_CONTROL_KEY, v as EncryptionState, vt as ShellGotoOptions, w as HiddenSurface, wt as StoragePutOptions, x as FrameConsentRequest, xt as StorageErrorCode, y as FRAME_MESSAGE, yt as ShellJarUnreachable, z as Placement, zt as WINDOW_HELLO_TIMEOUT_MS } from "./contract-CMQOic3K.js";
2
+ import { $ as RoomEvent, A as MiddleGotoOptions, At as StorageQuota, B as ProxyFetch, Bt as UdpSocketOptions, C as FrameMessageRelay, Ct as ShellJarUnreachable, D as IpFamily, Dt as StorageProgress, E as InstalledPackage, Et as StorageFail, F as PackageResult, Ft as TcpSocketListenerOptions, G as Radii, Gt as WindowMiddleControl, H as ProxyFetchInput, Ht as WINDOW_HANDSHAKE_TIMEOUT_MS, I as PackagesErrorCode, It as TcpSocketListenerResult, J as RoomClaimOptions, Jt as JarSeedCookie, K as Resolvers, Kt as WriteData, L as PackagesFail, Lt as TcpSocketOptions, M as OverlayRect, Mt as StoredObject, N as OverlayState, Nt as StoredPage, O as JAR_ANCHOR_MESSAGE, Ot as StoragePutOptions, P as PackageQuery, Pt as SurfaceRect, Q as RoomEnvelope, R as PickOptions, Rt as TcpSocketResult, S as FrameFetchScope, St as ShellGotoOptions, T as InstallOptions, Tt as StorageErrorCode, U as Quota, Ut as WINDOW_HELLO_TIMEOUT_MS, V as ProxyFetchInit, Vt as UdpSocketResult, W as ROOM_TEMPORARY_MS, Wt as WINDOW_JAR_MODE_TIMEOUT_MS, X as RoomDefaults, Y as RoomCreateOptions, Z as RoomEnd, _ as DnsLookup, _t as SHELL_JAR_UNREACHABLE, a as AccountChange, at as RoomMessage, b as FrameConsentAnswer, bt as ShellControl, c as AdoptRequest, ct as RoomPermissions, d as ConflictRequest, dt as RoomsErrorCode, et as RoomHandle, f as ConflictSide, ft as RoomsFail, g as DisplayLevel, gt as SHELL_JAR_MESSAGE, h as DisplayCause, ht as SHELL_FRAME_MESSAGE, i as Account, it as RoomMember, j as MountDescriptor, jt as StoredHandle, k as MiddleControl, kt as StoragePutWire, l as AdoptState, lt as RoomSchema, m as ConnectOptions, mt as SHELL_CONTROL_KEY, n as ATTACH_WINDOW_KEY, nt as RoomJson, o as AccountPinOptions, ot as RoomOpenOptions, p as ConnectAvailability, pt as SHELL_ATTACH_ERROR, q as RoomBacklog, qt as JarSeed, r as ATTACH_WINDOW_MESSAGE, rt as RoomMailbox, s as AddressLookupResult, st as RoomPermission, t as ATTACH_FRAME_KEY, tt as RoomJoinOptions, u as ConflictChoice, ut as RoomType, v as EncryptionState, vt as STORAGE_REFUSALS, w as HiddenSurface, wt as StorageEntry, x as FrameConsentRequest, xt as ShellFrameMessage, y as FRAME_MESSAGE, yt as SetOverlayHost, z as Placement, zt as UdpDatagram } from "./contract-DFycgFJK.js";
3
3
  import { o as TcpSocketOption, x as UdpSocketOption } from "./wire-Fk5pJaoy.js";
4
- export { ATTACH_FRAME_KEY, ATTACH_WINDOW_KEY, ATTACH_WINDOW_MESSAGE, Account, AccountChange, AccountPinOptions, AddressLookupResult, AdoptRequest, AdoptState, type ClearCookiesWire, ConflictChoice, ConflictRequest, ConflictSide, ConnectAvailability, ConnectOptions, type CookieMatchWire, DisplayCause, DisplayLevel, DnsLookup, EncryptionState, FRAME_MESSAGE, FrameConsentAnswer, FrameConsentRequest, FrameFetchScope, FrameMessageRelay, HiddenSurface, InstallOptions, InstalledPackage, IpFamily, JAR_ANCHOR_MESSAGE, type JarSeed, type JarSeedCookie, MiddleControl, MiddleGotoOptions, MountDescriptor, OverlayRect, OverlayState, PackageQuery, PackageResult, PackagesErrorCode, PackagesFail, PickOptions, Placement, ProxyFetch, ProxyFetchInit, ProxyFetchInput, Quota, ROOM_TEMPORARY_MS, Radii, Resolvers, RoomBacklog, RoomClaimOptions, RoomCreateOptions, RoomDefaults, RoomEnd, RoomEvent, RoomHandle, RoomJoinOptions, RoomMailbox, RoomMember, RoomMessage, RoomOpenOptions, RoomPermission, RoomPermissions, RoomsErrorCode, RoomsFail, SHELL_ATTACH_ERROR, SHELL_CONTROL_KEY, SHELL_FRAME_MESSAGE, SHELL_JAR_MESSAGE, SHELL_JAR_UNREACHABLE, STORAGE_REFUSALS, SetOverlayHost, ShellControl, ShellFrameMessage, ShellGotoOptions, ShellJarUnreachable, StorageEntry, StorageErrorCode, StorageFail, StorageProgress, StoragePutOptions, StoragePutWire, StorageQuota, StoredHandle, StoredObject, StoredPage, SurfaceRect, TcpSocketListenerOptions, TcpSocketListenerResult, type TcpSocketOption, TcpSocketOptions, TcpSocketResult, UdpDatagram, type UdpSocketOption, UdpSocketOptions, UdpSocketResult, WINDOW_HANDSHAKE_TIMEOUT_MS, WINDOW_HELLO_TIMEOUT_MS, WINDOW_JAR_MODE_TIMEOUT_MS, WindowMiddleControl, WriteData };
4
+ export { ATTACH_FRAME_KEY, ATTACH_WINDOW_KEY, ATTACH_WINDOW_MESSAGE, Account, AccountChange, AccountPinOptions, AddressLookupResult, AdoptRequest, AdoptState, type ClearCookiesWire, ConflictChoice, ConflictRequest, ConflictSide, ConnectAvailability, ConnectOptions, type CookieMatchWire, DisplayCause, DisplayLevel, DnsLookup, EncryptionState, FRAME_MESSAGE, FrameConsentAnswer, FrameConsentRequest, FrameFetchScope, FrameMessageRelay, HiddenSurface, InstallOptions, InstalledPackage, IpFamily, JAR_ANCHOR_MESSAGE, type JarSeed, type JarSeedCookie, MiddleControl, MiddleGotoOptions, MountDescriptor, OverlayRect, OverlayState, PackageQuery, PackageResult, PackagesErrorCode, PackagesFail, PickOptions, Placement, ProxyFetch, ProxyFetchInit, ProxyFetchInput, Quota, ROOM_TEMPORARY_MS, Radii, Resolvers, RoomBacklog, RoomClaimOptions, RoomCreateOptions, RoomDefaults, RoomEnd, RoomEnvelope, RoomEvent, RoomHandle, RoomJoinOptions, RoomJson, RoomMailbox, RoomMember, RoomMessage, RoomOpenOptions, RoomPermission, RoomPermissions, RoomSchema, RoomType, RoomsErrorCode, RoomsFail, SHELL_ATTACH_ERROR, SHELL_CONTROL_KEY, SHELL_FRAME_MESSAGE, SHELL_JAR_MESSAGE, SHELL_JAR_UNREACHABLE, STORAGE_REFUSALS, SetOverlayHost, ShellControl, ShellFrameMessage, ShellGotoOptions, ShellJarUnreachable, StorageEntry, StorageErrorCode, StorageFail, StorageProgress, StoragePutOptions, StoragePutWire, StorageQuota, StoredHandle, StoredObject, StoredPage, SurfaceRect, TcpSocketListenerOptions, TcpSocketListenerResult, type TcpSocketOption, TcpSocketOptions, TcpSocketResult, UdpDatagram, type UdpSocketOption, UdpSocketOptions, UdpSocketResult, WINDOW_HANDSHAKE_TIMEOUT_MS, WINDOW_HELLO_TIMEOUT_MS, WINDOW_JAR_MODE_TIMEOUT_MS, WindowMiddleControl, WriteData };
package/dgram.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { K as Resolvers, Lt as UdpSocketResult } from "./contract-CMQOic3K.js";
1
+ import { K as Resolvers, Vt as UdpSocketResult } from "./contract-DFycgFJK.js";
2
2
  import { x as UdpSocketOption } from "./wire-Fk5pJaoy.js";
3
- import "./api-C-VvG5P-.js";
3
+ import "./api-BSpQkgnM.js";
4
4
  import { Buffer } from "buffer";
5
5
  import { AddressInfo } from "net";
6
6
  import { EventEmitter } from "events";
package/dns.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { s as AddressLookupResult } from "./contract-CMQOic3K.js";
1
+ import { s as AddressLookupResult } from "./contract-DFycgFJK.js";
2
2
  declare namespace dns_d_exports {
3
3
  export { AddressLookupResult, lookup };
4
4
  }
package/http.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as Socket, t as Server$1 } from "./net-B8YQuB9E.js";
1
+ import { n as Socket, t as Server$1 } from "./net-eEjhJ0AE.js";
2
2
  import { Buffer } from "buffer";
3
3
  import { Stream } from "stream";
4
4
  import { IncomingHttpHeaders, OutgoingHttpHeaders, RequestOptions } from "http";
package/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { $ as GateTools, A as attachFramePermission, B as CategoryMeta, C as FrameWindowRefusal, D as StorageState, E as Locator, F as LegacyPermissionRequest, G as VideoElementState, H as handleRevivableModules, I as PermissionGrant, J as isType, K as box, L as PermissionRequest, M as gotoPermission, N as CategoryGrant, O as StorageStateCookie, P as CategoryRequest, Q as Gate, R as permissions, S as FrameWindowOptions, T as GotoOptions, U as BoxedVideoElement, V as PermissionCategory, W as RemoteVideoElement, X as type, Y as revive, Z as Executor, _ as FrameEventMap, a as AttachCookies, b as FramePostMessageOptions, c as BlankPage, d as CookieMatchWire, et as OperationRequest, f as Frame, g as FrameEventListener, h as FrameDocumentEvent, i as AddScriptTagOptions, j as createFrame, k as WindowFrame, l as ClearCookiesOptions, m as FrameBackendEvent, o as AttachFrameOptions, p as FrameBackend, q as createVideoElementHandle, r as AttachFrameFunction, s as AttachWindowOptions, t as ATTACH_FRAME_EVENT_KEY, tt as SelectorPart, u as ClearCookiesWire, v as FrameLocator, w as FrameWindowRefusedError, x as FrameWindowBlockedError, y as FrameMessageEvent, z as CATEGORIES } from "./index-BQ5OZQhf.js";
2
2
  import { $ as isLocatorDenied, A as setRequestHeaderRule, B as fetchLocalPermission, C as assertAttachableFrameUrl, D as RequestHeaderRule, E as HeaderOperation, F as FetchInit, G as assertForgeableHeaders, H as isBlockedFetchUrl, I as ProxyFetchRequest, J as LOCATOR_DENIED, K as assertOneCookieIdentity, L as assertFetchableUrl, M as SiteCookie, N as cookies, O as modifyRequestHeadersPermission, P as readCookiePermission, Q as TimeoutError, S as MAX_REASON_LENGTH, T as isBlockedFrameUrl, U as isLocalNetworkUrl, V as fetchPermission, W as FORGEABLE_HEADERS, X as LOCATOR_INVALID, Y as LOCATOR_ERROR, Z as LOCATOR_UNSUPPORTED, _ as BackgroundStoppedError, b as PermissionDeniedError, c as setMissingExtensionHandler, d as ExtensionHandshake, et as isLocatorInvalid, f as ExtensionOperationUnsupportedError, g as BACKGROUND_STOPPED, h as supportsOperation, i as promptInstall, j as CookieDetails, k as removeRequestHeaderRule, l as waitForExtensionExposure, m as REQUIRED_EXTENSION_ABI, n as fetch, nt as isTerminalError, o as isExtensionExposed, p as ExtensionOutdatedError, q as hasForgedCookie, s as readExtensionHandshake, t as extension_d_exports, tt as isLocatorUnsupported, u as EXTENSION_ABI, v as isBackgroundStopped, w as assertLockdownApplicable, x as isPermissionDenied, y as PERMISSION_DENIED, z as fetchCredentialedPermission } from "./extension-kE9yzbkW.js";
3
3
  import { t as account_d_exports } from "./account.js";
4
- import { n as cloud_d_exports } from "./cloud-S8hQywqV.js";
4
+ import { n as cloud_d_exports } from "./cloud-BslRIoKs.js";
5
5
  import { t as dns_d_exports } from "./dns.js";
6
- import { s as net_d_exports } from "./net-B8YQuB9E.js";
6
+ import { s as net_d_exports } from "./net-eEjhJ0AE.js";
7
7
  import { t as dgram_d_exports } from "./dgram.js";
8
8
  import { t as http_d_exports } from "./http.js";
9
9
  import { t as desktop_d_exports } from "./desktop.js";
@@ -1,6 +1,6 @@
1
- import { K as Resolvers, Mt as TcpSocketListenerResult, Pt as TcpSocketResult } from "./contract-CMQOic3K.js";
1
+ import { It as TcpSocketListenerResult, K as Resolvers, Rt as TcpSocketResult } from "./contract-DFycgFJK.js";
2
2
  import { o as TcpSocketOption } from "./wire-Fk5pJaoy.js";
3
- import "./api-C-VvG5P-.js";
3
+ import "./api-BSpQkgnM.js";
4
4
  import { AddressInfo, ListenOptions, Server, ServerOpts, Socket, SocketConnectOpts, SocketConstructorOpts } from "net";
5
5
  import { DuplexOptions, Stream } from "stream";
6
6
  import { EventEmitter } from "events";
package/net.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as createConnection, c as isIP, i as connect, l as isIPv4, n as Socket, o as createServer, r as _default, t as Server, u as isIPv6 } from "./net-B8YQuB9E.js";
1
+ import { a as createConnection, c as isIP, i as connect, l as isIPv4, n as Socket, o as createServer, r as _default, t as Server, u as isIPv6 } from "./net-eEjhJ0AE.js";
2
2
  export { Server, Socket, _default, _default as default, connect, createConnection, createServer, isIP, isIPv4, isIPv6 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fkn/lib",
3
- "version": "0.9.54",
3
+ "version": "0.9.55",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/packages.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { At as SurfaceRect, E as InstalledPackage, F as PackageResult, G as Radii, I as PackagesErrorCode, P as PackageQuery, R as PickOptions, T as InstallOptions, m as ConnectOptions, z as Placement } from "./contract-CMQOic3K.js";
1
+ import { E as InstalledPackage, F as PackageResult, G as Radii, I as PackagesErrorCode, P as PackageQuery, Pt as SurfaceRect, R as PickOptions, T as InstallOptions, m as ConnectOptions, z as Placement } from "./contract-DFycgFJK.js";
2
2
  import { Remote } from "osra";
3
3
  declare namespace packages_d_exports {
4
4
  export { AppConnectOptions, Connect, ConnectOptions, ConnectPayload, IncomingConnection, IncomingConnectionInfo, InstallOptions, InstalledPackage, MountOptions, MountedPackage, PackageConnection, PackageQuery, PackageResult, PackageView, PackagesError, PackagesErrorCode, PickOptions, Placement, Radii, RawPackageConnection, ShowOptions, SurfaceRect, attach, connect, hide, install, isVisible, list, mount, onConnect, onVisibilityChange, pick, search, show, uninstall };
@@ -1,5 +1,5 @@
1
- import { K as Resolvers } from "./contract-CMQOic3K.js";
2
- import "./api-C-VvG5P-.js";
1
+ import { K as Resolvers } from "./contract-DFycgFJK.js";
2
+ import "./api-BSpQkgnM.js";
3
3
  //#region src/proxy.d.ts
4
4
  type ProxyFetch = Resolvers['cloud']['fetch'];
5
5
  type FetchParameters = Parameters<ProxyFetch>;
package/rooms.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-BIInC43l.cjs"),t=require("./api-Csb5b8dE.cjs"),n=require("./busy-BXbVH595.cjs"),r=require("./contract.cjs");var i=e.t({available:()=>_,create:()=>b,join:()=>x,open:()=>y}),a={wrongKey:`rooms: wrong room key`,inviteNoKey:`rooms: the invite carries no key`,badName:`rooms: the name is not one a room can have`,badKeyOption:`rooms: the key is not 32 bytes base64url`,noSuchMember:`rooms: no such member`,noSuchMessage:`rooms: no such message`,roomFull:`rooms: the room is full`,tooManyConnections:`rooms: too many connections`,tooManyBlocks:`rooms: too many blocks`,tooManyClaims:`rooms: too many claims`,mailboxFull:`rooms: the mailbox is full`,outOfStorage:`rooms: the owner is out of storage`,outOfQuota:`rooms: out of daily bandwidth`,blocked:`rooms: you are blocked from this room`,cannotSend:`rooms: you cannot send here`,permissionDenied:`rooms: permission denied`,notOwner:`rooms: not the room owner`,ownerNotRemovable:`rooms: the owner cannot be removed`,ownerKeepsEvery:`rooms: the owner keeps every permission`,removeYourself:`rooms: you cannot remove yourself`,needsAccount:`rooms: claiming needs an account`,nameClaimed:`rooms: the name is claimed`,notClaimed:`rooms: the room is not claimed`,noMailbox:`rooms: the room keeps no messages`,badLimit:`rooms: the limit is out of range`,badDescription:`rooms: the description is not one a claim can carry`,notClaimer:`rooms: only the app that claimed the room can describe it`,notReleaser:`rooms: only the app that claimed the room can release it`,notClaimingApp:`rooms: only the app that claimed the room can change it`,badTemporary:`rooms: the temporary duration is not one a claim can carry`,notTemporaryClaimer:`rooms: only the app that claimed the room can set when it expires`,temporaryUnavailable:`rooms: temporary claims are not available`,mailboxUnavailable:`rooms: the mailbox switch is not available`,guestUnavailable:`rooms: guest joins are not available`,tooFast:`rooms: sending too fast`,tooLarge:`rooms: the message is too large`,unavailable:`rooms: rooms are unavailable`,notEnabled:`rooms: rooms are not available`,alreadyJoined:`rooms: already joined`,notJoined:`rooms: not joined`,malformed:`rooms: malformed frame`,ended:`rooms: the room has ended`},o=(e,t)=>Object.assign(Error(t),{code:e}),s=e=>e instanceof Error&&typeof e.code==`string`,c={send:!0,receive:!0,maxMessageBytes:262144},l=()=>({messages:0,bytes:0,cap:5e8,archived:!1}),u=async()=>{if(!t.l)return;let e=(await t.s(`a room`).catch(()=>void 0))?.rooms;return typeof e?.open==`function`?e:void 0},d=()=>{throw o(`unavailable`,a.unavailable)},f=e=>e===`blocked`?`blocked`:e===`not-found`?`ended`:`unavailable`,p=e=>{if(e!==void 0&&e!==!1)return e===!0?r.ROOM_TEMPORARY_MS.default:typeof e!=`number`||!Number.isInteger(e)?null:e>=r.ROOM_TEMPORARY_MS.min&&e<=r.ROOM_TEMPORARY_MS.max?e:null},m=(e,t)=>{let n=t?e?.guest:e;return typeof n?.join==`function`?n:void 0},h=e=>{let t=e?.guest;if(t!==void 0&&typeof t!=`boolean`)throw o(`invalid`,a.malformed);return t===!0},g=async(e,r)=>{let i=e.invite,u=e,d=0,h=e.self,g=e.owner,_=e.claimed,v=e.mailbox,y=0,b=await e.defaults().catch(()=>c),x=!1,S=new Set,C=new Set,w=n.t(`room`),T=()=>{},E=()=>{},D=new Promise(e=>{E=e}),O=e=>{let t=[...C];C.clear();for(let n of t)try{n(e)}catch{}},k=e=>{x||(x=!0,T(),S.clear(),w(),O(o(`closed`,a.ended)),E({reason:e}))},A=e=>{if(x)return;let t=e;if(t.type===`defaults`&&(b=t.defaults),t.type===`permissions`&&t.id===h.id&&(h={id:h.id,permissions:t.permissions,maxMessageBytes:t.maxMessageBytes}),t.type===`claim`){y+=1;let e=t.claimed&&t.mailbox!==!1;t={type:`claim`,claimed:t.claimed,owner:t.owner,mailbox:e},_=t.claimed,g=t.owner,v=e?l():null}for(let e of[...S])try{e(t)}catch{}},j=(e,t)=>{Promise.resolve(e.on(A)).catch(()=>{}),Promise.resolve(e.closed).then(e=>{t===d&&k(e.reason)},()=>{})},M=async(e,t)=>{let n=m(e,r);if(!n)return k(`unavailable`);let a=await n.join(i).catch(()=>void 0);if(x||t!==d)return;if(!a)return k(`unavailable`);if(`error`in a)return k(f(a.error));if(a.self.id!==h.id)return Promise.resolve(a.leave()).catch(()=>{}),k(`unavailable`);u=a,h=a.self,g=a.owner,_=a.claimed,v=a.mailbox,j(a,t);let o=await a.defaults().catch(()=>void 0);o&&!x&&t===d&&(b=o)};T=t.u((e,t)=>{let n=d;d=t,!(x||n===0||n===t)&&(O(o(`unavailable`,a.unavailable)),M(e.rooms,t))}),j(e,d);let N=async e=>{if(x)throw o(`closed`,a.ended);let t=()=>{},n=new Promise((e,n)=>{t=n});C.add(t);try{return await Promise.race([Promise.resolve(e(u)),n])}catch(e){throw s(e)?e:o(`unavailable`,a.unavailable)}finally{C.delete(t)}},P=async e=>{let t=await N(e);if(`error`in t)throw o(t.error,t.message)},F=async e=>{let t=await N(e);if(typeof t==`object`&&t&&`error`in t)throw o(t.error,t.message);return t};return{id:e.id,name:e.name,key:e.key,invite:i,get self(){return h},get owner(){return g},get claimed(){return _},get mailbox(){return v},defaults:()=>b,members:()=>N(e=>e.members()),send:e=>P(t=>t.send(e)),edit:(e,t)=>P(n=>n.edit(e,t)),delete:(e,t)=>P(n=>n.delete(e,t)),backlog:(e,t)=>F(n=>n.backlog(e,t)),setDefault:(e,t)=>P(n=>n.setDefault(e,t)),limit:(e,t)=>P(n=>n.limit(e,t)),grant:(e,t)=>P(n=>n.grant(e,t)),revoke:(e,t)=>P(n=>n.revoke(e,t)),remove:e=>P(t=>t.remove(e)),block:e=>P(t=>t.block(e)),unblock:e=>P(t=>t.unblock(e)),claim:async e=>{let t=e?.description;if(t!==void 0&&typeof t!=`string`)throw o(`invalid`,a.badDescription);let n=p(e?.temporary);if(n===null)throw o(`invalid`,a.badTemporary);let r=e?.mailbox;if(r!==void 0&&typeof r!=`boolean`)throw o(`invalid`,a.malformed);let i={...t===void 0?{}:{description:t},...n===void 0?{}:{temporary:n},...r===void 0?{}:{mailbox:r}};return Object.keys(i).length===0?P(e=>e.claim()):P(e=>{if(n!==void 0&&e.temporaryClaims!==!0)throw o(`unavailable`,a.temporaryUnavailable);if(r===!1&&e.mailboxSwitch!==!0)throw o(`unavailable`,a.mailboxUnavailable);return e.claim(i)})},setMailbox:async e=>{if(typeof e!=`boolean`)throw o(`invalid`,a.malformed);let t=y;await P(t=>{if(t.mailboxSwitch!==!0)throw o(`unavailable`,a.mailboxUnavailable);return t.setMailbox(e)}),y===t&&(e?v===null&&(v=l()):v=null)},release:()=>P(e=>e.release()),usage:async()=>{let e=await F(e=>e.usage());return v=e,e},on:async e=>x?()=>{}:(S.add(e),()=>{S.delete(e)}),leave:async()=>{await Promise.resolve(u.leave()).catch(()=>{}),k(`left`)},closed:D}},_=async()=>{let e=await u();return e?e.available().catch(()=>!1):!1},v=async(e,t)=>{let n=await u();if(!n)throw o(`unavailable`,a.unavailable);let r=m(n,e);if(!r)throw o(`unavailable`,a.guestUnavailable);let i=await t(r).catch(d);if(`error`in i)throw o(i.error,i.message);return g(i,e)},y=async(e,t)=>{if(typeof e!=`string`||e.length===0||e.length>72)throw o(`invalid`,a.badName);return v(h(t),n=>n.open(e,t))},b=async e=>v(h(e),t=>t.create(e)),x=async(e,t)=>{let n=typeof e==`string`?e.indexOf(`.`):-1;if(n<=0||n===e.length-1)throw o(`invalid`,a.inviteNoKey);return v(h(t),n=>n.join(e,t))};exports.available=_,exports.create=b,exports.join=x,exports.open=y,Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return i}});
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-BIInC43l.cjs"),t=require("./api-Csb5b8dE.cjs"),n=require("./busy-BXbVH595.cjs"),r=require("./contract.cjs");var i=e.t({available:()=>S,create:()=>T,join:()=>E,open:()=>w}),a={wrongKey:`rooms: wrong room key`,inviteNoKey:`rooms: the invite carries no key`,badName:`rooms: the name is not one a room can have`,badKeyOption:`rooms: the key is not 32 bytes base64url`,noSuchMember:`rooms: no such member`,noSuchMessage:`rooms: no such message`,roomFull:`rooms: the room is full`,tooManyConnections:`rooms: too many connections`,tooManyBlocks:`rooms: too many blocks`,tooManyClaims:`rooms: too many claims`,mailboxFull:`rooms: the mailbox is full`,outOfStorage:`rooms: the owner is out of storage`,outOfQuota:`rooms: out of daily bandwidth`,blocked:`rooms: you are blocked from this room`,cannotSend:`rooms: you cannot send here`,permissionDenied:`rooms: permission denied`,notOwner:`rooms: not the room owner`,ownerNotRemovable:`rooms: the owner cannot be removed`,ownerKeepsEvery:`rooms: the owner keeps every permission`,removeYourself:`rooms: you cannot remove yourself`,needsAccount:`rooms: claiming needs an account`,nameClaimed:`rooms: the name is claimed`,notClaimed:`rooms: the room is not claimed`,noMailbox:`rooms: the room keeps no messages`,badLimit:`rooms: the limit is out of range`,badDescription:`rooms: the description is not one a claim can carry`,notClaimer:`rooms: only the app that claimed the room can describe it`,notReleaser:`rooms: only the app that claimed the room can release it`,notClaimingApp:`rooms: only the app that claimed the room can change it`,badTemporary:`rooms: the temporary duration is not one a claim can carry`,notTemporaryClaimer:`rooms: only the app that claimed the room can set when it expires`,temporaryUnavailable:`rooms: temporary claims are not available`,mailboxUnavailable:`rooms: the mailbox switch is not available`,guestUnavailable:`rooms: guest joins are not available`,schemasUnavailable:`rooms: room schemas are not available`,badSchema:`rooms: the schema is not one a room can take`,newerSchema:`rooms: the room holds a newer schema`,noSchema:`rooms: the room has no schema`,misfit:`rooms: the message does not fit the room's schema`,ownerSends:`rooms: only the owner sends this type`,accountSends:`rooms: sending this needs an account`,perAccount:`rooms: you have as many of these here as the room allows`,tooFast:`rooms: sending too fast`,tooLarge:`rooms: the message is too large`,unavailable:`rooms: rooms are unavailable`,notEnabled:`rooms: rooms are not available`,alreadyJoined:`rooms: already joined`,notJoined:`rooms: not joined`,malformed:`rooms: malformed frame`,ended:`rooms: the room has ended`},o=(e,t)=>Object.assign(Error(t),{code:e}),s=e=>e instanceof Error&&typeof e.code==`string`,c={send:!0,receive:!0,maxMessageBytes:262144},l=2048,u=()=>({messages:0,bytes:0,cap:5e8,archived:!1}),d=async()=>{if(!t.l)return;let e=(await t.s(`a room`).catch(()=>void 0))?.rooms;return typeof e?.open==`function`?e:void 0},f=()=>{throw o(`unavailable`,a.unavailable)},p=e=>e===`blocked`?`blocked`:e===`not-found`?`ended`:`unavailable`,m=e=>{if(e!==void 0&&e!==!1)return e===!0?r.ROOM_TEMPORARY_MS.default:typeof e!=`number`||!Number.isInteger(e)?null:e>=r.ROOM_TEMPORARY_MS.min&&e<=r.ROOM_TEMPORARY_MS.max?e:null},h=(e,t)=>{let n=t?e?.guest:e;return typeof n?.join==`function`?n:void 0},g=e=>{let t;try{t=JSON.stringify(e)}catch{}let n=t===void 0?void 0:JSON.parse(t),r=typeof n==`object`&&!!n&&!Array.isArray(n)&&typeof n.type==`string`;if(t===void 0||!r||t.length>l)throw o(`invalid`,a.misfit);return t},_=e=>{let t;try{t=JSON.parse(JSON.stringify(e))}catch{}if(typeof t!=`object`||!t||Array.isArray(t))throw o(`invalid`,a.badSchema);return t},v=e=>e?.schema===void 0?e:{...e,schema:_(e.schema)},y=e=>{if(e.schemas!==!0)throw o(`unavailable`,a.schemasUnavailable);return e},b=e=>{let t=e?.guest;if(t!==void 0&&typeof t!=`boolean`)throw o(`invalid`,a.malformed);return t===!0},x=async(e,r)=>{let i=e.invite,l=e,d=0,f=e.self,v=e.owner,b=e.claimed,x=e.mailbox,S=0,C=await e.defaults().catch(()=>c),w=e.schemas===!0?await Promise.resolve(e.schema()).catch(()=>null):null,T=0,E=!1,D=new Set,O=new Set,k=n.t(`room`),A=()=>{},j=()=>{},M=new Promise(e=>{j=e}),N=e=>{let t=[...O];O.clear();for(let n of t)try{n(e)}catch{}},P=e=>{E||(E=!0,A(),D.clear(),k(),N(o(`closed`,a.ended)),j({reason:e}))},F=e=>{if(E)return;let t=e;if(t.type===`defaults`&&(C=t.defaults),t.type===`schema`&&(T+=1,w=t.schema),t.type===`message`||t.type===`edited`){let e={...t.message,envelope:t.message.envelope??null};t=t.type===`message`?{...t,message:e}:{type:`edited`,message:e}}if(t.type===`permissions`&&t.id===f.id&&(f={id:f.id,permissions:t.permissions,maxMessageBytes:t.maxMessageBytes}),t.type===`claim`){S+=1;let e=t.claimed&&t.mailbox!==!1;t={type:`claim`,claimed:t.claimed,owner:t.owner,mailbox:e},b=t.claimed,v=t.owner,x=e?u():null}for(let e of[...D])try{e(t)}catch{}},I=(e,t)=>{Promise.resolve(e.on(F)).catch(()=>{}),Promise.resolve(e.closed).then(e=>{t===d&&P(e.reason)},()=>{})},L=async(e,t)=>{let n=h(e,r);if(!n)return P(`unavailable`);let a=await n.join(i).catch(()=>void 0);if(E||t!==d)return;if(!a)return P(`unavailable`);if(`error`in a)return P(p(a.error));if(a.self.id!==f.id)return Promise.resolve(a.leave()).catch(()=>{}),P(`unavailable`);l=a,f=a.self,v=a.owner,b=a.claimed,x=a.mailbox,I(a,t);let o=await a.defaults().catch(()=>void 0);if(o&&!E&&t===d&&(C=o),a.schemas!==!0)return;let s=await Promise.resolve(a.schema()).catch(()=>void 0);s!==void 0&&!E&&t===d&&(w=s)};A=t.u((e,t)=>{let n=d;d=t,!(E||n===0||n===t)&&(N(o(`unavailable`,a.unavailable)),L(e.rooms,t))}),I(e,d);let R=async e=>{if(E)throw o(`closed`,a.ended);let t=()=>{},n=new Promise((e,n)=>{t=n});O.add(t);try{return await Promise.race([Promise.resolve(e(l)),n])}catch(e){throw s(e)?e:o(`unavailable`,a.unavailable)}finally{O.delete(t)}},z=async e=>{let t=await R(e);if(`error`in t)throw o(t.error,t.message)},B=async e=>{let t=await R(e);if(typeof t==`object`&&t&&`error`in t)throw o(t.error,t.message);return t};return{id:e.id,name:e.name,key:e.key,invite:i,get self(){return f},get owner(){return v},get claimed(){return b},get mailbox(){return x},defaults:()=>C,members:()=>R(e=>e.members()),schema:()=>w,send:async(e,t)=>{if(t===void 0)return z(t=>t.send(e));let n=g(t);return z(t=>y(t).send(e,n))},edit:async(e,t,n)=>{if(n===void 0)return z(n=>n.edit(e,t));let r=g(n);return z(n=>y(n).edit(e,t,r))},setSchema:async e=>{let t=_(e),n=T;await z(e=>y(e).setSchema(t)),T===n&&(w=t)},delete:(e,t)=>z(n=>n.delete(e,t)),backlog:(e,t)=>B(n=>n.backlog(e,t)),setDefault:(e,t)=>z(n=>n.setDefault(e,t)),limit:(e,t)=>z(n=>n.limit(e,t)),grant:(e,t)=>z(n=>n.grant(e,t)),revoke:(e,t)=>z(n=>n.revoke(e,t)),remove:e=>z(t=>t.remove(e)),block:e=>z(t=>t.block(e)),unblock:e=>z(t=>t.unblock(e)),claim:async e=>{let t=e?.description;if(t!==void 0&&typeof t!=`string`)throw o(`invalid`,a.badDescription);let n=m(e?.temporary);if(n===null)throw o(`invalid`,a.badTemporary);let r=e?.mailbox;if(r!==void 0&&typeof r!=`boolean`)throw o(`invalid`,a.malformed);let i={...t===void 0?{}:{description:t},...n===void 0?{}:{temporary:n},...r===void 0?{}:{mailbox:r}};return Object.keys(i).length===0?z(e=>e.claim()):z(e=>{if(n!==void 0&&e.temporaryClaims!==!0)throw o(`unavailable`,a.temporaryUnavailable);if(r===!1&&e.mailboxSwitch!==!0)throw o(`unavailable`,a.mailboxUnavailable);return e.claim(i)})},setMailbox:async e=>{if(typeof e!=`boolean`)throw o(`invalid`,a.malformed);let t=S;await z(t=>{if(t.mailboxSwitch!==!0)throw o(`unavailable`,a.mailboxUnavailable);return t.setMailbox(e)}),S===t&&(e?x===null&&(x=u()):x=null)},release:()=>z(e=>e.release()),usage:async()=>{let e=await B(e=>e.usage());return x=e,e},on:async e=>E?()=>{}:(D.add(e),()=>{D.delete(e)}),leave:async()=>{await Promise.resolve(l.leave()).catch(()=>{}),P(`left`)},closed:M}},S=async()=>{let e=await d();return e?e.available().catch(()=>!1):!1},C=async(e,t,n)=>{let r=await d();if(!r)throw o(`unavailable`,a.unavailable);let i=h(r,e);if(!i)throw o(`unavailable`,a.guestUnavailable);let s=await n(i).catch(f);if(`error`in s)throw o(s.error,s.message);if(t?.schema!==void 0&&s.schemas!==!0)throw await Promise.resolve(s.leave()).catch(()=>{}),o(`unavailable`,a.schemasUnavailable);return x(s,e)},w=async(e,t)=>{if(typeof e!=`string`||e.length===0||e.length>72)throw o(`invalid`,a.badName);let n=b(t),r=v(t);return C(n,r,t=>t.open(e,r))},T=async e=>{let t=b(e),n=v(e);return C(t,n,e=>e.create(n))},E=async(e,t)=>{let n=typeof e==`string`?e.indexOf(`.`):-1;if(n<=0||n===e.length-1)throw o(`invalid`,a.inviteNoKey);return C(b(t),void 0,n=>n.join(e,t))};exports.available=S,exports.create=T,exports.join=E,exports.open=w,Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return i}});
package/rooms.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { J as RoomClaimOptions, Q as RoomEvent, X as RoomDefaults, Y as RoomCreateOptions, Z as RoomEnd, at as RoomPermission, et as RoomJoinOptions, it as RoomOpenOptions, nt as RoomMember, ot as RoomPermissions, q as RoomBacklog, rt as RoomMessage, st as RoomsErrorCode, tt as RoomMailbox } from "./contract-CMQOic3K.js";
1
+ import { $ as RoomEvent, J as RoomClaimOptions, Q as RoomEnvelope, X as RoomDefaults, Y as RoomCreateOptions, Z as RoomEnd, at as RoomMessage, ct as RoomPermissions, dt as RoomsErrorCode, it as RoomMember, lt as RoomSchema, nt as RoomJson, ot as RoomOpenOptions, q as RoomBacklog, rt as RoomMailbox, st as RoomPermission, tt as RoomJoinOptions, ut as RoomType } from "./contract-DFycgFJK.js";
2
2
  declare namespace rooms_d_exports {
3
- export { RoomClaimOptions as ClaimOptions, RoomCreateOptions as CreateOptions, RoomJoinOptions as JoinOptions, RoomOpenOptions as OpenOptions, Room, RoomBacklog, RoomDefaults, RoomEnd, RoomEvent, RoomMailbox, RoomMember, RoomMessage, RoomPermission, RoomPermissions, RoomsError, RoomsErrorCode, available, create, join, open };
3
+ export { RoomClaimOptions as ClaimOptions, RoomCreateOptions as CreateOptions, RoomJoinOptions as JoinOptions, RoomOpenOptions as OpenOptions, Room, RoomBacklog, RoomDefaults, RoomEnd, RoomEnvelope, RoomEvent, RoomJson, RoomMailbox, RoomMember, RoomMessage, RoomPermission, RoomPermissions, RoomSchema, RoomType, RoomsError, RoomsErrorCode, available, create, join, open };
4
4
  }
5
5
  /** Thrown by every member of this namespace. Match on `code`, never on the message. */
6
6
  export type RoomsError = Error & {
@@ -33,14 +33,48 @@ export type Room = {
33
33
  readonly mailbox: RoomMailbox | null;
34
34
  defaults: () => RoomDefaults;
35
35
  members: () => Promise<RoomMember[]>;
36
- /** sealed before it leaves the browser. Rejects `too-large` past `self.maxMessageBytes` on the wire, never truncates. */
37
- send: (text: string) => Promise<void>;
36
+ /** the room's schema as the room last said, null for a room without one */
37
+ schema: () => RoomSchema | null;
38
38
  /**
39
- * replaces a stored message's text: one of your own, or any as the owner. On a room claimed under an
40
- * app's scope, from another app of the claim's account, it is refused `denied` (`rooms: only the app
41
- * that claimed the room can change it`), the account's own messages included, as `claim` says.
39
+ * `text` is sealed before it leaves the browser. Rejects `too-large` past `self.maxMessageBytes` on the
40
+ * wire, never truncates.
41
+ *
42
+ * In a room with a schema `envelope` is required: it goes in plain beside the sealed text, which may be
43
+ * empty, and the sealed text opens only under it. The app chooses what is sealed at each send: put in
44
+ * the envelope only what every member and FKN may read, and the rest in `text`. The lib writes it with
45
+ * `JSON.stringify` and refuses `invalid` (`rooms: the message does not fit the room's schema`), with
46
+ * nothing sent, one that is not a JSON object with a string `type` or is past 2,048 characters; the room
47
+ * refuses the same for an envelope that does not fit its type, or a send without one. The size counted
48
+ * is the envelope's text and the sealed text together, against `self.maxMessageBytes` and the type's
49
+ * `maxBytes`. The type's sender rule refuses `denied` (`rooms: only the owner sends this type`, `rooms:
50
+ * sending this needs an account`), its per-account limit `full` (`rooms: you have as many of these
51
+ * here as the room allows`), and the room's cap `storage` (`rooms: the mailbox is full`).
52
+ *
53
+ * Without a schema an envelope is refused `invalid` (`rooms: the room has no schema`). An fkn.app older
54
+ * than room schemas refuses one `unavailable` (`rooms: room schemas are not available`) with nothing
55
+ * sent; a send without one goes as before.
56
+ */
57
+ send: (text: string, envelope?: RoomEnvelope) => Promise<void>;
58
+ /**
59
+ * replaces a stored message's text: one of your own, or any as the owner. Checked exactly as a send is,
60
+ * `send` and the rate limits included; in a room with a schema `envelope` is required and names the
61
+ * message's own type, so a message stored before the room had a schema is deleted rather than edited.
62
+ * On a room claimed under an app's scope, from another app of the claim's account, it is refused
63
+ * `denied` (`rooms: only the app that claimed the room can change it`), the account's own messages
64
+ * included, as `claim` says.
65
+ */
66
+ edit: (seq: number, text: string, envelope?: RoomEnvelope) => Promise<void>;
67
+ /**
68
+ * replaces the room's schema with one of a higher `version`, from the next send on; everyone present
69
+ * hears a `schema` event. The same schema at the same `version` resolves and changes nothing, so set it
70
+ * on every open. A lower `version`, or another schema at the same one, is refused `invalid` (`rooms: the
71
+ * room holds a newer schema`), and one the room cannot take `invalid` (`rooms: the schema is not one a
72
+ * room can take`). From the owner only (`denied`, `rooms: not the room owner`), and on a room claimed
73
+ * under an app's scope only through the app that claimed it (`denied`, `rooms: only the app that
74
+ * claimed the room can change it`), as `claim` says. A schema is never removed. An fkn.app older than
75
+ * room schemas refuses it `unavailable` (`rooms: room schemas are not available`).
42
76
  */
43
- edit: (seq: number, text: string) => Promise<void>;
77
+ setSchema: (schema: RoomSchema) => Promise<void>;
44
78
  /**
45
79
  * drops stored messages: one of your own, or any range as the owner. On a room claimed under an app's
46
80
  * scope, from another app of the claim's account, it is refused `denied` (`rooms: only the app that
@@ -177,4 +211,4 @@ export declare const create: (options?: RoomCreateOptions) => Promise<Room>;
177
211
  /** `invite` is `room.invite`: a key and a room id joined by a dot. */
178
212
  export declare const join: (invite: string, options?: RoomJoinOptions) => Promise<Room>;
179
213
  //#endregion
180
- export { type RoomClaimOptions as ClaimOptions, type RoomCreateOptions as CreateOptions, type RoomJoinOptions as JoinOptions, type RoomOpenOptions as OpenOptions, type RoomBacklog, type RoomDefaults, type RoomEnd, type RoomEvent, type RoomMailbox, type RoomMember, type RoomMessage, type RoomPermission, type RoomPermissions, type RoomsErrorCode, rooms_d_exports as t };
214
+ export { type RoomClaimOptions as ClaimOptions, type RoomCreateOptions as CreateOptions, type RoomJoinOptions as JoinOptions, type RoomOpenOptions as OpenOptions, type RoomBacklog, type RoomDefaults, type RoomEnd, type RoomEnvelope, type RoomEvent, type RoomJson, type RoomMailbox, type RoomMember, type RoomMessage, type RoomPermission, type RoomPermissions, type RoomSchema, type RoomType, type RoomsErrorCode, rooms_d_exports as t };