@draftlab/auth 0.15.0 → 0.16.0

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 (272) hide show
  1. package/dist/esm/allow.js +26 -0
  2. package/dist/esm/client.js +254 -0
  3. package/dist/esm/core.js +597 -0
  4. package/dist/esm/css.d.js +0 -0
  5. package/dist/esm/error.js +88 -0
  6. package/dist/esm/index.js +5 -0
  7. package/dist/esm/keys.js +126 -0
  8. package/dist/esm/mutex.js +53 -0
  9. package/dist/esm/pkce.js +87 -0
  10. package/dist/esm/provider/apple.js +15 -0
  11. package/dist/esm/provider/code.js +62 -0
  12. package/dist/esm/provider/discord.js +15 -0
  13. package/dist/esm/provider/facebook.js +15 -0
  14. package/dist/esm/provider/github.js +15 -0
  15. package/dist/esm/provider/gitlab.js +15 -0
  16. package/dist/esm/provider/google.js +16 -0
  17. package/dist/esm/provider/linkedin.js +15 -0
  18. package/dist/esm/provider/magiclink.js +83 -0
  19. package/dist/esm/provider/microsoft.js +15 -0
  20. package/dist/esm/provider/oauth2.js +130 -0
  21. package/dist/esm/provider/password.js +331 -0
  22. package/dist/esm/provider/provider.js +18 -0
  23. package/dist/esm/provider/reddit.js +15 -0
  24. package/dist/esm/provider/slack.js +15 -0
  25. package/dist/esm/provider/spotify.js +15 -0
  26. package/dist/esm/provider/twitch.js +15 -0
  27. package/dist/esm/provider/vercel.js +17 -0
  28. package/dist/esm/random.js +40 -0
  29. package/dist/esm/revocation.js +27 -0
  30. package/dist/esm/storage/memory.js +110 -0
  31. package/dist/esm/storage/storage.js +56 -0
  32. package/dist/esm/storage/turso.js +93 -0
  33. package/dist/esm/storage/unstorage.js +78 -0
  34. package/dist/esm/subject.js +7 -0
  35. package/dist/esm/themes/theme.js +115 -0
  36. package/dist/esm/toolkit/client.js +119 -0
  37. package/dist/esm/toolkit/index.js +25 -0
  38. package/dist/esm/toolkit/providers/facebook.js +11 -0
  39. package/dist/esm/toolkit/providers/github.js +11 -0
  40. package/dist/esm/toolkit/providers/google.js +11 -0
  41. package/dist/esm/toolkit/providers/strategy.js +0 -0
  42. package/dist/esm/toolkit/storage.js +81 -0
  43. package/dist/esm/toolkit/utils.js +18 -0
  44. package/dist/esm/types.js +0 -0
  45. package/dist/esm/ui/base.js +478 -0
  46. package/dist/esm/ui/code.js +186 -0
  47. package/dist/esm/ui/form.js +46 -0
  48. package/dist/esm/ui/icon.js +242 -0
  49. package/dist/esm/ui/magiclink.js +158 -0
  50. package/dist/esm/ui/password.js +435 -0
  51. package/dist/esm/ui/select.js +102 -0
  52. package/dist/esm/util.js +59 -0
  53. package/dist/{allow.d.mts → types/allow.d.ts} +9 -11
  54. package/dist/types/allow.d.ts.map +1 -0
  55. package/dist/types/client.d.ts +462 -0
  56. package/dist/types/client.d.ts.map +1 -0
  57. package/dist/types/core.d.ts +113 -0
  58. package/dist/types/core.d.ts.map +1 -0
  59. package/dist/{error.d.mts → types/error.d.ts} +95 -97
  60. package/dist/types/error.d.ts.map +1 -0
  61. package/dist/types/index.d.ts +2 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/{keys.d.mts → types/keys.d.ts} +20 -24
  64. package/dist/types/keys.d.ts.map +1 -0
  65. package/dist/types/mutex.d.ts +42 -0
  66. package/dist/types/mutex.d.ts.map +1 -0
  67. package/dist/{pkce.d.mts → types/pkce.d.ts} +10 -11
  68. package/dist/types/pkce.d.ts.map +1 -0
  69. package/dist/types/provider/apple.d.ts +197 -0
  70. package/dist/types/provider/apple.d.ts.map +1 -0
  71. package/dist/types/provider/code.d.ts +288 -0
  72. package/dist/types/provider/code.d.ts.map +1 -0
  73. package/dist/types/provider/discord.d.ts +206 -0
  74. package/dist/types/provider/discord.d.ts.map +1 -0
  75. package/dist/types/provider/facebook.d.ts +200 -0
  76. package/dist/types/provider/facebook.d.ts.map +1 -0
  77. package/dist/types/provider/github.d.ts +220 -0
  78. package/dist/types/provider/github.d.ts.map +1 -0
  79. package/dist/types/provider/gitlab.d.ts +180 -0
  80. package/dist/types/provider/gitlab.d.ts.map +1 -0
  81. package/dist/types/provider/google.d.ts +158 -0
  82. package/dist/types/provider/google.d.ts.map +1 -0
  83. package/dist/types/provider/linkedin.d.ts +190 -0
  84. package/dist/types/provider/linkedin.d.ts.map +1 -0
  85. package/dist/types/provider/magiclink.d.ts +141 -0
  86. package/dist/types/provider/magiclink.d.ts.map +1 -0
  87. package/dist/types/provider/microsoft.d.ts +247 -0
  88. package/dist/types/provider/microsoft.d.ts.map +1 -0
  89. package/dist/types/provider/oauth2.d.ts +229 -0
  90. package/dist/types/provider/oauth2.d.ts.map +1 -0
  91. package/dist/types/provider/password.d.ts +408 -0
  92. package/dist/types/provider/password.d.ts.map +1 -0
  93. package/dist/types/provider/provider.d.ts +226 -0
  94. package/dist/types/provider/provider.d.ts.map +1 -0
  95. package/dist/types/provider/reddit.d.ts +159 -0
  96. package/dist/types/provider/reddit.d.ts.map +1 -0
  97. package/dist/types/provider/slack.d.ts +171 -0
  98. package/dist/types/provider/slack.d.ts.map +1 -0
  99. package/dist/types/provider/spotify.d.ts +168 -0
  100. package/dist/types/provider/spotify.d.ts.map +1 -0
  101. package/dist/types/provider/twitch.d.ts +163 -0
  102. package/dist/types/provider/twitch.d.ts.map +1 -0
  103. package/dist/types/provider/vercel.d.ts +294 -0
  104. package/dist/types/provider/vercel.d.ts.map +1 -0
  105. package/dist/{random.d.mts → types/random.d.ts} +4 -6
  106. package/dist/types/random.d.ts.map +1 -0
  107. package/dist/types/revocation.d.ts +76 -0
  108. package/dist/types/revocation.d.ts.map +1 -0
  109. package/dist/{storage/memory.d.mts → types/storage/memory.d.ts} +17 -21
  110. package/dist/types/storage/memory.d.ts.map +1 -0
  111. package/dist/types/storage/storage.d.ts +177 -0
  112. package/dist/types/storage/storage.d.ts.map +1 -0
  113. package/dist/{storage/turso.d.mts → types/storage/turso.d.ts} +4 -8
  114. package/dist/types/storage/turso.d.ts.map +1 -0
  115. package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -11
  116. package/dist/types/storage/unstorage.d.ts.map +1 -0
  117. package/dist/types/subject.d.ts +115 -0
  118. package/dist/types/subject.d.ts.map +1 -0
  119. package/dist/types/themes/theme.d.ts +207 -0
  120. package/dist/types/themes/theme.d.ts.map +1 -0
  121. package/dist/types/toolkit/client.d.ts +235 -0
  122. package/dist/types/toolkit/client.d.ts.map +1 -0
  123. package/dist/types/toolkit/index.d.ts +45 -0
  124. package/dist/types/toolkit/index.d.ts.map +1 -0
  125. package/dist/types/toolkit/providers/facebook.d.ts +8 -0
  126. package/dist/types/toolkit/providers/facebook.d.ts.map +1 -0
  127. package/dist/types/toolkit/providers/github.d.ts +8 -0
  128. package/dist/types/toolkit/providers/github.d.ts.map +1 -0
  129. package/dist/types/toolkit/providers/google.d.ts +8 -0
  130. package/dist/types/toolkit/providers/google.d.ts.map +1 -0
  131. package/dist/types/toolkit/providers/strategy.d.ts +38 -0
  132. package/dist/types/toolkit/providers/strategy.d.ts.map +1 -0
  133. package/dist/{toolkit/storage.d.mts → types/toolkit/storage.d.ts} +37 -39
  134. package/dist/types/toolkit/storage.d.ts.map +1 -0
  135. package/dist/{toolkit/utils.d.mts → types/toolkit/utils.d.ts} +2 -4
  136. package/dist/types/toolkit/utils.d.ts.map +1 -0
  137. package/dist/types/types.d.ts +92 -0
  138. package/dist/types/types.d.ts.map +1 -0
  139. package/dist/types/ui/base.d.ts +18 -0
  140. package/dist/types/ui/base.d.ts.map +1 -0
  141. package/dist/types/ui/code.d.ts +43 -0
  142. package/dist/types/ui/code.d.ts.map +1 -0
  143. package/dist/types/ui/form.d.ts +24 -0
  144. package/dist/types/ui/form.d.ts.map +1 -0
  145. package/dist/types/ui/icon.d.ts +60 -0
  146. package/dist/types/ui/icon.d.ts.map +1 -0
  147. package/dist/types/ui/magiclink.d.ts +41 -0
  148. package/dist/types/ui/magiclink.d.ts.map +1 -0
  149. package/dist/types/ui/password.d.ts +43 -0
  150. package/dist/types/ui/password.d.ts.map +1 -0
  151. package/dist/types/ui/select.d.ts +33 -0
  152. package/dist/types/ui/select.d.ts.map +1 -0
  153. package/dist/{util.d.mts → types/util.d.ts} +11 -13
  154. package/dist/types/util.d.ts.map +1 -0
  155. package/package.json +10 -16
  156. package/dist/adapters/node.d.mts +0 -18
  157. package/dist/adapters/node.mjs +0 -69
  158. package/dist/allow.mjs +0 -63
  159. package/dist/client.d.mts +0 -456
  160. package/dist/client.mjs +0 -283
  161. package/dist/core.d.mts +0 -110
  162. package/dist/core.mjs +0 -595
  163. package/dist/error.mjs +0 -237
  164. package/dist/index.d.mts +0 -2
  165. package/dist/index.mjs +0 -3
  166. package/dist/keys.mjs +0 -146
  167. package/dist/mutex.d.mts +0 -44
  168. package/dist/mutex.mjs +0 -110
  169. package/dist/pkce.mjs +0 -157
  170. package/dist/provider/apple.d.mts +0 -111
  171. package/dist/provider/apple.mjs +0 -164
  172. package/dist/provider/code.d.mts +0 -228
  173. package/dist/provider/code.mjs +0 -246
  174. package/dist/provider/discord.d.mts +0 -146
  175. package/dist/provider/discord.mjs +0 -156
  176. package/dist/provider/facebook.d.mts +0 -142
  177. package/dist/provider/facebook.mjs +0 -150
  178. package/dist/provider/github.d.mts +0 -140
  179. package/dist/provider/github.mjs +0 -169
  180. package/dist/provider/gitlab.d.mts +0 -106
  181. package/dist/provider/gitlab.mjs +0 -147
  182. package/dist/provider/google.d.mts +0 -112
  183. package/dist/provider/google.mjs +0 -109
  184. package/dist/provider/linkedin.d.mts +0 -132
  185. package/dist/provider/linkedin.mjs +0 -142
  186. package/dist/provider/magiclink.d.mts +0 -89
  187. package/dist/provider/magiclink.mjs +0 -143
  188. package/dist/provider/microsoft.d.mts +0 -178
  189. package/dist/provider/microsoft.mjs +0 -177
  190. package/dist/provider/oauth2.d.mts +0 -176
  191. package/dist/provider/oauth2.mjs +0 -222
  192. package/dist/provider/passkey.d.mts +0 -104
  193. package/dist/provider/passkey.mjs +0 -320
  194. package/dist/provider/password.d.mts +0 -412
  195. package/dist/provider/password.mjs +0 -363
  196. package/dist/provider/provider.d.mts +0 -227
  197. package/dist/provider/provider.mjs +0 -44
  198. package/dist/provider/reddit.d.mts +0 -107
  199. package/dist/provider/reddit.mjs +0 -127
  200. package/dist/provider/slack.d.mts +0 -114
  201. package/dist/provider/slack.mjs +0 -138
  202. package/dist/provider/spotify.d.mts +0 -113
  203. package/dist/provider/spotify.mjs +0 -135
  204. package/dist/provider/totp.d.mts +0 -112
  205. package/dist/provider/totp.mjs +0 -191
  206. package/dist/provider/twitch.d.mts +0 -108
  207. package/dist/provider/twitch.mjs +0 -131
  208. package/dist/provider/vercel.d.mts +0 -177
  209. package/dist/provider/vercel.mjs +0 -230
  210. package/dist/random.mjs +0 -86
  211. package/dist/revocation.d.mts +0 -55
  212. package/dist/revocation.mjs +0 -63
  213. package/dist/router/context.d.mts +0 -21
  214. package/dist/router/context.mjs +0 -193
  215. package/dist/router/cookies.d.mts +0 -8
  216. package/dist/router/cookies.mjs +0 -13
  217. package/dist/router/index.d.mts +0 -21
  218. package/dist/router/index.mjs +0 -107
  219. package/dist/router/matcher.d.mts +0 -15
  220. package/dist/router/matcher.mjs +0 -76
  221. package/dist/router/middleware/cors.d.mts +0 -15
  222. package/dist/router/middleware/cors.mjs +0 -114
  223. package/dist/router/safe-request.d.mts +0 -52
  224. package/dist/router/safe-request.mjs +0 -160
  225. package/dist/router/types.d.mts +0 -67
  226. package/dist/router/types.mjs +0 -1
  227. package/dist/router/variables.d.mts +0 -12
  228. package/dist/router/variables.mjs +0 -20
  229. package/dist/storage/memory.mjs +0 -125
  230. package/dist/storage/storage.d.mts +0 -179
  231. package/dist/storage/storage.mjs +0 -104
  232. package/dist/storage/turso.mjs +0 -117
  233. package/dist/storage/unstorage.mjs +0 -103
  234. package/dist/subject.d.mts +0 -62
  235. package/dist/subject.mjs +0 -36
  236. package/dist/themes/theme.d.mts +0 -209
  237. package/dist/themes/theme.mjs +0 -120
  238. package/dist/toolkit/client.d.mts +0 -169
  239. package/dist/toolkit/client.mjs +0 -209
  240. package/dist/toolkit/index.d.mts +0 -9
  241. package/dist/toolkit/index.mjs +0 -9
  242. package/dist/toolkit/providers/facebook.d.mts +0 -12
  243. package/dist/toolkit/providers/facebook.mjs +0 -16
  244. package/dist/toolkit/providers/github.d.mts +0 -12
  245. package/dist/toolkit/providers/github.mjs +0 -16
  246. package/dist/toolkit/providers/google.d.mts +0 -12
  247. package/dist/toolkit/providers/google.mjs +0 -20
  248. package/dist/toolkit/providers/strategy.d.mts +0 -40
  249. package/dist/toolkit/providers/strategy.mjs +0 -1
  250. package/dist/toolkit/storage.mjs +0 -157
  251. package/dist/toolkit/utils.mjs +0 -30
  252. package/dist/types.d.mts +0 -94
  253. package/dist/types.mjs +0 -1
  254. package/dist/ui/base.d.mts +0 -30
  255. package/dist/ui/base.mjs +0 -407
  256. package/dist/ui/code.d.mts +0 -43
  257. package/dist/ui/code.mjs +0 -173
  258. package/dist/ui/form.d.mts +0 -32
  259. package/dist/ui/form.mjs +0 -49
  260. package/dist/ui/icon.d.mts +0 -58
  261. package/dist/ui/icon.mjs +0 -247
  262. package/dist/ui/magiclink.d.mts +0 -41
  263. package/dist/ui/magiclink.mjs +0 -152
  264. package/dist/ui/passkey.d.mts +0 -27
  265. package/dist/ui/passkey.mjs +0 -323
  266. package/dist/ui/password.d.mts +0 -42
  267. package/dist/ui/password.mjs +0 -402
  268. package/dist/ui/select.d.mts +0 -34
  269. package/dist/ui/select.mjs +0 -98
  270. package/dist/ui/totp.d.mts +0 -34
  271. package/dist/ui/totp.mjs +0 -270
  272. package/dist/util.mjs +0 -128
@@ -0,0 +1,93 @@
1
+ // src/storage/turso.ts
2
+ import { joinKey, splitKey } from "./storage";
3
+ var TursoStorage = (client) => {
4
+ const TABLE_NAME = "__draftauth__kv_storage";
5
+ client.execute(`
6
+ CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
7
+ key TEXT PRIMARY KEY,
8
+ value TEXT NOT NULL,
9
+ expiry INTEGER
10
+ )
11
+ `).catch(() => console.log(`Failed to create storage table: ${TABLE_NAME}`));
12
+ client.execute(`
13
+ CREATE INDEX IF NOT EXISTS idx_${TABLE_NAME}_key_prefix
14
+ ON ${TABLE_NAME} (key)
15
+ `).catch(() => console.log(`Failed to create index prefix for table: ${TABLE_NAME}`));
16
+ client.execute(`
17
+ CREATE INDEX IF NOT EXISTS idx_${TABLE_NAME}_expiry
18
+ ON ${TABLE_NAME} (expiry)
19
+ WHERE expiry IS NOT NULL
20
+ `).catch(() => console.log(`Failed to create index expiry-based for table: ${TABLE_NAME}`));
21
+ return {
22
+ async get(key) {
23
+ const joinedKey = joinKey(key);
24
+ const { rows } = await client.execute({
25
+ sql: `SELECT value, expiry FROM ${TABLE_NAME} WHERE key = ?`,
26
+ args: [joinedKey]
27
+ });
28
+ const row = rows[0];
29
+ if (!row) {
30
+ return;
31
+ }
32
+ if (row.expiry && row.expiry < Date.now()) {
33
+ await client.execute({
34
+ sql: `DELETE FROM ${TABLE_NAME} WHERE key = ?`,
35
+ args: [joinedKey]
36
+ });
37
+ return;
38
+ }
39
+ try {
40
+ return JSON.parse(row.value);
41
+ } catch {
42
+ return;
43
+ }
44
+ },
45
+ async set(key, value, expiry) {
46
+ const joinedKey = joinKey(key);
47
+ const expiryTimestamp = expiry?.getTime() ?? null;
48
+ try {
49
+ const serializedValue = JSON.stringify(value);
50
+ await client.execute({
51
+ sql: `INSERT OR REPLACE INTO ${TABLE_NAME} (key, value, expiry) VALUES (?, ?, ?)`,
52
+ args: [joinedKey, serializedValue, expiryTimestamp]
53
+ });
54
+ } catch {
55
+ throw new Error("Storage operation failed");
56
+ }
57
+ },
58
+ async remove(key) {
59
+ const joinedKey = joinKey(key);
60
+ await client.execute({
61
+ sql: `DELETE FROM ${TABLE_NAME} WHERE key = ?`,
62
+ args: [joinedKey]
63
+ });
64
+ },
65
+ async* scan(prefix) {
66
+ const joinedPrefix = joinKey(prefix);
67
+ const now = Date.now();
68
+ const { rows } = await client.execute({
69
+ sql: `
70
+ SELECT key, value, expiry
71
+ FROM ${TABLE_NAME}
72
+ WHERE key LIKE ?
73
+ AND (expiry IS NULL OR expiry >= ?)
74
+ ORDER BY key
75
+ `,
76
+ args: [`${joinedPrefix}%`, now]
77
+ });
78
+ for (const row of rows) {
79
+ try {
80
+ const parsedValue = JSON.parse(row.value);
81
+ yield [splitKey(row.key), parsedValue];
82
+ } catch {}
83
+ }
84
+ client.execute({
85
+ sql: `DELETE FROM ${TABLE_NAME} WHERE expiry IS NOT NULL AND expiry < ?`,
86
+ args: [now]
87
+ }).catch(() => {});
88
+ }
89
+ };
90
+ };
91
+ export {
92
+ TursoStorage
93
+ };
@@ -0,0 +1,78 @@
1
+ // src/storage/unstorage.ts
2
+ import { createStorage } from "unstorage";
3
+ import { joinKey, splitKey } from "./storage";
4
+ var UnStorage = ({ driver } = {}) => {
5
+ const store = createStorage({
6
+ driver
7
+ });
8
+ return {
9
+ async get(key) {
10
+ try {
11
+ const keyPath = joinKey(key);
12
+ const entry = await store.getItem(keyPath);
13
+ if (!entry) {
14
+ return;
15
+ }
16
+ if (entry.expiry && Date.now() >= entry.expiry) {
17
+ store.removeItem(keyPath).catch(() => {});
18
+ return;
19
+ }
20
+ return entry.value;
21
+ } catch (error) {
22
+ console.error("UnStorage get error:", error);
23
+ return;
24
+ }
25
+ },
26
+ async set(key, value, expiry) {
27
+ try {
28
+ const keyPath = joinKey(key);
29
+ const entry = {
30
+ value,
31
+ expiry: expiry ? expiry.getTime() : undefined
32
+ };
33
+ await store.setItem(keyPath, entry);
34
+ } catch (error) {
35
+ console.error("UnStorage set error:", error);
36
+ throw error;
37
+ }
38
+ },
39
+ async remove(key) {
40
+ try {
41
+ const keyPath = joinKey(key);
42
+ await store.removeItem(keyPath);
43
+ } catch (error) {
44
+ console.error("UnStorage remove error:", error);
45
+ }
46
+ },
47
+ async* scan(prefix) {
48
+ try {
49
+ const now = Date.now();
50
+ const prefixPath = joinKey(prefix);
51
+ let keys = await store.getKeys(prefixPath);
52
+ if (keys.length === 0) {
53
+ const allKeys = await store.getKeys();
54
+ if (allKeys.length > 0) {
55
+ keys = allKeys.filter((key) => key.startsWith(prefixPath));
56
+ }
57
+ }
58
+ for (const keyPath of keys) {
59
+ try {
60
+ const entry = await store.getItem(keyPath);
61
+ if (!entry || !entry.value)
62
+ continue;
63
+ if (entry.expiry && now >= entry.expiry) {
64
+ store.removeItem(keyPath).catch(() => {});
65
+ continue;
66
+ }
67
+ yield [splitKey(keyPath), entry.value];
68
+ } catch {}
69
+ }
70
+ } catch (error) {
71
+ console.error("UnStorage scan error:", error);
72
+ }
73
+ }
74
+ };
75
+ };
76
+ export {
77
+ UnStorage
78
+ };
@@ -0,0 +1,7 @@
1
+ // src/subject.ts
2
+ var createSubjects = (types) => {
3
+ return { ...types };
4
+ };
5
+ export {
6
+ createSubjects
7
+ };
@@ -0,0 +1,115 @@
1
+ // src/themes/theme.ts
2
+ var THEME_DRAFTAUTH = {
3
+ title: "Draft Auth",
4
+ radius: "none",
5
+ background: {
6
+ dark: "black",
7
+ light: "white"
8
+ },
9
+ primary: {
10
+ dark: "white",
11
+ light: "black"
12
+ },
13
+ font: {
14
+ family: "IBM Plex Sans, sans-serif"
15
+ },
16
+ css: `
17
+ @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@100;200;300;400;500;600;700&display=swap');
18
+ `
19
+ };
20
+ var THEME_TERMINAL = {
21
+ title: "terminal",
22
+ radius: "none",
23
+ favicon: "https://www.terminal.shop/favicon.svg",
24
+ logo: {
25
+ dark: "https://www.terminal.shop/images/logo-white.svg",
26
+ light: "https://www.terminal.shop/images/logo-black.svg"
27
+ },
28
+ primary: "#ff5e00",
29
+ background: {
30
+ dark: "rgb(0, 0, 0)",
31
+ light: "rgb(255, 255, 255)"
32
+ },
33
+ font: {
34
+ family: "Geist Mono, monospace"
35
+ },
36
+ css: `
37
+ @import url('https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100;200;300;400;500;600;700;800;900&display=swap');
38
+ `
39
+ };
40
+ var THEME_SST = {
41
+ title: "SST",
42
+ favicon: "https://sst.dev/favicon.svg",
43
+ logo: {
44
+ dark: "https://sst.dev/favicon.svg",
45
+ light: "https://sst.dev/favicon.svg"
46
+ },
47
+ background: {
48
+ dark: "#1a1a2d",
49
+ light: "rgb(255, 255, 255)"
50
+ },
51
+ primary: "#f3663f",
52
+ font: {
53
+ family: "Rubik, sans-serif"
54
+ },
55
+ css: `
56
+ @import url('https://fonts.googleapis.com/css2?family=Rubik:wght@100;200;300;400;500;600;700;800;900&display=swap');
57
+ `
58
+ };
59
+ var THEME_SUPABASE = {
60
+ title: "Supabase",
61
+ logo: {
62
+ dark: "https://supabase.com/dashboard/_next/image?url=%2Fdashboard%2Fimg%2Fsupabase-dark.svg&w=128&q=75",
63
+ light: "https://supabase.com/dashboard/_next/image?url=%2Fdashboard%2Fimg%2Fsupabase-light.svg&w=128&q=75"
64
+ },
65
+ background: {
66
+ dark: "#171717",
67
+ light: "#f8f8f8"
68
+ },
69
+ primary: {
70
+ dark: "#006239",
71
+ light: "#72e3ad"
72
+ },
73
+ font: {
74
+ family: "Varela Round, sans-serif"
75
+ },
76
+ css: `
77
+ @import url('https://fonts.googleapis.com/css2?family=Varela+Round:wght@100;200;300;400;500;600;700;800;900&display=swap');
78
+ `
79
+ };
80
+ var THEME_VERCEL = {
81
+ title: "Vercel",
82
+ logo: {
83
+ dark: "https://vercel.com/mktng/_next/static/media/vercel-logotype-dark.e8c0a742.svg",
84
+ light: "https://vercel.com/mktng/_next/static/media/vercel-logotype-light.700a8d26.svg"
85
+ },
86
+ background: {
87
+ dark: "black",
88
+ light: "white"
89
+ },
90
+ primary: {
91
+ dark: "white",
92
+ light: "black"
93
+ },
94
+ font: {
95
+ family: "Geist, sans-serif"
96
+ },
97
+ css: `
98
+ @import url('https://fonts.googleapis.com/css2?family=Geist:wght@100;200;300;400;500;600;700;800;900&display=swap');
99
+ `
100
+ };
101
+ var setTheme = (value) => {
102
+ globalThis.DRAFTAUTH_THEME = value;
103
+ };
104
+ var getTheme = () => {
105
+ return globalThis.DRAFTAUTH_THEME || THEME_DRAFTAUTH;
106
+ };
107
+ export {
108
+ setTheme,
109
+ getTheme,
110
+ THEME_VERCEL,
111
+ THEME_TERMINAL,
112
+ THEME_SUPABASE,
113
+ THEME_SST,
114
+ THEME_DRAFTAUTH
115
+ };
@@ -0,0 +1,119 @@
1
+ // src/toolkit/client.ts
2
+ import { generatePKCE } from "../pkce";
3
+ import { createSessionStorage } from "./storage";
4
+ import { generateSecureRandom } from "./utils";
5
+ var createOAuthClient = (config) => {
6
+ const storage = config.storage || (typeof sessionStorage !== "undefined" ? createSessionStorage() : null);
7
+ if (!storage) {
8
+ throw new Error("No storage adapter provided. Please provide a storage adapter for server-side environments.");
9
+ }
10
+ return {
11
+ async authorize(provider, options) {
12
+ const providerConfig = config.providers[provider];
13
+ if (!providerConfig) {
14
+ throw new Error(`Provider '${String(provider)}' not configured`);
15
+ }
16
+ const pkce = await generatePKCE();
17
+ const state = generateSecureRandom(16);
18
+ await storage.set({
19
+ state,
20
+ verifier: pkce.verifier,
21
+ provider: String(provider),
22
+ nonce: options?.nonce
23
+ });
24
+ const scopes = options?.scopes || providerConfig.scopes || providerConfig.strategy.scopes;
25
+ const params = new URLSearchParams({
26
+ client_id: providerConfig.clientId,
27
+ redirect_uri: providerConfig.redirectUri,
28
+ response_type: "code",
29
+ scope: Array.isArray(scopes) ? scopes.join(" ") : scopes,
30
+ state,
31
+ code_challenge: pkce.challenge,
32
+ code_challenge_method: pkce.method,
33
+ ...options?.params
34
+ });
35
+ const url = `${providerConfig.strategy.authorizationEndpoint}?${params.toString()}`;
36
+ return { url, state };
37
+ },
38
+ async handleCallback(callbackUrl) {
39
+ const url = new URL(callbackUrl);
40
+ const code = url.searchParams.get("code");
41
+ const state = url.searchParams.get("state");
42
+ const error = url.searchParams.get("error");
43
+ const errorDescription = url.searchParams.get("error_description");
44
+ if (error) {
45
+ throw new Error(`OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ""}`);
46
+ }
47
+ if (!code || !state) {
48
+ throw new Error("Invalid callback URL: missing code or state parameter");
49
+ }
50
+ const storedState = await storage.get();
51
+ await storage.clear();
52
+ if (!storedState) {
53
+ throw new Error("No stored PKCE state found. OAuth flow may have expired or been tampered with.");
54
+ }
55
+ if (state !== storedState.state) {
56
+ throw new Error("State mismatch. Possible CSRF attack detected.");
57
+ }
58
+ const providerConfig = config.providers[storedState.provider];
59
+ if (!providerConfig) {
60
+ throw new Error(`Provider '${storedState.provider}' from callback not configured`);
61
+ }
62
+ const tokenParams = new URLSearchParams({
63
+ grant_type: "authorization_code",
64
+ code,
65
+ redirect_uri: providerConfig.redirectUri,
66
+ client_id: providerConfig.clientId,
67
+ client_secret: providerConfig.clientSecret,
68
+ code_verifier: storedState.verifier
69
+ });
70
+ const tokenResponse = await fetch(providerConfig.strategy.tokenEndpoint, {
71
+ method: "POST",
72
+ headers: {
73
+ "Content-Type": "application/x-www-form-urlencoded",
74
+ Accept: "application/json"
75
+ },
76
+ body: tokenParams
77
+ });
78
+ if (!tokenResponse.ok) {
79
+ const errorText = await tokenResponse.text();
80
+ throw new Error(`Token exchange failed (${tokenResponse.status}): ${errorText}`);
81
+ }
82
+ const tokenData = await tokenResponse.json();
83
+ if (!tokenData.access_token) {
84
+ throw new Error("No access token in provider response");
85
+ }
86
+ return {
87
+ provider: storedState.provider,
88
+ accessToken: tokenData.access_token,
89
+ refreshToken: tokenData.refresh_token,
90
+ expiresIn: tokenData.expires_in,
91
+ tokenType: tokenData.token_type,
92
+ idToken: tokenData.id_token
93
+ };
94
+ },
95
+ async getUserInfo(provider, accessToken) {
96
+ const providerConfig = config.providers[provider];
97
+ if (!providerConfig) {
98
+ throw new Error(`Provider '${String(provider)}' not configured`);
99
+ }
100
+ if (!providerConfig.strategy.userInfoEndpoint) {
101
+ throw new Error(`Provider '${String(provider)}' does not support user info endpoint`);
102
+ }
103
+ const response = await fetch(providerConfig.strategy.userInfoEndpoint, {
104
+ headers: {
105
+ Authorization: `Bearer ${accessToken}`,
106
+ Accept: "application/json"
107
+ }
108
+ });
109
+ if (!response.ok) {
110
+ const errorText = await response.text();
111
+ throw new Error(`Failed to fetch user info (${response.status}): ${errorText}`);
112
+ }
113
+ return response.json();
114
+ }
115
+ };
116
+ };
117
+ export {
118
+ createOAuthClient
119
+ };
@@ -0,0 +1,25 @@
1
+ // src/toolkit/index.ts
2
+ import { generatePKCE } from "../pkce";
3
+ import { createOAuthClient } from "./client";
4
+ import { FacebookStrategy } from "./providers/facebook";
5
+ import { GitHubStrategy } from "./providers/github";
6
+ import { GoogleStrategy } from "./providers/google";
7
+ import {
8
+ createCookieStorage,
9
+ createLocalStorage,
10
+ createMemoryStorage,
11
+ createSessionStorage
12
+ } from "./storage";
13
+ import { generateSecureRandom } from "./utils";
14
+ export {
15
+ generateSecureRandom,
16
+ generatePKCE,
17
+ createSessionStorage,
18
+ createOAuthClient,
19
+ createMemoryStorage,
20
+ createLocalStorage,
21
+ createCookieStorage,
22
+ GoogleStrategy,
23
+ GitHubStrategy,
24
+ FacebookStrategy
25
+ };
@@ -0,0 +1,11 @@
1
+ // src/toolkit/providers/facebook.ts
2
+ var FacebookStrategy = {
3
+ name: "facebook",
4
+ authorizationEndpoint: "https://www.facebook.com/v23.0/dialog/oauth",
5
+ tokenEndpoint: "https://graph.facebook.com/v23.0/oauth/access_token",
6
+ userInfoEndpoint: "https://graph.facebook.com/me?fields=id,name,email",
7
+ scopes: ["public_profile", "email"]
8
+ };
9
+ export {
10
+ FacebookStrategy
11
+ };
@@ -0,0 +1,11 @@
1
+ // src/toolkit/providers/github.ts
2
+ var GitHubStrategy = {
3
+ name: "github",
4
+ authorizationEndpoint: "https://github.com/login/oauth/authorize",
5
+ tokenEndpoint: "https://github.com/login/oauth/access_token",
6
+ userInfoEndpoint: "https://api.github.com/user",
7
+ scopes: ["read:user", "user:email"]
8
+ };
9
+ export {
10
+ GitHubStrategy
11
+ };
@@ -0,0 +1,11 @@
1
+ // src/toolkit/providers/google.ts
2
+ var GoogleStrategy = {
3
+ name: "google",
4
+ authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
5
+ tokenEndpoint: "https://oauth2.googleapis.com/token",
6
+ userInfoEndpoint: "https://www.googleapis.com/oauth2/v3/userinfo",
7
+ scopes: ["openid", "email", "profile"]
8
+ };
9
+ export {
10
+ GoogleStrategy
11
+ };
File without changes
@@ -0,0 +1,81 @@
1
+ // src/toolkit/storage.ts
2
+ var STORAGE_KEY = "draftauth.pkce";
3
+ var createSessionStorage = () => ({
4
+ set: (data) => {
5
+ if (typeof sessionStorage === "undefined") {
6
+ throw new Error("sessionStorage is not available in this environment");
7
+ }
8
+ sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
9
+ },
10
+ get: () => {
11
+ if (typeof sessionStorage === "undefined") {
12
+ return null;
13
+ }
14
+ const data = sessionStorage.getItem(STORAGE_KEY);
15
+ return data ? JSON.parse(data) : null;
16
+ },
17
+ clear: () => {
18
+ if (typeof sessionStorage === "undefined") {
19
+ return;
20
+ }
21
+ sessionStorage.removeItem(STORAGE_KEY);
22
+ }
23
+ });
24
+ var createLocalStorage = () => ({
25
+ set: (data) => {
26
+ if (typeof localStorage === "undefined") {
27
+ throw new Error("localStorage is not available in this environment");
28
+ }
29
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
30
+ },
31
+ get: () => {
32
+ if (typeof localStorage === "undefined") {
33
+ return null;
34
+ }
35
+ const data = localStorage.getItem(STORAGE_KEY);
36
+ return data ? JSON.parse(data) : null;
37
+ },
38
+ clear: () => {
39
+ if (typeof localStorage === "undefined") {
40
+ return;
41
+ }
42
+ localStorage.removeItem(STORAGE_KEY);
43
+ }
44
+ });
45
+ var createMemoryStorage = () => {
46
+ let state = null;
47
+ return {
48
+ set: (data) => {
49
+ state = data;
50
+ },
51
+ get: () => {
52
+ return state;
53
+ },
54
+ clear: () => {
55
+ state = null;
56
+ }
57
+ };
58
+ };
59
+ var createCookieStorage = (options) => ({
60
+ set: async (data) => {
61
+ await options.setCookie(STORAGE_KEY, JSON.stringify(data), {
62
+ maxAge: 60 * 10,
63
+ httpOnly: true,
64
+ secure: false,
65
+ sameSite: "lax"
66
+ });
67
+ },
68
+ get: async () => {
69
+ const value = await options.getCookie(STORAGE_KEY);
70
+ return value ? JSON.parse(value) : null;
71
+ },
72
+ clear: async () => {
73
+ await options.deleteCookie(STORAGE_KEY);
74
+ }
75
+ });
76
+ export {
77
+ createSessionStorage,
78
+ createMemoryStorage,
79
+ createLocalStorage,
80
+ createCookieStorage
81
+ };
@@ -0,0 +1,18 @@
1
+ // src/toolkit/utils.ts
2
+ var generateSecureRandom = (length = 32) => {
3
+ if (length <= 0 || !Number.isInteger(length)) {
4
+ throw new RangeError("Length must be a positive integer");
5
+ }
6
+ const randomBytes = new Uint8Array(length);
7
+ crypto.getRandomValues(randomBytes);
8
+ let base64 = "";
9
+ if (typeof btoa !== "undefined") {
10
+ base64 = btoa(String.fromCharCode(...randomBytes));
11
+ } else {
12
+ base64 = Buffer.from(randomBytes).toString("base64");
13
+ }
14
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
15
+ };
16
+ export {
17
+ generateSecureRandom
18
+ };
File without changes