@fkn/lib 0.9.63 → 0.9.65

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 (169) hide show
  1. package/README.md +34 -0
  2. package/account-Bm7uIcQo.d.ts +39 -0
  3. package/account-Uh0-1Cbp.js +22 -0
  4. package/{account-generation-B0cJrpDx.cjs → account-generation-ACCBzaI-.cjs} +1 -1
  5. package/{account-generation-u31dhamM.js → account-generation-BKHNe-jL.js} +2 -3
  6. package/account-m2iCmNui.cjs +1 -0
  7. package/{account-storage-ZkzqZp3A.js → account-storage-BmCVutNL.js} +4 -5
  8. package/{account-storage-Co9IvkPr.d.ts → account-storage-UmSfF63A.d.ts} +1 -66
  9. package/{account-storage-BnohkyMJ.cjs → account-storage-dYWDpqsr.cjs} +1 -1
  10. package/account.cjs +1 -1
  11. package/account.d.ts +3 -40
  12. package/account.js +1 -23
  13. package/{api-xh6lzApn.d.ts → api-0Yp9uZcV.d.ts} +3 -7
  14. package/{api-Di2Ff3jS.js → api-DRglK7ft.js} +115 -156
  15. package/api-DrvhPN56.cjs +3 -0
  16. package/api.cjs +1 -1
  17. package/api.d.ts +2 -2
  18. package/api.js +1 -2
  19. package/attach-policy.d.ts +0 -4
  20. package/attach-policy.js +2 -3
  21. package/broker-frame-CF4-yXtj.cjs +9 -0
  22. package/broker-frame-vjSpBa8d.js +51 -0
  23. package/broker-frame.cjs +1 -0
  24. package/broker-frame.d.ts +12 -0
  25. package/broker-frame.js +1 -0
  26. package/{busy-DsMWrSzc.js → busy-C1JPjoZ_.js} +1 -2
  27. package/cloud/dgram.cjs +1 -1
  28. package/cloud/dgram.d.ts +1 -1
  29. package/cloud/dgram.js +1 -2
  30. package/cloud/dns.cjs +1 -1
  31. package/cloud/dns.d.ts +2 -2
  32. package/cloud/dns.js +1 -2
  33. package/cloud/fetch.cjs +1 -1
  34. package/cloud/fetch.d.ts +1 -1
  35. package/cloud/fetch.js +1 -2
  36. package/cloud/fs/promises.cjs +1 -1
  37. package/cloud/fs/promises.d.ts +3 -5
  38. package/cloud/fs/promises.js +2 -3
  39. package/cloud/fs.cjs +1 -1
  40. package/cloud/fs.d.ts +4 -4
  41. package/cloud/fs.js +4 -34
  42. package/cloud/http.cjs +1 -1
  43. package/cloud/http.d.ts +1 -1
  44. package/cloud/http.js +1 -2
  45. package/cloud/net.cjs +1 -1
  46. package/cloud/net.d.ts +1 -1
  47. package/cloud/net.js +3 -3
  48. package/{cloud-CI7FFRMC.d.ts → cloud-BoH54gaM.d.ts} +7 -11
  49. package/{cloud-C6rG_aod.js → cloud-C7StNncS.js} +17 -17
  50. package/cloud-TN0eDUy3.cjs +1 -0
  51. package/cloud.cjs +1 -1
  52. package/cloud.d.ts +7 -7
  53. package/cloud.js +7 -7
  54. package/connect-button-2FmOM8ai.d.ts +2 -0
  55. package/{connect-button-DtsN3X1J.js → connect-button-C1wKkIhh.js} +1 -2
  56. package/{contract-BGMJVvTg.d.ts → contract-0rua6Wsh.d.ts} +11 -6
  57. package/contract.d.ts +3 -3
  58. package/contract.js +1 -2
  59. package/desktop-DOubT4ES.d.ts +57 -0
  60. package/desktop-vXKU4wEK.cjs +1 -0
  61. package/desktop-xTT7ciGX.js +50 -0
  62. package/desktop.cjs +1 -1
  63. package/desktop.d.ts +2 -58
  64. package/desktop.js +1 -51
  65. package/dgram-BBbLokVF.js +397 -0
  66. package/dgram-BYk-QDHW.d.ts +118 -0
  67. package/dgram-D9ljiUFh.cjs +1 -0
  68. package/dgram.cjs +1 -1
  69. package/dgram.d.ts +2 -119
  70. package/dgram.js +1 -410
  71. package/dns-2v96zoEh.cjs +1 -0
  72. package/dns-DyB4K2oE.d.ts +9 -0
  73. package/dns-o8DLFjP1.js +5 -0
  74. package/dns.cjs +1 -1
  75. package/dns.d.ts +3 -10
  76. package/dns.js +1 -6
  77. package/extension-BXBjpypy.cjs +1 -0
  78. package/{extension-C3_aJX7C.js → extension-D5UMnEmQ.js} +11 -12
  79. package/{extension-C1bcizcn.d.ts → extension-D98KM8W7.d.ts} +1 -27
  80. package/extension.cjs +1 -1
  81. package/extension.d.ts +2 -2
  82. package/extension.js +2 -2
  83. package/fs/promises.cjs +1 -1
  84. package/fs/promises.d.ts +2 -4
  85. package/fs/promises.js +2 -3
  86. package/fs--MLHvMW-.cjs +1 -0
  87. package/fs-BX_ghRy0.cjs +1 -0
  88. package/fs-BnWXGRik.js +33 -0
  89. package/{fs-DCJAYoYy.d.ts → fs-ChOYC6VD.d.ts} +3 -4
  90. package/{fs-DgdN2HPt.js → fs-Cw7CcUhx.js} +17 -41
  91. package/fs.cjs +1 -1
  92. package/fs.d.ts +4 -4
  93. package/fs.js +2 -2
  94. package/{hosts-t7CKGTRz.js → hosts-HUfgMimI.js} +1 -2
  95. package/http-BE3UBktN.cjs +9 -0
  96. package/http-CDhG4bUc.d.ts +187 -0
  97. package/http-DIDjdm08.js +523 -0
  98. package/http.cjs +1 -9
  99. package/http.d.ts +2 -188
  100. package/http.js +1 -542
  101. package/index-CUWTpQKP.d.ts +87 -0
  102. package/{index-BQgZVQl7.d.ts → index-CcVwh9yz.d.ts} +0 -2
  103. package/{index-C5DdoMGo.d.ts → index-Cu5EcdK0.d.ts} +0 -59
  104. package/{index-57lTXnoe.d.ts → index-D6GPJ4Ow.d.ts} +29 -26
  105. package/index.cjs +1 -1
  106. package/index.d.ts +17 -25
  107. package/index.js +22 -27
  108. package/lib-Bs-g5jyp.cjs +53 -0
  109. package/{lib-BrsqpUkv.js → lib-CtJaID_y.js} +7 -31
  110. package/{messages-AdPfdoLV.d.ts → messages-B9dOXntM.d.ts} +0 -2
  111. package/messages.d.ts +1 -1
  112. package/messages.js +1 -2
  113. package/net-COkJw8lV.js +286 -0
  114. package/net-Dk2kqtgE.cjs +1 -0
  115. package/{net-BpyIeQ8r.d.ts → net-mVAYXs8e.d.ts} +5 -7
  116. package/net.cjs +1 -1
  117. package/net.d.ts +1 -1
  118. package/net.js +3 -323
  119. package/{node-fs-DY2fO5zd.js → node-fs-B4pY08Kc.js} +3 -10
  120. package/node-fs-DN0ejGTL.cjs +1 -0
  121. package/opfs/promises.cjs +1 -1
  122. package/opfs/promises.d.ts +2 -4
  123. package/opfs/promises.js +2 -3
  124. package/{opfs-D0goLAQW.js → opfs-CzCfVam3.js} +2 -3
  125. package/opfs-D3pYzYRc.js +35 -0
  126. package/opfs-DuXvTgIl.cjs +1 -0
  127. package/opfs.cjs +1 -1
  128. package/opfs.d.ts +3 -88
  129. package/opfs.js +1 -36
  130. package/package.json +6 -1
  131. package/packages-BEadIy_h.d.ts +155 -0
  132. package/packages-Cws_rcgf.js +346 -0
  133. package/packages-DT8vPB5_.cjs +1 -0
  134. package/packages.cjs +1 -1
  135. package/packages.d.ts +3 -156
  136. package/packages.js +1 -347
  137. package/{proxy-tsVhjcl-.js → proxy-BBAQxJmP.js} +13 -13
  138. package/{proxy-Dz60YyYy.d.ts → proxy-BP40IXYD.d.ts} +2 -4
  139. package/proxy-DVgGp6A8.cjs +1 -0
  140. package/react.cjs +1 -1
  141. package/react.d.ts +16 -4
  142. package/react.js +96 -7
  143. package/{relay-choice-BGwXRC5d.js → relay-choice-Bb3oP2gw.js} +1 -2
  144. package/{relay-choice-5yUPI-tJ.d.ts → relay-choice-DOUttUnL.d.ts} +2 -4
  145. package/{rolldown-runtime-Dy4uBu1J.js → rolldown-runtime-CGnMp29N.js} +1 -2
  146. package/rooms-C6mbannC.d.ts +227 -0
  147. package/rooms-DHFS9cwA.cjs +1 -0
  148. package/rooms-DP5stTEr.js +300 -0
  149. package/rooms.cjs +1 -1
  150. package/rooms.d.ts +3 -228
  151. package/rooms.js +1 -301
  152. package/storage-BCjYihUO.cjs +1 -0
  153. package/storage-BhfImh_2.js +136 -0
  154. package/storage-DpCLksAa.d.ts +68 -0
  155. package/storage.cjs +1 -1
  156. package/storage.d.ts +3 -69
  157. package/storage.js +1 -137
  158. package/{utils-Cyq8uJiy.js → utils-DtWP-E9x.js} +1 -2
  159. package/{wire-Fk5pJaoy.d.ts → wire-DhmLnYEU.d.ts} +0 -2
  160. package/wire.d.ts +1 -1
  161. package/wire.js +1 -2
  162. package/api-BSk3dc_X.cjs +0 -3
  163. package/cloud-BoiHKoRZ.cjs +0 -1
  164. package/connect-button-Cp0NS95-.d.ts +0 -4
  165. package/extension-Crv4aUAm.cjs +0 -1
  166. package/fs-CjQTj3FA.cjs +0 -1
  167. package/lib-C_X3WR4G.cjs +0 -53
  168. package/node-fs-vsWuoMGa.cjs +0 -1
  169. package/proxy-BA92hkId.cjs +0 -1
package/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # @fkn/lib
2
+
3
+ FKN for apps: the account, storage, rooms and packages, and Node's `fs`, `net`, `dgram` and `http` in the browser.
4
+
5
+ ## Mount the broker frame from your html
6
+
7
+ The lib reaches FKN through a frame of fkn.app's `/api`, which it mounts once your bundle runs. Mount it from
8
+ your html instead and it loads while the bundle downloads and parses: on slow 4G, FKN Social showed Sign in about
9
+ 1.2 s sooner. The lib adopts that frame and treats it as its own.
10
+
11
+ With Vite:
12
+
13
+ ```ts
14
+ // vite.config.ts
15
+ import { defineConfig } from 'vite'
16
+ import { brokerFrameScript } from '@fkn/lib/broker-frame'
17
+
18
+ export default defineConfig({
19
+ plugins: [
20
+ {
21
+ name: 'fkn-broker-frame',
22
+ transformIndexHtml: () => [{ tag: 'script', children: brokerFrameScript, injectTo: 'body-prepend' }],
23
+ },
24
+ ],
25
+ })
26
+ ```
27
+
28
+ With anything else, write `<script>${brokerFrameScript}</script>` as the first thing in `<body>` at build time, from
29
+ the installed version.
30
+
31
+ - In a framed page, the script mounts nothing: inside fkn.app the lib uses fkn.app's own broker.
32
+ - Use the script, not a hand-written iframe of fkn.app's `/api`, which misses the frame's `allow` list.
33
+ - A `Content-Security-Policy` that blocks inline scripts needs the script's hash in `script-src`. Without it, the lib
34
+ mounts the frame itself, as before.
@@ -0,0 +1,39 @@
1
+ import { a as AccountChange } from "./contract-0rua6Wsh.js";
2
+ declare namespace account_d_exports {
3
+ export { AccountChange, AccountInfo, info, login, logout, onChange };
4
+ }
5
+ type AccountInfo = {
6
+ /** the account's display name (a username, not necessarily a real name) */
7
+ name: string;
8
+ /** profile image URL, or null if none is set */
9
+ image: string | null;
10
+ /** the account has an active paid subscription */
11
+ premium: boolean;
12
+ /** when the current subscription lapses, as a ms epoch, or null when not subscribed */
13
+ premiumUntil: number | null;
14
+ };
15
+ declare const login: () => Promise<boolean>;
16
+ declare const logout: () => Promise<void>;
17
+ declare const info: () => Promise<AccountInfo | null>;
18
+ /**
19
+ * Calls `callback` whenever the account this page acts as may have changed (a switch, a sign-in or a
20
+ * sign-out, in this tab or another), and when the connection is renewed without one. Works in a window
21
+ * and in a worker bridged with `relayWorker`; resolves to a no-op where there is no FKN transport at all.
22
+ *
23
+ * `change.switched` says which. True: this page may now act as another account, or as none, so drop
24
+ * what the old account put in memory (its lists, any open work) and read again; a storage call made
25
+ * before this callback never lands in the new account (it is refused with `StorageAccountChangedError`).
26
+ * It is also true when fkn.app is too old to tell (before 2026-10-02) and when the library moved on its
27
+ * own after a refusal, so treating true as a switch is always safe. False: fkn.app saw the same account.
28
+ * Its connect token was renewed, or an app in this browser signed in or out of FKN on its own, this one
29
+ * included, so read `info()` again to learn whether this page is still signed in. Calls made before it
30
+ * still land. A switch fkn.app could not see, because its document was replaced in between, reaches you
31
+ * as true once a storage call is refused for it.
32
+ *
33
+ * Storage moves to the new account BEFORE any callback runs. Work the app started before a switch and
34
+ * resumes after it is the app's to check: keep a counter this callback bumps when `switched` is true,
35
+ * and compare it synchronously right before the storage call, which captures the account in the same
36
+ * synchronous step, so the check and the call are atomic.
37
+ */
38
+ declare const onChange: (callback: (change: AccountChange) => void) => Promise<() => void>;
39
+ export { logout as a, login as i, account_d_exports as n, onChange as o, info as r, AccountInfo as t };
@@ -0,0 +1,22 @@
1
+ import { t as e } from "./rolldown-runtime-CGnMp29N.js";
2
+ import { l as t, o as n } from "./api-DRglK7ft.js";
3
+ import { i as r } from "./account-generation-BKHNe-jL.js";
4
+ // src/account.ts
5
+ var i = /* @__PURE__ */ e({
6
+ info: () => s,
7
+ login: () => a,
8
+ logout: () => o,
9
+ onChange: () => c
10
+ }), a = async () => typeof window > "u" ? !1 : (await n).account.login(location.origin).catch(() => !1), o = async () => {
11
+ typeof window < "u" && await (await n).account.logout().catch(() => {});
12
+ }, s = async () => {
13
+ if (typeof window > "u") return null;
14
+ let e = await n.then((e) => e.account.info()).catch(() => null);
15
+ return e ? {
16
+ name: e.name,
17
+ image: e.image,
18
+ premium: e.premium,
19
+ premiumUntil: e.premiumUntil ? Date.parse(e.premiumUntil) : null
20
+ } : null;
21
+ }, c = async (e) => t ? r(e) : () => {};
22
+ export { c as a, o as i, s as n, a as r, i as t };
@@ -1 +1 @@
1
- const e=require("./api-BSk3dc_X.cjs");var t=0,n=new Set,r=2e3,i=null,a=e=>{let r=e?.switched!==!1;r&&(t+=1,i&&=(clearTimeout(i.timer),null));for(let e of[...n])try{e({switched:r})}catch{}},o=!1,s=0,c=()=>{let t=e.c();t&&s!==t.epoch&&(s=t.epoch,Promise.resolve(t.remote.account.onChange(a)).catch(()=>{s===t.epoch&&(s=0)}))},l=()=>{!o&&e.l&&(o=!0,e.u(c))},u=()=>t,d=e=>(n.add(e),l(),()=>{n.delete(e)}),f=e=>{if(e!==t||i?.generation===e)return;let n=setTimeout(()=>{i?.timer===n&&(i=null,t===e&&a({switched:!0}))},r);i={generation:e,timer:n}};Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return u}});
1
+ const e=require("./api-DrvhPN56.cjs");var t=0,n=new Set,r=2e3,i=null,a=e=>{let r=e?.switched!==!1;r&&(t+=1,i&&=(clearTimeout(i.timer),null));for(let e of[...n])try{e({switched:r})}catch{}},o=!1,s=0,c=()=>{let t=e.c();t&&s!==t.epoch&&(s=t.epoch,Promise.resolve(t.remote.account.onChange(a)).catch(()=>{s===t.epoch&&(s=0)}))},l=()=>{!o&&e.l&&(o=!0,e.u(c))},u=()=>t,d=e=>(n.add(e),l(),()=>{n.delete(e)}),f=e=>{if(e!==t||i?.generation===e)return;let n=setTimeout(()=>{i?.timer===n&&(i=null,t===e&&a({switched:!0}))},r);i={generation:e,timer:n}};Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return u}});
@@ -1,5 +1,5 @@
1
- import { c as e, l as t, u as n } from "./api-Di2Ff3jS.js";
2
- //#region src/account-generation.ts
1
+ import { c as e, l as t, u as n } from "./api-DRglK7ft.js";
2
+ // src/account-generation.ts
3
3
  var r = 0, i = /* @__PURE__ */ new Set(), a = 2e3, o = null, s = (e) => {
4
4
  let t = e?.switched !== !1;
5
5
  t && (r += 1, o &&= (clearTimeout(o.timer), null));
@@ -25,5 +25,4 @@ var r = 0, i = /* @__PURE__ */ new Set(), a = 2e3, o = null, s = (e) => {
25
25
  timer: t
26
26
  };
27
27
  };
28
- //#endregion
29
28
  export { p as i, d as n, m as r, f as t };
@@ -0,0 +1 @@
1
+ const e=require("./rolldown-runtime-BIInC43l.cjs"),t=require("./api-DrvhPN56.cjs"),n=require("./account-generation-ACCBzaI-.cjs");var r=e.t({info:()=>o,login:()=>i,logout:()=>a,onChange:()=>s}),i=async()=>typeof window>`u`?!1:(await t.o).account.login(location.origin).catch(()=>!1),a=async()=>{typeof window<`u`&&await(await t.o).account.logout().catch(()=>{})},o=async()=>{if(typeof window>`u`)return null;let e=await t.o.then(e=>e.account.info()).catch(()=>null);return e?{name:e.name,image:e.image,premium:e.premium,premiumUntil:e.premiumUntil?Date.parse(e.premiumUntil):null}:null},s=async e=>t.l?n.i(e):()=>{};Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return r}});
@@ -1,8 +1,8 @@
1
- import { t as e } from "./rolldown-runtime-Dy4uBu1J.js";
2
- import { o as t } from "./api-Di2Ff3jS.js";
1
+ import { t as e } from "./rolldown-runtime-CGnMp29N.js";
2
+ import { o as t } from "./api-DRglK7ft.js";
3
3
  import { STORAGE_ACCOUNT_CHANGED as n, STORAGE_ACCOUNT_PIN_UNSUPPORTED as r, STORAGE_NOT_FOUND as i } from "./messages.js";
4
- import { n as a, r as o, t as s } from "./account-generation-u31dhamM.js";
5
- //#region src/account-storage.ts
4
+ import { n as a, r as o, t as s } from "./account-generation-BKHNe-jL.js";
5
+ // src/account-storage.ts
6
6
  var c = /* @__PURE__ */ e({
7
7
  StorageAccountChangedError: () => f,
8
8
  StorageAccountPinUnsupportedError: () => p,
@@ -119,5 +119,4 @@ var c = /* @__PURE__ */ e({
119
119
  }, B = async (e, t) => {
120
120
  await D(E(t), (t, n) => t.remove(e, n));
121
121
  }, V = () => t.then((e) => e.cloud.fs.encryption()), H = () => t.then((e) => e.cloud.fs.unlock());
122
- //#endregion
123
122
  export { R as _, c as a, z as b, V as c, d, C as f, I as g, F as h, u as i, m as l, w as m, p as n, N as o, P as p, l as r, _ as s, f as t, h as u, B as v, H as y };
@@ -1,39 +1,3 @@
1
- //#region src/fs/types.d.ts
2
- type FileEntry$1 = {
3
- path: string;
4
- size: number;
5
- contentType: string | null;
6
- updatedAt: string | null;
7
- };
8
- type WriteData = Blob | ArrayBuffer | Uint8Array | string;
9
- /**
10
- * Which account a cloud call belongs to; library plumbing app code never passes. A multi-call
11
- * operation (a rename, a mount, a queue drain) captures one at its start so no call lands in an
12
- * account the realm switched to meanwhile. `{ generation }` is a ticket from `captureAccount()`;
13
- * `{ pin }` is the pin a queued entry was stamped with, sent as is.
14
- */
15
- type PinFrom = {
16
- readonly generation: number;
17
- } | {
18
- readonly pin: string;
19
- };
20
- type PinOptions = {
21
- pin?: PinFrom;
22
- };
23
- type FileSystem = {
24
- available: () => Promise<boolean>;
25
- list: (opts?: PinOptions) => Promise<FileEntry$1[]>;
26
- readFile: (path: string, opts?: PinOptions) => Promise<Blob>;
27
- writeFile: (path: string, data: WriteData, opts?: {
28
- contentType?: string;
29
- } & PinOptions) => Promise<void>;
30
- remove: (path: string, opts?: PinOptions) => Promise<void>;
31
- /** Captures the account generation this realm is on now; absent on a backing with no account. */
32
- captureAccount?: () => PinFrom;
33
- };
34
- declare namespace account_storage_d_exports {
35
- export { AccountTicket, CloudAvailability, EncryptionStatus, FileEntry, SealedRead, StorageAccountChangedError, StorageAccountPinUnsupportedError, StorageLockedError, StorageNotFoundError, StorageQuota, availability, available, captureAccount, encryption, isAccountChanged, isInvalidPin, isNotFound, knownPin, list, pinFor, quota, readFile, readFileSealed, remove, unlock, writeFile };
36
- }
37
1
  type FileEntry = {
38
2
  path: string;
39
3
  size: number;
@@ -103,18 +67,6 @@ declare class StorageAccountPinUnsupportedError extends Error {
103
67
  }
104
68
  /** Whether an error from this module means the account changed under the call, which was not made. */
105
69
  declare const isAccountChanged: (error: unknown) => boolean;
106
- /** Whether the api could not read a pin at all (a queued entry's record damaged on the device). */
107
- declare const isInvalidPin: (error: unknown) => boolean;
108
- type AccountTicket = {
109
- readonly generation: number;
110
- };
111
- /** The account generation this realm is on now. Synchronous, so it is captured before any await. */
112
- declare const captureAccount: () => AccountTicket;
113
- /** The pin a ticket's generation carries, if it was already taken. */
114
- declare const knownPin: (ticket: AccountTicket) => string | undefined;
115
- /** The pin a ticket's generation carries, taking it if need be; refused once the generation has moved. */
116
- declare const pinFor: (ticket: AccountTicket) => Promise<string>;
117
- declare const available: () => Promise<boolean>;
118
70
  type CloudAvailability = 'connected' | 'disconnected' | 'unknown';
119
71
  /**
120
72
  * Whether the cloud half is backed by an account, as three answers rather than two:
@@ -124,29 +76,12 @@ type CloudAvailability = 'connected' | 'disconnected' | 'unknown';
124
76
  * 'disconnected'; treating 'unknown' the same silently loses the write.
125
77
  */
126
78
  declare const availability: () => Promise<CloudAvailability>;
127
- declare const list: (opts?: PinOptions) => Promise<FileEntry[]>;
128
79
  declare const quota: () => Promise<StorageQuota>;
129
- declare const readFile: (path: string, opts?: PinOptions) => Promise<Blob>;
130
80
  /** The bytes of a cloud object and the seal time they carry, as an ISO string or null. */
131
81
  type SealedRead = {
132
82
  data: Uint8Array;
133
83
  sealedAt: string | null;
134
84
  };
135
- /**
136
- * A cloud read that also reports when the copy was sealed.
137
- *
138
- * `sealedAt` is an ISO string, or null for an envelope written before the seal time existed or a
139
- * data plane older than this call. It is authenticated, so the server can neither forge nor alter
140
- * it, but it is the WRITER's claim: it does not prove this copy is the newest, so an app that needs
141
- * that keeps a high-water mark per path. The listing's `updatedAt` is a server hint, for display only.
142
- * The bytes and the stamp come from one read of one envelope.
143
- */
144
- declare const readFileSealed: (path: string, opts?: PinOptions) => Promise<SealedRead>;
145
- declare const writeFile: (path: string, data: WriteData, opts?: {
146
- contentType?: string;
147
- } & PinOptions) => Promise<void>;
148
- declare const remove: (path: string, opts?: PinOptions) => Promise<void>;
149
85
  declare const encryption: () => Promise<EncryptionStatus>;
150
86
  declare const unlock: () => Promise<boolean>;
151
- //#endregion
152
- export { unlock as _, StorageAccountChangedError as a, PinOptions as b, StorageNotFoundError as c, availability as d, captureAccount as f, quota as g, isNotFound as h, SealedRead as i, StorageQuota as l, isAccountChanged as m, EncryptionStatus as n, StorageAccountPinUnsupportedError as o, encryption as p, FileEntry as r, StorageLockedError as s, CloudAvailability as t, account_storage_d_exports as u, FileEntry$1 as v, WriteData as x, FileSystem as y };
87
+ export { StorageAccountChangedError as a, StorageNotFoundError as c, encryption as d, isAccountChanged as f, unlock as h, SealedRead as i, StorageQuota as l, quota as m, EncryptionStatus as n, StorageAccountPinUnsupportedError as o, isNotFound as p, FileEntry as r, StorageLockedError as s, CloudAvailability as t, availability as u };
@@ -1 +1 @@
1
- const e=require("./rolldown-runtime-BIInC43l.cjs"),t=require("./api-BSk3dc_X.cjs"),n=require("./messages.cjs"),r=require("./account-generation-B0cJrpDx.cjs");var i=e.t({StorageAccountChangedError:()=>c,StorageAccountPinUnsupportedError:()=>l,StorageLockedError:()=>a,StorageNotFoundError:()=>o,availability:()=>k,available:()=>w,captureAccount:()=>p,encryption:()=>L,isAccountChanged:()=>u,isInvalidPin:()=>d,isNotFound:()=>s,knownPin:()=>y,list:()=>A,pinFor:()=>b,quota:()=>j,readFile:()=>M,readFileSealed:()=>P,remove:()=>I,unlock:()=>R,writeFile:()=>F}),a=class extends Error{code=`FKN_E2E_LOCKED`;constructor(){super(`storage locked: connect the app again to open encrypted data`)}},o=class extends Error{code=n.STORAGE_NOT_FOUND;constructor(e=`storage: no object at that path`){super(e)}},s=e=>e?.code===n.STORAGE_NOT_FOUND,c=class extends Error{code=n.STORAGE_ACCOUNT_CHANGED;constructor(e=`storage: the signed-in account changed, so this call was not made`){super(e)}},l=class extends Error{code=n.STORAGE_ACCOUNT_PIN_UNSUPPORTED;constructor(e=`storage: the FKN broker cannot pin calls to an account yet, so nothing was sent`){super(e)}},u=e=>e?.code===`FKN_ACCOUNT_CHANGED`||e instanceof Error&&e.message.startsWith(`fkn:account-changed`),d=e=>e instanceof Error&&e.message.startsWith(`fkn:account-pin-invalid`),f=e=>{throw e instanceof Error&&e.message.startsWith(`fkn:e2e-locked`)?new a:s(e)?new o(e.message):u(e)?new c:e instanceof Error&&e.message.startsWith(`fkn:account-pin-unsupported`)?new l:e instanceof Error&&(/^not found$/i.test(e.message)||/\(404\)$/.test(e.message))?new o(e.message):e},p=()=>(r.n(),{generation:r.t()}),m=new Map,h=null,g=e=>typeof e?.accountPin==`function`,_=(e,t)=>{let n=Promise.resolve(t.accountPin()).then(t=>{if(typeof t!=`string`||!t)throw Error(`storage: the broker answered no account pin`);return r.t()===e&&m.set(e,t),t});return h={generation:e,pin:n},n.catch(()=>{h?.pin===n&&(h=null)}),n},v=async(e,t)=>{let n=m.get(e.generation);if(n!==void 0)return n;if(e.generation!==r.t())throw new c;let i=await(h?.generation===e.generation?h.pin:_(e.generation,t)).catch(f);if(e.generation!==r.t())throw new c;return i},y=e=>m.get(e.generation),b=async e=>{let n=(await t.o).cloud.fs;if(!g(n))throw new l;return v(e,n)},x=e=>{for(let[t,n]of m)if(n===e)return t},S=e=>e?.pin??p(),C=async(e,n)=>{let i=(await t.o).cloud.fs;if(!g(i))throw new l;let a=`pin`in e?e.pin:await v(e,i);if(!g(i))throw new l;return n(i,{accountPin:a}).catch(t=>{if(u(t)){let t=`generation`in e?e.generation:x(a);t!==void 0&&r.r(t)}return f(t)})},w=()=>t.o.then(e=>e.cloud.fs.available()).catch(()=>!1),T=8e3,E=1e3,D=!1,O=async()=>{let e=(await t.o).cloud.fs;return typeof e.availability==`function`?e.availability():await e.available()?`connected`:`disconnected`},k=async()=>{let e=D?E:T,t=await new Promise(t=>{let n=setTimeout(()=>t(`timeout`),e);O().then(e=>{clearTimeout(n),t(e)},()=>{clearTimeout(n),t(`unknown`)})});return t===`timeout`?(D=!0,`unknown`):(D=!1,t)},A=e=>C(S(e),(e,t)=>e.list(t)),j=()=>t.o.then(e=>e.cloud.fs.quota()),M=async(e,t)=>{let n=await C(S(t),(t,n)=>t.readFile(e,n));return new Blob([n])},N=e=>{if(e===null||!Number.isFinite(e))return null;let t=new Date(e);return Number.isNaN(t.getTime())?null:t.toISOString()},P=async(e,t)=>C(S(t),async(t,n)=>{let r=t;if(typeof r.readFileSealed!=`function`)return{data:await t.readFile(e,n),sealedAt:null};let i=await r.readFileSealed(e,n);return{data:i.bytes,sealedAt:N(i.sealedAt)}}),F=async(e,t,n)=>{let r=S(n),i=t instanceof Blob?new Uint8Array(await t.arrayBuffer()):t;await C(r,(t,r)=>t.writeFile(e,i,n?.contentType??null,r))},I=async(e,t)=>{await C(S(t),(t,n)=>t.remove(e,n))},L=()=>t.o.then(e=>e.cloud.fs.encryption()),R=()=>t.o.then(e=>e.cloud.fs.unlock());Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return R}});
1
+ const e=require("./rolldown-runtime-BIInC43l.cjs"),t=require("./api-DrvhPN56.cjs"),n=require("./messages.cjs"),r=require("./account-generation-ACCBzaI-.cjs");var i=e.t({StorageAccountChangedError:()=>c,StorageAccountPinUnsupportedError:()=>l,StorageLockedError:()=>a,StorageNotFoundError:()=>o,availability:()=>k,available:()=>w,captureAccount:()=>p,encryption:()=>L,isAccountChanged:()=>u,isInvalidPin:()=>d,isNotFound:()=>s,knownPin:()=>y,list:()=>A,pinFor:()=>b,quota:()=>j,readFile:()=>M,readFileSealed:()=>P,remove:()=>I,unlock:()=>R,writeFile:()=>F}),a=class extends Error{code=`FKN_E2E_LOCKED`;constructor(){super(`storage locked: connect the app again to open encrypted data`)}},o=class extends Error{code=n.STORAGE_NOT_FOUND;constructor(e=`storage: no object at that path`){super(e)}},s=e=>e?.code===n.STORAGE_NOT_FOUND,c=class extends Error{code=n.STORAGE_ACCOUNT_CHANGED;constructor(e=`storage: the signed-in account changed, so this call was not made`){super(e)}},l=class extends Error{code=n.STORAGE_ACCOUNT_PIN_UNSUPPORTED;constructor(e=`storage: the FKN broker cannot pin calls to an account yet, so nothing was sent`){super(e)}},u=e=>e?.code===`FKN_ACCOUNT_CHANGED`||e instanceof Error&&e.message.startsWith(`fkn:account-changed`),d=e=>e instanceof Error&&e.message.startsWith(`fkn:account-pin-invalid`),f=e=>{throw e instanceof Error&&e.message.startsWith(`fkn:e2e-locked`)?new a:s(e)?new o(e.message):u(e)?new c:e instanceof Error&&e.message.startsWith(`fkn:account-pin-unsupported`)?new l:e instanceof Error&&(/^not found$/i.test(e.message)||/\(404\)$/.test(e.message))?new o(e.message):e},p=()=>(r.n(),{generation:r.t()}),m=new Map,h=null,g=e=>typeof e?.accountPin==`function`,_=(e,t)=>{let n=Promise.resolve(t.accountPin()).then(t=>{if(typeof t!=`string`||!t)throw Error(`storage: the broker answered no account pin`);return r.t()===e&&m.set(e,t),t});return h={generation:e,pin:n},n.catch(()=>{h?.pin===n&&(h=null)}),n},v=async(e,t)=>{let n=m.get(e.generation);if(n!==void 0)return n;if(e.generation!==r.t())throw new c;let i=await(h?.generation===e.generation?h.pin:_(e.generation,t)).catch(f);if(e.generation!==r.t())throw new c;return i},y=e=>m.get(e.generation),b=async e=>{let n=(await t.o).cloud.fs;if(!g(n))throw new l;return v(e,n)},x=e=>{for(let[t,n]of m)if(n===e)return t},S=e=>e?.pin??p(),C=async(e,n)=>{let i=(await t.o).cloud.fs;if(!g(i))throw new l;let a=`pin`in e?e.pin:await v(e,i);if(!g(i))throw new l;return n(i,{accountPin:a}).catch(t=>{if(u(t)){let t=`generation`in e?e.generation:x(a);t!==void 0&&r.r(t)}return f(t)})},w=()=>t.o.then(e=>e.cloud.fs.available()).catch(()=>!1),T=8e3,E=1e3,D=!1,O=async()=>{let e=(await t.o).cloud.fs;return typeof e.availability==`function`?e.availability():await e.available()?`connected`:`disconnected`},k=async()=>{let e=D?E:T,t=await new Promise(t=>{let n=setTimeout(()=>t(`timeout`),e);O().then(e=>{clearTimeout(n),t(e)},()=>{clearTimeout(n),t(`unknown`)})});return t===`timeout`?(D=!0,`unknown`):(D=!1,t)},A=e=>C(S(e),(e,t)=>e.list(t)),j=()=>t.o.then(e=>e.cloud.fs.quota()),M=async(e,t)=>{let n=await C(S(t),(t,n)=>t.readFile(e,n));return new Blob([n])},N=e=>{if(e===null||!Number.isFinite(e))return null;let t=new Date(e);return Number.isNaN(t.getTime())?null:t.toISOString()},P=async(e,t)=>C(S(t),async(t,n)=>{let r=t;if(typeof r.readFileSealed!=`function`)return{data:await t.readFile(e,n),sealedAt:null};let i=await r.readFileSealed(e,n);return{data:i.bytes,sealedAt:N(i.sealedAt)}}),F=async(e,t,n)=>{let r=S(n),i=t instanceof Blob?new Uint8Array(await t.arrayBuffer()):t;await C(r,(t,r)=>t.writeFile(e,i,n?.contentType??null,r))},I=async(e,t)=>{await C(S(t),(t,n)=>t.remove(e,n))},L=()=>t.o.then(e=>e.cloud.fs.encryption()),R=()=>t.o.then(e=>e.cloud.fs.unlock());Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return R}});
package/account.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-BIInC43l.cjs"),t=require("./api-BSk3dc_X.cjs"),n=require("./account-generation-B0cJrpDx.cjs");var r=e.t({info:()=>o,login:()=>i,logout:()=>a,onChange:()=>s}),i=async()=>typeof window>`u`?!1:(await t.o).account.login(location.origin).catch(()=>!1),a=async()=>{typeof window<`u`&&await(await t.o).account.logout().catch(()=>{})},o=async()=>{if(typeof window>`u`)return null;let e=await t.o.then(e=>e.account.info()).catch(()=>null);return e?{name:e.name,image:e.image,premium:e.premium,premiumUntil:e.premiumUntil?Date.parse(e.premiumUntil):null}:null},s=async e=>t.l?n.i(e):()=>{};exports.info=o,exports.login=i,exports.logout=a,exports.onChange=s,Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return r}});
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./account-m2iCmNui.cjs");exports.info=e.n,exports.login=e.r,exports.logout=e.i,exports.onChange=e.a;
package/account.d.ts CHANGED
@@ -1,40 +1,3 @@
1
- import { a as AccountChange } from "./contract-BGMJVvTg.js";
2
- declare namespace account_d_exports {
3
- export { AccountChange, AccountInfo, info, login, logout, onChange };
4
- }
5
- export type AccountInfo = {
6
- /** the account's display name (a username, not necessarily a real name) */
7
- name: string;
8
- /** profile image URL, or null if none is set */
9
- image: string | null;
10
- /** the account has an active paid subscription */
11
- premium: boolean;
12
- /** when the current subscription lapses, as a ms epoch, or null when not subscribed */
13
- premiumUntil: number | null;
14
- };
15
- export declare const login: () => Promise<boolean>;
16
- export declare const logout: () => Promise<void>;
17
- export declare const info: () => Promise<AccountInfo | null>;
18
- /**
19
- * Calls `callback` whenever the account this page acts as may have changed (a switch, a sign-in or a
20
- * sign-out, in this tab or another), and when the connection is renewed without one. Works in a window
21
- * and in a worker bridged with `relayWorker`; resolves to a no-op where there is no FKN transport at all.
22
- *
23
- * `change.switched` says which. True: this page may now act as another account, or as none, so drop
24
- * what the old account put in memory (its lists, any open work) and read again; a storage call made
25
- * before this callback never lands in the new account (it is refused with `StorageAccountChangedError`).
26
- * It is also true when fkn.app is too old to tell (before 2026-10-02) and when the library moved on its
27
- * own after a refusal, so treating true as a switch is always safe. False: fkn.app saw the same account.
28
- * Its connect token was renewed, or an app in this browser signed in or out of FKN on its own, this one
29
- * included, so read `info()` again to learn whether this page is still signed in. Calls made before it
30
- * still land. A switch fkn.app could not see, because its document was replaced in between, reaches you
31
- * as true once a storage call is refused for it.
32
- *
33
- * Storage moves to the new account BEFORE any callback runs. Work the app started before a switch and
34
- * resumes after it is the app's to check: keep a counter this callback bumps when `switched` is true,
35
- * and compare it synchronously right before the storage call, which captures the account in the same
36
- * synchronous step, so the check and the call are atomic.
37
- */
38
- export declare const onChange: (callback: (change: AccountChange) => void) => Promise<() => void>;
39
- //#endregion
40
- export { type AccountChange, account_d_exports as t };
1
+ import { a as AccountChange } from "./contract-0rua6Wsh.js";
2
+ import { a as logout, i as login, o as onChange, r as info, t as AccountInfo } from "./account-Bm7uIcQo.js";
3
+ export { type AccountChange, AccountInfo, info, login, logout, onChange };
package/account.js CHANGED
@@ -1,23 +1 @@
1
- import { t as e } from "./rolldown-runtime-Dy4uBu1J.js";
2
- import { l as t, o as n } from "./api-Di2Ff3jS.js";
3
- import { i as r } from "./account-generation-u31dhamM.js";
4
- //#region src/account.ts
5
- var i = /* @__PURE__ */ e({
6
- info: () => s,
7
- login: () => a,
8
- logout: () => o,
9
- onChange: () => c
10
- }), a = async () => typeof window > "u" ? !1 : (await n).account.login(location.origin).catch(() => !1), o = async () => {
11
- typeof window < "u" && await (await n).account.logout().catch(() => {});
12
- }, s = async () => {
13
- if (typeof window > "u") return null;
14
- let e = await n.then((e) => e.account.info()).catch(() => null);
15
- return e ? {
16
- name: e.name,
17
- image: e.image,
18
- premium: e.premium,
19
- premiumUntil: e.premiumUntil ? Date.parse(e.premiumUntil) : null
20
- } : null;
21
- }, c = async (e) => t ? r(e) : () => {};
22
- //#endregion
23
- export { s as info, a as login, o as logout, c as onChange, i as t };
1
+ export { n as info, r as login, i as logout, a as onChange } from "./account-Uh0-1Cbp.js";
@@ -1,11 +1,8 @@
1
- import { D as RelayChoice } from "./index-C5DdoMGo.js";
2
- import { D as IpFamily, H as ProxyFetchInput, I as PackagesErrorCode, N as OverlayState, Nt as StoragePutWire, P as PackageQuery, Q as RoomClaimOptions, R as PickOptions, T as InstallOptions, Ut as UdpDatagram, V as ProxyFetchInit, Vt as TcpSocketOptions, Wt as UdpSocketOptions, X as Resolvers, Xt as WriteData, a as AccountChange, at as RoomJoinOptions, b as FrameConsentAnswer, c as AdoptRequest, d as ConflictRequest, dt as RoomPermission, ht as RoomsErrorCode, kt as StorageErrorCode, l as AdoptState, m as ConnectOptions, mt as RoomType, o as AccountPinOptions, p as ConnectAvailability, rt as RoomEvent, st as RoomMailbox, u as ConflictChoice, ut as RoomOpenOptions, x as FrameConsentRequest, z as Placement, zt as TcpSocketListenerOptions } from "./contract-BGMJVvTg.js";
3
- import { o as TcpSocketOption, x as UdpSocketOption } from "./wire-Fk5pJaoy.js";
1
+ import { D as RelayChoice } from "./index-Cu5EcdK0.js";
2
+ import { D as IpFamily, H as ProxyFetchInput, I as PackagesErrorCode, N as OverlayState, Nt as StoragePutWire, P as PackageQuery, Q as RoomClaimOptions, R as PickOptions, T as InstallOptions, Ut as UdpDatagram, V as ProxyFetchInit, Vt as TcpSocketOptions, Wt as UdpSocketOptions, X as Resolvers, Xt as WriteData, a as AccountChange, at as RoomJoinOptions, b as FrameConsentAnswer, c as AdoptRequest, d as ConflictRequest, dt as RoomPermission, ht as RoomsErrorCode, kt as StorageErrorCode, l as AdoptState, m as ConnectOptions, mt as RoomType, o as AccountPinOptions, p as ConnectAvailability, rt as RoomEvent, st as RoomMailbox, u as ConflictChoice, ut as RoomOpenOptions, x as FrameConsentRequest, z as Placement, zt as TcpSocketListenerOptions } from "./contract-0rua6Wsh.js";
3
+ import { o as TcpSocketOption, x as UdpSocketOption } from "./wire-DhmLnYEU.js";
4
4
  import { Remote } from "osra";
5
- //#region src/api-epochs.d.ts
6
5
  type EpochListener<T> = (remote: T, epoch: number) => void;
7
- //#endregion
8
- //#region src/api.d.ts
9
6
  declare const hasTransport: boolean;
10
7
  type Api = Remote<Resolvers>;
11
8
  /**
@@ -2828,5 +2825,4 @@ declare const currentApiEpoch: () => {
2828
2825
  /** Activity on the broker connection: every call flows through the facade, so these see all of it. */
2829
2826
  declare const apiLastCall: () => number;
2830
2827
  declare const apiInFlight: () => number;
2831
- //#endregion
2832
2828
  export { apiLastCall as a, currentApiEpoch as c, apiInFlight as i, hasTransport as l, BrokerUnreachableError as n, apiPromise as o, OwnChannelUnavailableError as r, apiWithin as s, API_DEADLINE_MS as t, onApiEpoch as u };