@hatk/hatk 0.0.1-alpha.9 → 0.0.1-alpha.90

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 (218) hide show
  1. package/dist/adapter.d.ts +19 -0
  2. package/dist/adapter.d.ts.map +1 -0
  3. package/dist/adapter.js +113 -0
  4. package/dist/backfill.d.ts +29 -2
  5. package/dist/backfill.d.ts.map +1 -1
  6. package/dist/backfill.js +137 -51
  7. package/dist/car.d.ts +20 -0
  8. package/dist/car.d.ts.map +1 -1
  9. package/dist/car.js +108 -0
  10. package/dist/cli.js +247 -1043
  11. package/dist/config.d.ts +145 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +61 -8
  14. package/dist/database/adapter-factory.d.ts +6 -0
  15. package/dist/database/adapter-factory.d.ts.map +1 -0
  16. package/dist/database/adapter-factory.js +20 -0
  17. package/dist/database/adapters/duckdb-search.d.ts +12 -0
  18. package/dist/database/adapters/duckdb-search.d.ts.map +1 -0
  19. package/dist/database/adapters/duckdb-search.js +27 -0
  20. package/dist/database/adapters/duckdb.d.ts +25 -0
  21. package/dist/database/adapters/duckdb.d.ts.map +1 -0
  22. package/dist/database/adapters/duckdb.js +161 -0
  23. package/dist/database/adapters/sqlite-search.d.ts +16 -0
  24. package/dist/database/adapters/sqlite-search.d.ts.map +1 -0
  25. package/dist/database/adapters/sqlite-search.js +76 -0
  26. package/dist/database/adapters/sqlite.d.ts +18 -0
  27. package/dist/database/adapters/sqlite.d.ts.map +1 -0
  28. package/dist/database/adapters/sqlite.js +88 -0
  29. package/dist/{db.d.ts → database/db.d.ts} +68 -6
  30. package/dist/database/db.d.ts.map +1 -0
  31. package/dist/database/db.js +1775 -0
  32. package/dist/database/dialect.d.ts +45 -0
  33. package/dist/database/dialect.d.ts.map +1 -0
  34. package/dist/database/dialect.js +72 -0
  35. package/dist/{fts.d.ts → database/fts.d.ts} +7 -0
  36. package/dist/database/fts.d.ts.map +1 -0
  37. package/dist/{fts.js → database/fts.js} +122 -34
  38. package/dist/database/index.d.ts +7 -0
  39. package/dist/database/index.d.ts.map +1 -0
  40. package/dist/database/index.js +6 -0
  41. package/dist/database/ports.d.ts +50 -0
  42. package/dist/database/ports.d.ts.map +1 -0
  43. package/dist/database/ports.js +1 -0
  44. package/dist/{schema.d.ts → database/schema.d.ts} +16 -3
  45. package/dist/database/schema.d.ts.map +1 -0
  46. package/dist/{schema.js → database/schema.js} +126 -44
  47. package/dist/dev-entry.d.ts +8 -0
  48. package/dist/dev-entry.d.ts.map +1 -0
  49. package/dist/dev-entry.js +127 -0
  50. package/dist/feeds.d.ts +26 -8
  51. package/dist/feeds.d.ts.map +1 -1
  52. package/dist/feeds.js +72 -16
  53. package/dist/hooks.d.ts +102 -0
  54. package/dist/hooks.d.ts.map +1 -0
  55. package/dist/hooks.js +186 -0
  56. package/dist/hydrate.d.ts +49 -6
  57. package/dist/hydrate.d.ts.map +1 -1
  58. package/dist/hydrate.js +21 -20
  59. package/dist/indexer.d.ts +156 -3
  60. package/dist/indexer.d.ts.map +1 -1
  61. package/dist/indexer.js +539 -94
  62. package/dist/jetstream.d.ts +118 -0
  63. package/dist/jetstream.d.ts.map +1 -0
  64. package/dist/jetstream.js +225 -0
  65. package/dist/labels.d.ts +36 -0
  66. package/dist/labels.d.ts.map +1 -1
  67. package/dist/labels.js +71 -6
  68. package/dist/lex-types.d.ts +2 -0
  69. package/dist/lex-types.d.ts.map +1 -1
  70. package/dist/lexicon-resolve.d.ts.map +1 -1
  71. package/dist/lexicon-resolve.js +27 -112
  72. package/dist/lexicons/com/atproto/label/defs.json +75 -0
  73. package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
  74. package/dist/lexicons/com/atproto/repo/strongRef.json +21 -0
  75. package/dist/lexicons/dev/hatk/applyWrites.json +87 -0
  76. package/dist/lexicons/dev/hatk/createRecord.json +40 -0
  77. package/dist/lexicons/dev/hatk/createReport.json +48 -0
  78. package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
  79. package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
  80. package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
  81. package/dist/lexicons/dev/hatk/describeLabels.json +45 -0
  82. package/dist/lexicons/dev/hatk/getFeed.json +30 -0
  83. package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
  84. package/dist/lexicons/dev/hatk/getRecord.json +26 -0
  85. package/dist/lexicons/dev/hatk/getRecords.json +32 -0
  86. package/dist/lexicons/dev/hatk/putPreference.json +28 -0
  87. package/dist/lexicons/dev/hatk/putRecord.json +41 -0
  88. package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
  89. package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
  90. package/dist/logger.d.ts +29 -0
  91. package/dist/logger.d.ts.map +1 -1
  92. package/dist/logger.js +29 -0
  93. package/dist/main.js +198 -75
  94. package/dist/mst.d.ts +15 -0
  95. package/dist/mst.d.ts.map +1 -1
  96. package/dist/mst.js +13 -0
  97. package/dist/oauth/db.d.ts +16 -1
  98. package/dist/oauth/db.d.ts.map +1 -1
  99. package/dist/oauth/db.js +74 -19
  100. package/dist/oauth/discovery.d.ts +10 -0
  101. package/dist/oauth/discovery.d.ts.map +1 -1
  102. package/dist/oauth/discovery.js +54 -2
  103. package/dist/oauth/server.d.ts +93 -1
  104. package/dist/oauth/server.d.ts.map +1 -1
  105. package/dist/oauth/server.js +416 -39
  106. package/dist/oauth/service-describe.d.ts +42 -0
  107. package/dist/oauth/service-describe.d.ts.map +1 -0
  108. package/dist/oauth/service-describe.js +108 -0
  109. package/dist/oauth/session.d.ts +32 -0
  110. package/dist/oauth/session.d.ts.map +1 -0
  111. package/dist/oauth/session.js +131 -0
  112. package/dist/opengraph.d.ts +10 -0
  113. package/dist/opengraph.d.ts.map +1 -1
  114. package/dist/opengraph.js +94 -42
  115. package/dist/pds-proxy.d.ts +82 -0
  116. package/dist/pds-proxy.d.ts.map +1 -0
  117. package/dist/pds-proxy.js +356 -0
  118. package/dist/private-collections.d.ts +13 -0
  119. package/dist/private-collections.d.ts.map +1 -0
  120. package/dist/private-collections.js +27 -0
  121. package/dist/push.d.ts +54 -0
  122. package/dist/push.d.ts.map +1 -0
  123. package/dist/push.js +367 -0
  124. package/dist/renderer.d.ts +27 -0
  125. package/dist/renderer.d.ts.map +1 -0
  126. package/dist/renderer.js +46 -0
  127. package/dist/resolve-hatk.d.ts +6 -0
  128. package/dist/resolve-hatk.d.ts.map +1 -0
  129. package/dist/resolve-hatk.js +20 -0
  130. package/dist/response.d.ts +16 -0
  131. package/dist/response.d.ts.map +1 -0
  132. package/dist/response.js +69 -0
  133. package/dist/scanner.d.ts +21 -0
  134. package/dist/scanner.d.ts.map +1 -0
  135. package/dist/scanner.js +88 -0
  136. package/dist/seed.d.ts +19 -0
  137. package/dist/seed.d.ts.map +1 -1
  138. package/dist/seed.js +43 -4
  139. package/dist/server-init.d.ts +8 -0
  140. package/dist/server-init.d.ts.map +1 -0
  141. package/dist/server-init.js +62 -0
  142. package/dist/server.d.ts +34 -3
  143. package/dist/server.d.ts.map +1 -1
  144. package/dist/server.js +1021 -649
  145. package/dist/setup.d.ts +28 -1
  146. package/dist/setup.d.ts.map +1 -1
  147. package/dist/setup.js +50 -3
  148. package/dist/spaces/blob.d.ts +51 -0
  149. package/dist/spaces/blob.d.ts.map +1 -0
  150. package/dist/spaces/blob.js +111 -0
  151. package/dist/spaces/credential.d.ts +62 -0
  152. package/dist/spaces/credential.d.ts.map +1 -0
  153. package/dist/spaces/credential.js +184 -0
  154. package/dist/spaces/engine.d.ts +97 -0
  155. package/dist/spaces/engine.d.ts.map +1 -0
  156. package/dist/spaces/engine.js +559 -0
  157. package/dist/spaces/guard.d.ts +41 -0
  158. package/dist/spaces/guard.d.ts.map +1 -0
  159. package/dist/spaces/guard.js +79 -0
  160. package/dist/spaces/identity.d.ts +37 -0
  161. package/dist/spaces/identity.d.ts.map +1 -0
  162. package/dist/spaces/identity.js +88 -0
  163. package/dist/spaces/index.d.ts +55 -0
  164. package/dist/spaces/index.d.ts.map +1 -0
  165. package/dist/spaces/index.js +133 -0
  166. package/dist/spaces/notify.d.ts +51 -0
  167. package/dist/spaces/notify.d.ts.map +1 -0
  168. package/dist/spaces/notify.js +121 -0
  169. package/dist/spaces/records.d.ts +37 -0
  170. package/dist/spaces/records.d.ts.map +1 -0
  171. package/dist/spaces/records.js +63 -0
  172. package/dist/spaces/store.d.ts +51 -0
  173. package/dist/spaces/store.d.ts.map +1 -0
  174. package/dist/spaces/store.js +99 -0
  175. package/dist/spaces/uri.d.ts +60 -0
  176. package/dist/spaces/uri.d.ts.map +1 -0
  177. package/dist/spaces/uri.js +97 -0
  178. package/dist/spaces/verify.d.ts +39 -0
  179. package/dist/spaces/verify.d.ts.map +1 -0
  180. package/dist/spaces/verify.js +87 -0
  181. package/dist/spaces/viewer.d.ts +51 -0
  182. package/dist/spaces/viewer.d.ts.map +1 -0
  183. package/dist/spaces/viewer.js +167 -0
  184. package/dist/spaces/visibility.d.ts +57 -0
  185. package/dist/spaces/visibility.d.ts.map +1 -0
  186. package/dist/spaces/visibility.js +81 -0
  187. package/dist/templates/feed.tpl +18 -0
  188. package/dist/templates/hook.tpl +5 -0
  189. package/dist/templates/label.tpl +15 -0
  190. package/dist/templates/og.tpl +17 -0
  191. package/dist/templates/seed.tpl +11 -0
  192. package/dist/templates/setup.tpl +5 -0
  193. package/dist/templates/test-feed.tpl +19 -0
  194. package/dist/templates/test-xrpc.tpl +19 -0
  195. package/dist/templates/xrpc.tpl +53 -0
  196. package/dist/test.d.ts +3 -1
  197. package/dist/test.d.ts.map +1 -1
  198. package/dist/test.js +60 -36
  199. package/dist/views.js +1 -1
  200. package/dist/vite-plugin.d.ts +1 -1
  201. package/dist/vite-plugin.d.ts.map +1 -1
  202. package/dist/vite-plugin.js +254 -66
  203. package/dist/xrpc.d.ts +101 -12
  204. package/dist/xrpc.d.ts.map +1 -1
  205. package/dist/xrpc.js +255 -55
  206. package/package.json +21 -9
  207. package/public/admin-auth.js +271 -306
  208. package/public/admin.html +177 -61
  209. package/dist/db.d.ts.map +0 -1
  210. package/dist/db.js +0 -1361
  211. package/dist/fts.d.ts.map +0 -1
  212. package/dist/oauth/hooks.d.ts +0 -10
  213. package/dist/oauth/hooks.d.ts.map +0 -1
  214. package/dist/oauth/hooks.js +0 -40
  215. package/dist/schema.d.ts.map +0 -1
  216. package/dist/test-browser.d.ts +0 -14
  217. package/dist/test-browser.d.ts.map +0 -1
  218. package/dist/test-browser.js +0 -26
@@ -1,320 +1,285 @@
1
- function g(s) {
2
- const t = s instanceof Uint8Array ? s : new Uint8Array(s)
3
- let o = ''
4
- for (let e = 0; e < t.length; e++) o += String.fromCharCode(t[e])
5
- return btoa(o).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
1
+ //#region ../oauth-client/src/crypto.js
2
+ function e(e) {
3
+ let t = e instanceof Uint8Array ? e : new Uint8Array(e), n = "";
4
+ for (let e = 0; e < t.length; e++) n += String.fromCharCode(t[e]);
5
+ return btoa(n).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
6
6
  }
7
- function f(s = 32) {
8
- return g(crypto.getRandomValues(new Uint8Array(s)))
7
+ function t(t = 32) {
8
+ return e(crypto.getRandomValues(new Uint8Array(t)));
9
9
  }
10
- async function D(s) {
11
- return new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(s)))
10
+ async function n(e) {
11
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e)));
12
12
  }
13
- async function k(s) {
14
- return g(await D(s))
13
+ async function r(t) {
14
+ return e(await n(t));
15
15
  }
16
- async function E(s, t, o) {
17
- const e = new TextEncoder(),
18
- n = g(e.encode(JSON.stringify(s))),
19
- r = g(e.encode(JSON.stringify(t))),
20
- a = `${n}.${r}`,
21
- i = await crypto.subtle.sign({ name: 'ECDSA', hash: 'SHA-256' }, o, e.encode(a))
22
- return `${a}.${g(i)}`
16
+ async function i(t, n, r) {
17
+ let i = new TextEncoder(), a = `${e(i.encode(JSON.stringify(t)))}.${e(i.encode(JSON.stringify(n)))}`;
18
+ return `${a}.${e(await crypto.subtle.sign({
19
+ name: "ECDSA",
20
+ hash: "SHA-256"
21
+ }, r, i.encode(a)))}`;
23
22
  }
24
- const x = 1,
25
- d = 'dpop-keys',
26
- p = 'dpop-key',
27
- y = /* @__PURE__ */ new Map()
28
- function m(s) {
29
- const t = y.get(s)
30
- if (t) return t
31
- const o = new Promise((e, n) => {
32
- const r = indexedDB.open(`appview-oauth-${s}`, x)
33
- ;((r.onerror = () => n(r.error)),
34
- (r.onsuccess = () => e(r.result)),
35
- (r.onupgradeneeded = (a) => {
36
- const i = a.target.result
37
- i.objectStoreNames.contains(d) || i.createObjectStore(d, { keyPath: 'id' })
38
- }))
39
- })
40
- return (y.set(s, o), o)
23
+ //#endregion
24
+ //#region ../oauth-client/src/dpop.js
25
+ var a = "dpop-keys", o = "dpop-key", s = /* @__PURE__ */ new Map();
26
+ function c(e) {
27
+ let t = s.get(e);
28
+ if (t) return t;
29
+ let n = new Promise((t, n) => {
30
+ let r = indexedDB.open(`appview-oauth-${e}`, 1);
31
+ r.onerror = () => n(r.error), r.onsuccess = () => t(r.result), r.onupgradeneeded = (e) => {
32
+ let t = e.target.result;
33
+ t.objectStoreNames.contains(a) || t.createObjectStore(a, { keyPath: "id" });
34
+ };
35
+ });
36
+ return s.set(e, n), n;
41
37
  }
42
- async function $(s) {
43
- const t = await m(s)
44
- return new Promise((o, e) => {
45
- const r = t.transaction(d, 'readonly').objectStore(d).get(p)
46
- ;((r.onsuccess = () => o(r.result || null)), (r.onerror = () => e(r.error)))
47
- })
38
+ async function l(e) {
39
+ let t = await c(e);
40
+ return new Promise((e, n) => {
41
+ let r = t.transaction(a, "readonly").objectStore(a).get(o);
42
+ r.onsuccess = () => e(r.result || null), r.onerror = () => n(r.error);
43
+ });
48
44
  }
49
- async function b(s, t, o) {
50
- const e = await m(s)
51
- return new Promise((n, r) => {
52
- const i = e.transaction(d, 'readwrite').objectStore(d).put({
53
- id: p,
54
- privateKey: t,
55
- publicJwk: o,
56
- createdAt: Date.now(),
57
- })
58
- ;((i.onsuccess = () => n()), (i.onerror = () => r(i.error)))
59
- })
45
+ async function u(e, t, n) {
46
+ let r = await c(e);
47
+ return new Promise((e, i) => {
48
+ let s = r.transaction(a, "readwrite").objectStore(a).put({
49
+ id: o,
50
+ privateKey: t,
51
+ publicJwk: n,
52
+ createdAt: Date.now()
53
+ });
54
+ s.onsuccess = () => e(), s.onerror = () => i(s.error);
55
+ });
60
56
  }
61
- async function P(s) {
62
- const t = await $(s)
63
- if (t) return t
64
- const o = await crypto.subtle.generateKey(
65
- { name: 'ECDSA', namedCurve: 'P-256' },
66
- !1,
67
- // non-extractable private key
68
- ['sign'],
69
- ),
70
- e = await crypto.subtle.exportKey('jwk', o.publicKey)
71
- return (await b(s, o.privateKey, e), { id: p, privateKey: o.privateKey, publicJwk: e, createdAt: Date.now() })
57
+ async function d(e) {
58
+ let t = await l(e);
59
+ if (t) return t;
60
+ let n = await crypto.subtle.generateKey({
61
+ name: "ECDSA",
62
+ namedCurve: "P-256"
63
+ }, !1, ["sign"]), r = await crypto.subtle.exportKey("jwk", n.publicKey);
64
+ return await u(e, n.privateKey, r), {
65
+ id: o,
66
+ privateKey: n.privateKey,
67
+ publicJwk: r,
68
+ createdAt: Date.now()
69
+ };
72
70
  }
73
- async function v(s) {
74
- const t = await m(s)
75
- return new Promise((o, e) => {
76
- const r = t.transaction(d, 'readwrite').objectStore(d).delete(p)
77
- ;((r.onsuccess = () => o()), (r.onerror = () => e(r.error)))
78
- })
71
+ async function f(e) {
72
+ let t = await c(e);
73
+ return new Promise((e, n) => {
74
+ let r = t.transaction(a, "readwrite").objectStore(a).delete(o);
75
+ r.onsuccess = () => e(), r.onerror = () => n(r.error);
76
+ });
79
77
  }
80
- async function w(s, t, o, e) {
81
- const n = await P(s),
82
- { kty: r, crv: a, x: i, y: c } = n.publicJwk,
83
- h = { alg: 'ES256', typ: 'dpop+jwt', jwk: { kty: r, crv: a, x: i, y: c } },
84
- l = {
85
- jti: f(16),
86
- htm: t,
87
- htu: o.split('?')[0],
88
- iat: Math.floor(Date.now() / 1e3),
89
- }
90
- return (e && (l.ath = await k(e)), E(h, l, n.privateKey))
78
+ async function p(e, n, a, o) {
79
+ let s = await d(e), { kty: c, crv: l, x: u, y: f } = s.publicJwk, p = {
80
+ alg: "ES256",
81
+ typ: "dpop+jwt",
82
+ jwk: {
83
+ kty: c,
84
+ crv: l,
85
+ x: u,
86
+ y: f
87
+ }
88
+ }, m = {
89
+ jti: t(16),
90
+ htm: n,
91
+ htu: a.split("?")[0],
92
+ iat: Math.floor(Date.now() / 1e3)
93
+ };
94
+ return o && (m.ath = await r(o)), i(p, m, s.privateKey);
91
95
  }
92
- function U(s) {
93
- const t = (e) => `appview_${s}_${e}`,
94
- o = /* @__PURE__ */ new Set(['codeVerifier', 'oauthState', 'redirectUri'])
95
- return {
96
- get(e) {
97
- return (o.has(e) ? sessionStorage : localStorage).getItem(t(e))
98
- },
99
- set(e, n) {
100
- ;(o.has(e) ? sessionStorage : localStorage).setItem(t(e), n)
101
- },
102
- remove(e) {
103
- ;(o.has(e) ? sessionStorage : localStorage).removeItem(t(e))
104
- },
105
- clear() {
106
- for (const e of o) sessionStorage.removeItem(t(e))
107
- for (const e of ['accessToken', 'refreshToken', 'tokenExpiresAt', 'userDid', 'clientId'])
108
- localStorage.removeItem(t(e))
109
- },
110
- }
96
+ //#endregion
97
+ //#region ../oauth-client/src/storage.js
98
+ function m(e) {
99
+ let t = (t) => `appview_${e}_${t}`, n = /* @__PURE__ */ new Set([
100
+ "codeVerifier",
101
+ "oauthState",
102
+ "redirectUri"
103
+ ]);
104
+ return {
105
+ get(e) {
106
+ return (n.has(e) ? sessionStorage : localStorage).getItem(t(e));
107
+ },
108
+ set(e, r) {
109
+ (n.has(e) ? sessionStorage : localStorage).setItem(t(e), r);
110
+ },
111
+ remove(e) {
112
+ (n.has(e) ? sessionStorage : localStorage).removeItem(t(e));
113
+ },
114
+ clear() {
115
+ for (let e of n) sessionStorage.removeItem(t(e));
116
+ for (let e of [
117
+ "accessToken",
118
+ "refreshToken",
119
+ "tokenExpiresAt",
120
+ "userDid",
121
+ "clientId"
122
+ ]) localStorage.removeItem(t(e));
123
+ }
124
+ };
111
125
  }
112
- const S = 5e3
113
- async function A(s, t) {
114
- const o = `appview_${s}_lock_${t}`,
115
- e = `${Date.now()}_${Math.random()}`,
116
- n = Date.now() + S
117
- for (; Date.now() < n; ) {
118
- const r = localStorage.getItem(o)
119
- if (r) {
120
- const a = parseInt(r.split('_')[0])
121
- if (Date.now() - a > S) localStorage.removeItem(o)
122
- else {
123
- await new Promise((i) => setTimeout(i, 50))
124
- continue
125
- }
126
- }
127
- if ((localStorage.setItem(o, e), await new Promise((a) => setTimeout(a, 10)), localStorage.getItem(o) === e))
128
- return e
129
- }
130
- return null
126
+ var h = 5e3;
127
+ async function g(e, t) {
128
+ let n = `appview_${e}_lock_${t}`, r = `${Date.now()}_${Math.random()}`, i = Date.now() + h;
129
+ for (; Date.now() < i;) {
130
+ let e = localStorage.getItem(n);
131
+ if (e) {
132
+ let t = parseInt(e.split("_")[0]);
133
+ if (Date.now() - t > h) localStorage.removeItem(n);
134
+ else {
135
+ await new Promise((e) => setTimeout(e, 50));
136
+ continue;
137
+ }
138
+ }
139
+ if (localStorage.setItem(n, r), await new Promise((e) => setTimeout(e, 10)), localStorage.getItem(n) === r) return r;
140
+ }
141
+ return null;
131
142
  }
132
- function O(s, t, o) {
133
- const e = `appview_${s}_lock_${t}`
134
- localStorage.getItem(e) === o && localStorage.removeItem(e)
143
+ function _(e, t, n) {
144
+ let r = `appview_${e}_lock_${t}`;
145
+ localStorage.getItem(r) === n && localStorage.removeItem(r);
135
146
  }
136
- const _ = 6e4
137
- class K {
138
- /**
139
- * @param {object} opts
140
- * @param {string} opts.server - Appview server URL (e.g. 'https://my-appview.example.com')
141
- * @param {string} [opts.clientId] - OAuth client_id (defaults to current origin)
142
- * @param {string} [opts.redirectUri] - Callback URL (defaults to current page)
143
- * @param {string} [opts.scope] - OAuth scope (defaults to 'atproto')
144
- */
145
- constructor({ server: t, clientId: o, redirectUri: e, scope: n }) {
146
- ;((this.server = t.replace(/\/$/, '')),
147
- (this.clientId = o || window.location.origin),
148
- (this.redirectUri = e || window.location.origin + window.location.pathname),
149
- (this.scope = n || 'atproto'),
150
- (this.namespace = this.clientId.replace(/[^a-z0-9]/gi, '_').slice(0, 32)),
151
- (this.storage = U(this.namespace)),
152
- (this._initPromise = null))
153
- }
154
- /** Ensure DPoP key exists in IndexedDB. */
155
- async init() {
156
- return (this._initPromise || (this._initPromise = P(this.namespace)), this._initPromise)
157
- }
158
- /** Start the OAuth login flow (redirects the browser). */
159
- async login(t) {
160
- await this.init()
161
- const o = f(32),
162
- e = await k(o),
163
- n = f(16)
164
- ;(this.storage.set('codeVerifier', o),
165
- this.storage.set('oauthState', n),
166
- this.storage.set('clientId', this.clientId),
167
- this.storage.set('redirectUri', this.redirectUri))
168
- const r = `${this.server}/oauth/par`,
169
- a = await w(this.namespace, 'POST', r),
170
- i = new URLSearchParams({
171
- client_id: this.clientId,
172
- redirect_uri: this.redirectUri,
173
- response_type: 'code',
174
- code_challenge: e,
175
- code_challenge_method: 'S256',
176
- scope: this.scope,
177
- state: n,
178
- })
179
- t && i.set('login_hint', t)
180
- const c = await fetch(r, {
181
- method: 'POST',
182
- headers: {
183
- 'Content-Type': 'application/x-www-form-urlencoded',
184
- DPoP: a,
185
- },
186
- body: i.toString(),
187
- })
188
- if (!c.ok) {
189
- const u = await c.json().catch(() => ({}))
190
- throw new Error(`PAR failed: ${u.error || c.status}`)
191
- }
192
- const { request_uri: h } = await c.json(),
193
- l = new URLSearchParams({
194
- request_uri: h,
195
- client_id: this.clientId,
196
- })
197
- window.location.href = `${this.server}/oauth/authorize?${l}`
198
- }
199
- /**
200
- * Handle the OAuth callback after the redirect.
201
- * Call this on page load — returns true if a callback was processed.
202
- */
203
- async handleCallback() {
204
- const t = new URLSearchParams(window.location.search),
205
- o = t.get('code'),
206
- e = t.get('state'),
207
- n = t.get('error')
208
- if (n) throw new Error(`OAuth error: ${n} - ${t.get('error_description') || ''}`)
209
- if (!o || !e) return !1
210
- const r = this.storage.get('oauthState')
211
- if (e !== r) throw new Error('OAuth state mismatch')
212
- const a = this.storage.get('codeVerifier'),
213
- i = this.storage.get('clientId'),
214
- c = this.storage.get('redirectUri')
215
- if (!a || !i || !c) throw new Error('Missing OAuth session data')
216
- await this.init()
217
- const h = `${this.server}/oauth/token`,
218
- l = await w(this.namespace, 'POST', h),
219
- u = await fetch(h, {
220
- method: 'POST',
221
- headers: {
222
- 'Content-Type': 'application/x-www-form-urlencoded',
223
- DPoP: l,
224
- },
225
- body: new URLSearchParams({
226
- grant_type: 'authorization_code',
227
- code: o,
228
- redirect_uri: c,
229
- client_id: i,
230
- code_verifier: a,
231
- }),
232
- })
233
- if (!u.ok) {
234
- const I = await u.json().catch(() => ({}))
235
- throw new Error(`Token exchange failed: ${I.error_description || u.statusText}`)
236
- }
237
- const T = await u.json()
238
- return (
239
- this._storeTokens(T),
240
- this.storage.remove('codeVerifier'),
241
- this.storage.remove('oauthState'),
242
- this.storage.remove('redirectUri'),
243
- window.history.replaceState({}, document.title, window.location.pathname),
244
- !0
245
- )
246
- }
247
- /** Whether the user is currently logged in (has a non-expired token). */
248
- get isLoggedIn() {
249
- return !!this.storage.get('accessToken') && !!this.storage.get('userDid')
250
- }
251
- /** The logged-in user's DID, or null. */
252
- get did() {
253
- return this.storage.get('userDid')
254
- }
255
- /**
256
- * Make an authenticated fetch request.
257
- * Automatically adds DPoP proof and Authorization header.
258
- * Auto-refreshes expired tokens.
259
- */
260
- async fetch(t, o = {}) {
261
- await this.init()
262
- const e = t.startsWith('http') ? t : `${this.server}${t}`,
263
- n = (o.method || 'GET').toUpperCase(),
264
- r = await this._getValidToken()
265
- if (!r) throw new Error('Not authenticated')
266
- const a = await w(this.namespace, n, e, r),
267
- i = {
268
- ...o.headers,
269
- Authorization: `DPoP ${r}`,
270
- DPoP: a,
271
- }
272
- return fetch(e, { ...o, method: n, headers: i })
273
- }
274
- /** Log out — clear all stored tokens and DPoP keys. */
275
- async logout() {
276
- ;(this.storage.clear(), await v(this.namespace), (this._initPromise = null))
277
- }
278
- // --- Private ---
279
- _storeTokens(t) {
280
- ;(this.storage.set('accessToken', t.access_token),
281
- t.refresh_token && this.storage.set('refreshToken', t.refresh_token),
282
- t.sub && this.storage.set('userDid', t.sub))
283
- const o = Date.now() + (t.expires_in || 3600) * 1e3
284
- this.storage.set('tokenExpiresAt', o.toString())
285
- }
286
- async _getValidToken() {
287
- const t = this.storage.get('accessToken'),
288
- o = parseInt(this.storage.get('tokenExpiresAt') || '0')
289
- if (t && Date.now() < o - _) return t
290
- const e = this.storage.get('refreshToken')
291
- if (!e) return null
292
- const n = await A(this.namespace, 'refresh')
293
- if (!n) return (await new Promise((r) => setTimeout(r, 150)), this.storage.get('accessToken'))
294
- try {
295
- const r = this.storage.get('accessToken'),
296
- a = parseInt(this.storage.get('tokenExpiresAt') || '0')
297
- if (r && Date.now() < a - _) return r
298
- const i = `${this.server}/oauth/token`,
299
- c = await w(this.namespace, 'POST', i),
300
- h = await fetch(i, {
301
- method: 'POST',
302
- headers: {
303
- 'Content-Type': 'application/x-www-form-urlencoded',
304
- DPoP: c,
305
- },
306
- body: new URLSearchParams({
307
- grant_type: 'refresh_token',
308
- refresh_token: e,
309
- client_id: this.storage.get('clientId') || this.clientId,
310
- }),
311
- })
312
- if (!h.ok) return (this.storage.clear(), null)
313
- const l = await h.json()
314
- return (this._storeTokens(l), l.access_token)
315
- } finally {
316
- O(this.namespace, 'refresh', n)
317
- }
318
- }
319
- }
320
- export { K as OAuthClient }
147
+ //#endregion
148
+ //#region ../oauth-client/src/client.js
149
+ var v = 6e4, y = class {
150
+ constructor({ server: e, clientId: t, redirectUri: n, scope: r }) {
151
+ this.server = e.replace(/\/$/, ""), this.clientId = t || window.location.origin, this.redirectUri = n || window.location.origin + window.location.pathname, this.scope = r || "atproto", this.namespace = this.clientId.replace(/[^a-z0-9]/gi, "_").slice(0, 32), this.storage = m(this.namespace), this._initPromise = null, this._refreshPromise = null;
152
+ }
153
+ async init() {
154
+ return this._initPromise ||= d(this.namespace), this._initPromise;
155
+ }
156
+ async login(e) {
157
+ await this.init();
158
+ let n = t(32), i = await r(n), a = t(16);
159
+ this.storage.set("codeVerifier", n), this.storage.set("oauthState", a), this.storage.set("clientId", this.clientId), this.storage.set("redirectUri", this.redirectUri);
160
+ let o = `${this.server}/oauth/par`, s = await p(this.namespace, "POST", o), c = new URLSearchParams({
161
+ client_id: this.clientId,
162
+ redirect_uri: this.redirectUri,
163
+ response_type: "code",
164
+ code_challenge: i,
165
+ code_challenge_method: "S256",
166
+ scope: this.scope,
167
+ state: a
168
+ });
169
+ e && c.set("login_hint", e);
170
+ let l = await fetch(o, {
171
+ method: "POST",
172
+ headers: {
173
+ "Content-Type": "application/x-www-form-urlencoded",
174
+ DPoP: s
175
+ },
176
+ body: c.toString()
177
+ });
178
+ if (!l.ok) {
179
+ let e = await l.json().catch(() => ({}));
180
+ throw Error(`PAR failed: ${e.error || l.status}`);
181
+ }
182
+ let { request_uri: u } = await l.json(), d = new URLSearchParams({
183
+ request_uri: u,
184
+ client_id: this.clientId
185
+ });
186
+ window.location.href = `${this.server}/oauth/authorize?${d}`;
187
+ }
188
+ async handleCallback() {
189
+ let e = new URLSearchParams(window.location.search), t = e.get("code"), n = e.get("state"), r = e.get("error");
190
+ if (r) throw Error(`OAuth error: ${r} - ${e.get("error_description") || ""}`);
191
+ if (!t || !n) return !1;
192
+ if (n !== this.storage.get("oauthState")) throw Error("OAuth state mismatch");
193
+ let i = this.storage.get("codeVerifier"), a = this.storage.get("clientId"), o = this.storage.get("redirectUri");
194
+ if (!i || !a || !o) throw Error("Missing OAuth session data");
195
+ await this.init();
196
+ let s = `${this.server}/oauth/token`, c = await p(this.namespace, "POST", s), l = await fetch(s, {
197
+ method: "POST",
198
+ headers: {
199
+ "Content-Type": "application/x-www-form-urlencoded",
200
+ DPoP: c
201
+ },
202
+ body: new URLSearchParams({
203
+ grant_type: "authorization_code",
204
+ code: t,
205
+ redirect_uri: o,
206
+ client_id: a,
207
+ code_verifier: i
208
+ })
209
+ });
210
+ if (!l.ok) {
211
+ let e = await l.json().catch(() => ({}));
212
+ throw Error(`Token exchange failed: ${e.error_description || l.statusText}`);
213
+ }
214
+ let u = await l.json();
215
+ return this._storeTokens(u), this.storage.remove("codeVerifier"), this.storage.remove("oauthState"), this.storage.remove("redirectUri"), window.history.replaceState({}, document.title, window.location.pathname), !0;
216
+ }
217
+ get isLoggedIn() {
218
+ return !!this.storage.get("accessToken") && !!this.storage.get("userDid");
219
+ }
220
+ get did() {
221
+ return this.storage.get("userDid");
222
+ }
223
+ get handle() {
224
+ return this.storage.get("userHandle");
225
+ }
226
+ async fetch(e, t = {}) {
227
+ await this.init();
228
+ let n = e.startsWith("http") ? e : `${this.server}${e}`, r = (t.method || "GET").toUpperCase(), i = await this._getValidToken();
229
+ if (!i) throw Error("Not authenticated");
230
+ let a = await p(this.namespace, r, n, i), o = {
231
+ ...t.headers,
232
+ Authorization: `DPoP ${i}`,
233
+ DPoP: a
234
+ }, s = await fetch(n, {
235
+ ...t,
236
+ method: r,
237
+ headers: o
238
+ });
239
+ if (s.status === 403 && (await s.clone().json().catch(() => ({}))).error === "ScopeMissingError") throw this.login(this.did), Error("Re-authenticating with updated scopes");
240
+ return s;
241
+ }
242
+ async logout() {
243
+ this.storage.clear(), await f(this.namespace), this._initPromise = null;
244
+ }
245
+ _storeTokens(e) {
246
+ this.storage.set("accessToken", e.access_token), e.refresh_token && this.storage.set("refreshToken", e.refresh_token), e.sub && this.storage.set("userDid", e.sub), e.handle && this.storage.set("userHandle", e.handle);
247
+ let t = Date.now() + (e.expires_in || 3600) * 1e3;
248
+ this.storage.set("tokenExpiresAt", t.toString());
249
+ }
250
+ async _getValidToken() {
251
+ let e = this.storage.get("accessToken"), t = parseInt(this.storage.get("tokenExpiresAt") || "0");
252
+ return e && Date.now() < t - v ? e : (this._refreshPromise ||= this._refresh().finally(() => {
253
+ this._refreshPromise = null;
254
+ }), this._refreshPromise);
255
+ }
256
+ async _refresh() {
257
+ let e = this.storage.get("refreshToken");
258
+ if (!e) return null;
259
+ let t = await g(this.namespace, "refresh");
260
+ if (!t) return await new Promise((e) => setTimeout(e, 150)), this.storage.get("accessToken");
261
+ try {
262
+ let t = this.storage.get("accessToken"), n = parseInt(this.storage.get("tokenExpiresAt") || "0");
263
+ if (t && Date.now() < n - v) return t;
264
+ let r = `${this.server}/oauth/token`, i = await p(this.namespace, "POST", r), a = await fetch(r, {
265
+ method: "POST",
266
+ headers: {
267
+ "Content-Type": "application/x-www-form-urlencoded",
268
+ DPoP: i
269
+ },
270
+ body: new URLSearchParams({
271
+ grant_type: "refresh_token",
272
+ refresh_token: e,
273
+ client_id: this.storage.get("clientId") || this.clientId
274
+ })
275
+ });
276
+ if (!a.ok) return this.storage.clear(), null;
277
+ let o = await a.json();
278
+ return this._storeTokens(o), o.access_token;
279
+ } finally {
280
+ _(this.namespace, "refresh", t);
281
+ }
282
+ }
283
+ };
284
+ //#endregion
285
+ export { y as OAuthClient };