@draftlab/auth 0.4.1 → 0.6.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 (104) hide show
  1. package/dist/adapters/{node.js → node.mjs} +2 -4
  2. package/dist/{allow.js → allow.mjs} +1 -1
  3. package/dist/{client.d.ts → client.d.mts} +47 -4
  4. package/dist/{client.js → client.mjs} +81 -10
  5. package/dist/{core.d.ts → core.d.mts} +10 -10
  6. package/dist/{core.js → core.mjs} +104 -56
  7. package/dist/index.d.mts +2 -0
  8. package/dist/index.mjs +3 -0
  9. package/dist/{keys.d.ts → keys.d.mts} +1 -1
  10. package/dist/{keys.js → keys.mjs} +6 -8
  11. package/dist/{pkce.js → pkce.mjs} +5 -10
  12. package/dist/plugin/{builder.d.ts → builder.d.mts} +1 -1
  13. package/dist/plugin/{manager.d.ts → manager.d.mts} +2 -2
  14. package/dist/plugin/{manager.js → manager.mjs} +1 -1
  15. package/dist/plugin/{plugin.d.ts → plugin.d.mts} +1 -1
  16. package/dist/plugin/{types.d.ts → types.d.mts} +1 -1
  17. package/dist/provider/apple.d.mts +105 -0
  18. package/dist/provider/apple.mjs +151 -0
  19. package/dist/provider/{code.d.ts → code.d.mts} +1 -1
  20. package/dist/provider/{code.js → code.mjs} +2 -3
  21. package/dist/provider/{discord.d.ts → discord.d.mts} +2 -2
  22. package/dist/provider/{discord.js → discord.mjs} +59 -1
  23. package/dist/provider/{facebook.d.ts → facebook.d.mts} +2 -2
  24. package/dist/provider/{facebook.js → facebook.mjs} +57 -1
  25. package/dist/provider/{github.d.ts → github.d.mts} +2 -2
  26. package/dist/provider/{github.js → github.mjs} +79 -1
  27. package/dist/provider/gitlab.d.mts +100 -0
  28. package/dist/provider/gitlab.mjs +128 -0
  29. package/dist/provider/{google.d.ts → google.d.mts} +2 -2
  30. package/dist/provider/{google.js → google.mjs} +45 -1
  31. package/dist/provider/{linkedin.d.ts → linkedin.d.mts} +2 -2
  32. package/dist/provider/{linkedin.js → linkedin.mjs} +57 -1
  33. package/dist/provider/{magiclink.d.ts → magiclink.d.mts} +1 -1
  34. package/dist/provider/{magiclink.js → magiclink.mjs} +4 -6
  35. package/dist/provider/{microsoft.d.ts → microsoft.d.mts} +2 -2
  36. package/dist/provider/{microsoft.js → microsoft.mjs} +68 -1
  37. package/dist/provider/{oauth2.d.ts → oauth2.d.mts} +1 -1
  38. package/dist/provider/{oauth2.js → oauth2.mjs} +4 -4
  39. package/dist/provider/{passkey.d.ts → passkey.d.mts} +1 -1
  40. package/dist/provider/{passkey.js → passkey.mjs} +8 -13
  41. package/dist/provider/{password.d.ts → password.d.mts} +1 -1
  42. package/dist/provider/{password.js → password.mjs} +31 -44
  43. package/dist/provider/{provider.d.ts → provider.d.mts} +1 -1
  44. package/dist/provider/reddit.d.mts +101 -0
  45. package/dist/provider/reddit.mjs +114 -0
  46. package/dist/provider/slack.d.mts +108 -0
  47. package/dist/provider/slack.mjs +125 -0
  48. package/dist/provider/spotify.d.mts +107 -0
  49. package/dist/provider/spotify.mjs +122 -0
  50. package/dist/provider/{totp.d.ts → totp.d.mts} +1 -1
  51. package/dist/provider/{totp.js → totp.mjs} +51 -14
  52. package/dist/provider/twitch.d.mts +102 -0
  53. package/dist/provider/twitch.mjs +118 -0
  54. package/dist/{random.js → random.mjs} +1 -2
  55. package/dist/revocation.d.mts +55 -0
  56. package/dist/revocation.mjs +63 -0
  57. package/dist/storage/{memory.d.ts → memory.d.mts} +1 -1
  58. package/dist/storage/{memory.js → memory.mjs} +3 -5
  59. package/dist/storage/{storage.d.ts → storage.d.mts} +27 -10
  60. package/dist/storage/storage.mjs +104 -0
  61. package/dist/storage/{turso.d.ts → turso.d.mts} +1 -1
  62. package/dist/storage/{turso.js → turso.mjs} +1 -1
  63. package/dist/storage/{unstorage.d.ts → unstorage.d.mts} +1 -1
  64. package/dist/storage/{unstorage.js → unstorage.mjs} +11 -4
  65. package/dist/{subject.d.ts → subject.d.mts} +1 -1
  66. package/dist/ui/{base.d.ts → base.d.mts} +1 -1
  67. package/dist/ui/{base.js → base.mjs} +1 -1
  68. package/dist/ui/{code.d.ts → code.d.mts} +1 -1
  69. package/dist/ui/{code.js → code.mjs} +3 -4
  70. package/dist/ui/{magiclink.d.ts → magiclink.d.mts} +1 -1
  71. package/dist/ui/{magiclink.js → magiclink.mjs} +3 -4
  72. package/dist/ui/{passkey.d.ts → passkey.d.mts} +1 -1
  73. package/dist/ui/{passkey.js → passkey.mjs} +2 -2
  74. package/dist/ui/{password.d.ts → password.d.mts} +1 -1
  75. package/dist/ui/{password.js → password.mjs} +3 -4
  76. package/dist/ui/{select.d.ts → select.d.mts} +1 -1
  77. package/dist/ui/{select.js → select.mjs} +2 -2
  78. package/dist/ui/{totp.d.ts → totp.d.mts} +1 -1
  79. package/dist/ui/{totp.js → totp.mjs} +2 -2
  80. package/dist/{util.js → util.mjs} +2 -5
  81. package/package.json +17 -16
  82. package/dist/index.d.ts +0 -2
  83. package/dist/index.js +0 -3
  84. package/dist/storage/storage.js +0 -62
  85. /package/dist/adapters/{node.d.ts → node.d.mts} +0 -0
  86. /package/dist/{allow.d.ts → allow.d.mts} +0 -0
  87. /package/dist/{error.d.ts → error.d.mts} +0 -0
  88. /package/dist/{error.js → error.mjs} +0 -0
  89. /package/dist/{pkce.d.ts → pkce.d.mts} +0 -0
  90. /package/dist/plugin/{builder.js → builder.mjs} +0 -0
  91. /package/dist/plugin/{plugin.js → plugin.mjs} +0 -0
  92. /package/dist/plugin/{types.js → types.mjs} +0 -0
  93. /package/dist/provider/{provider.js → provider.mjs} +0 -0
  94. /package/dist/{random.d.ts → random.d.mts} +0 -0
  95. /package/dist/{subject.js → subject.mjs} +0 -0
  96. /package/dist/themes/{theme.d.ts → theme.d.mts} +0 -0
  97. /package/dist/themes/{theme.js → theme.mjs} +0 -0
  98. /package/dist/{types.d.ts → types.d.mts} +0 -0
  99. /package/dist/{types.js → types.mjs} +0 -0
  100. /package/dist/ui/{form.d.ts → form.d.mts} +0 -0
  101. /package/dist/ui/{form.js → form.mjs} +0 -0
  102. /package/dist/ui/{icon.d.ts → icon.d.mts} +0 -0
  103. /package/dist/ui/{icon.js → icon.mjs} +0 -0
  104. /package/dist/{util.d.ts → util.d.mts} +0 -0
@@ -0,0 +1,101 @@
1
+ import { Provider } from "./provider.mjs";
2
+ import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
3
+
4
+ //#region src/provider/reddit.d.ts
5
+
6
+ /**
7
+ * Configuration options for Reddit OAuth 2.0 provider.
8
+ * Extends the base OAuth 2.0 configuration with Reddit-specific documentation.
9
+ */
10
+ interface RedditConfig extends Oauth2WrappedConfig {
11
+ /**
12
+ * Reddit app client ID.
13
+ * Get this from your Reddit application preferences at https://www.reddit.com/prefs/apps
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * {
18
+ * clientID: "abcdef123456"
19
+ * }
20
+ * ```
21
+ */
22
+ readonly clientID: string;
23
+ /**
24
+ * Reddit app client secret.
25
+ * Keep this secure and never expose it to client-side code.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * {
30
+ * clientSecret: process.env.REDDIT_CLIENT_SECRET
31
+ * }
32
+ * ```
33
+ */
34
+ readonly clientSecret: string;
35
+ /**
36
+ * Reddit OAuth scopes to request access for.
37
+ * Determines what data and actions your app can access.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * {
42
+ * scopes: [
43
+ * "identity", // Access user identity
44
+ * "read" // Read private data
45
+ * ]
46
+ * }
47
+ * ```
48
+ */
49
+ readonly scopes: string[];
50
+ }
51
+ /**
52
+ * Creates a Reddit OAuth 2.0 authentication provider.
53
+ * Allows users to authenticate using their Reddit accounts.
54
+ *
55
+ * @param config - Reddit OAuth 2.0 configuration
56
+ * @returns OAuth 2.0 provider configured for Reddit
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * // Basic Reddit authentication
61
+ * const basicReddit = RedditProvider({
62
+ * clientID: process.env.REDDIT_CLIENT_ID,
63
+ * clientSecret: process.env.REDDIT_CLIENT_SECRET
64
+ * })
65
+ *
66
+ * // Reddit with identity scope
67
+ * const redditWithIdentity = RedditProvider({
68
+ * clientID: process.env.REDDIT_CLIENT_ID,
69
+ * clientSecret: process.env.REDDIT_CLIENT_SECRET,
70
+ * scopes: ["identity"]
71
+ * })
72
+ *
73
+ * // Using the access token to fetch user data
74
+ * export default issuer({
75
+ * providers: { reddit: redditWithIdentity },
76
+ * success: async (ctx, value) => {
77
+ * if (value.provider === "reddit") {
78
+ * const token = value.tokenset.access
79
+ *
80
+ * const userRes = await fetch('https://oauth.reddit.com/api/v1/me', {
81
+ * headers: {
82
+ * 'Authorization': `Bearer ${token}`,
83
+ * 'User-Agent': 'YourApp/1.0'
84
+ * }
85
+ * })
86
+ * const user = await userRes.json()
87
+ *
88
+ * return ctx.subject("user", {
89
+ * redditId: user.id,
90
+ * username: user.name,
91
+ * linkKarma: user.link_karma,
92
+ * commentKarma: user.comment_karma
93
+ * })
94
+ * }
95
+ * }
96
+ * })
97
+ * ```
98
+ */
99
+ declare const RedditProvider: (config: RedditConfig) => Provider<Oauth2UserData>;
100
+ //#endregion
101
+ export { RedditConfig, RedditProvider };
@@ -0,0 +1,114 @@
1
+ import { Oauth2Provider } from "./oauth2.mjs";
2
+
3
+ //#region src/provider/reddit.ts
4
+ /**
5
+ * Reddit authentication provider for Draft Auth.
6
+ * Implements OAuth 2.0 flow for authenticating users with their Reddit accounts.
7
+ *
8
+ * ## Quick Setup
9
+ *
10
+ * ```ts
11
+ * import { RedditProvider } from "@draftlab/auth/provider/reddit"
12
+ *
13
+ * export default issuer({
14
+ * providers: {
15
+ * reddit: RedditProvider({
16
+ * clientID: process.env.REDDIT_CLIENT_ID,
17
+ * clientSecret: process.env.REDDIT_CLIENT_SECRET,
18
+ * scopes: ["identity"]
19
+ * })
20
+ * }
21
+ * })
22
+ * ```
23
+ *
24
+ * ## Common Scopes
25
+ *
26
+ * - `identity` - Access user's identity information
27
+ * - `read` - Access user's private data (saved posts, hidden posts, etc.)
28
+ * - `submit` - Submit links and posts
29
+ * - `modposts` - Moderate posts
30
+ * - `privatemessages` - Access private messages
31
+ * - `subscribe` - Subscribe to subreddits
32
+ * - `wikiread` - Read wiki pages
33
+ *
34
+ * ## User Data Access
35
+ *
36
+ * ```ts
37
+ * success: async (ctx, value) => {
38
+ * if (value.provider === "reddit") {
39
+ * const accessToken = value.tokenset.access
40
+ *
41
+ * // Fetch user information
42
+ * const userResponse = await fetch('https://oauth.reddit.com/api/v1/me', {
43
+ * headers: { Authorization: `Bearer ${accessToken}` }
44
+ * })
45
+ * const user = await userResponse.json()
46
+ *
47
+ * // User info: id, name, created_utc, link_karma, comment_karma
48
+ * }
49
+ * }
50
+ * ```
51
+ *
52
+ * @packageDocumentation
53
+ */
54
+ /**
55
+ * Creates a Reddit OAuth 2.0 authentication provider.
56
+ * Allows users to authenticate using their Reddit accounts.
57
+ *
58
+ * @param config - Reddit OAuth 2.0 configuration
59
+ * @returns OAuth 2.0 provider configured for Reddit
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * // Basic Reddit authentication
64
+ * const basicReddit = RedditProvider({
65
+ * clientID: process.env.REDDIT_CLIENT_ID,
66
+ * clientSecret: process.env.REDDIT_CLIENT_SECRET
67
+ * })
68
+ *
69
+ * // Reddit with identity scope
70
+ * const redditWithIdentity = RedditProvider({
71
+ * clientID: process.env.REDDIT_CLIENT_ID,
72
+ * clientSecret: process.env.REDDIT_CLIENT_SECRET,
73
+ * scopes: ["identity"]
74
+ * })
75
+ *
76
+ * // Using the access token to fetch user data
77
+ * export default issuer({
78
+ * providers: { reddit: redditWithIdentity },
79
+ * success: async (ctx, value) => {
80
+ * if (value.provider === "reddit") {
81
+ * const token = value.tokenset.access
82
+ *
83
+ * const userRes = await fetch('https://oauth.reddit.com/api/v1/me', {
84
+ * headers: {
85
+ * 'Authorization': `Bearer ${token}`,
86
+ * 'User-Agent': 'YourApp/1.0'
87
+ * }
88
+ * })
89
+ * const user = await userRes.json()
90
+ *
91
+ * return ctx.subject("user", {
92
+ * redditId: user.id,
93
+ * username: user.name,
94
+ * linkKarma: user.link_karma,
95
+ * commentKarma: user.comment_karma
96
+ * })
97
+ * }
98
+ * }
99
+ * })
100
+ * ```
101
+ */
102
+ const RedditProvider = (config) => {
103
+ return Oauth2Provider({
104
+ ...config,
105
+ type: "reddit",
106
+ endpoint: {
107
+ authorization: "https://www.reddit.com/api/v1/authorize",
108
+ token: "https://www.reddit.com/api/v1/access_token"
109
+ }
110
+ });
111
+ };
112
+
113
+ //#endregion
114
+ export { RedditProvider };
@@ -0,0 +1,108 @@
1
+ import { Provider } from "./provider.mjs";
2
+ import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
3
+
4
+ //#region src/provider/slack.d.ts
5
+
6
+ /**
7
+ * Configuration options for Slack OAuth 2.0 provider.
8
+ * Extends the base OAuth 2.0 configuration with Slack-specific documentation.
9
+ */
10
+ interface SlackConfig extends Oauth2WrappedConfig {
11
+ /**
12
+ * Slack app client ID.
13
+ * Get this from your Slack App settings at https://api.slack.com/apps
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * {
18
+ * clientID: "123456789.1234567890"
19
+ * }
20
+ * ```
21
+ */
22
+ readonly clientID: string;
23
+ /**
24
+ * Slack app client secret.
25
+ * Keep this secure and never expose it to client-side code.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * {
30
+ * clientSecret: process.env.SLACK_CLIENT_SECRET
31
+ * }
32
+ * ```
33
+ */
34
+ readonly clientSecret: string;
35
+ /**
36
+ * Slack OAuth scopes to request access for.
37
+ * Determines what data and actions your app can access.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * {
42
+ * scopes: [
43
+ * "users:read", // Access to user profiles
44
+ * "users:read.email", // Access user emails
45
+ * "team:read" // Access team information
46
+ * ]
47
+ * }
48
+ * ```
49
+ */
50
+ readonly scopes: string[];
51
+ }
52
+ /**
53
+ * Creates a Slack OAuth 2.0 authentication provider.
54
+ * Allows users to authenticate using their Slack accounts.
55
+ *
56
+ * @param config - Slack OAuth 2.0 configuration
57
+ * @returns OAuth 2.0 provider configured for Slack
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * // Basic Slack authentication
62
+ * const basicSlack = SlackProvider({
63
+ * clientID: process.env.SLACK_CLIENT_ID,
64
+ * clientSecret: process.env.SLACK_CLIENT_SECRET
65
+ * })
66
+ *
67
+ * // Slack with user scopes
68
+ * const slackWithScopes = SlackProvider({
69
+ * clientID: process.env.SLACK_CLIENT_ID,
70
+ * clientSecret: process.env.SLACK_CLIENT_SECRET,
71
+ * scopes: ["users:read", "users:read.email", "team:read"]
72
+ * })
73
+ *
74
+ * // Using the access token to fetch user data
75
+ * export default issuer({
76
+ * providers: { slack: slackWithScopes },
77
+ * success: async (ctx, value) => {
78
+ * if (value.provider === "slack") {
79
+ * const token = value.tokenset.access
80
+ *
81
+ * // Get basic user info
82
+ * const authRes = await fetch('https://slack.com/api/auth.test', {
83
+ * headers: { Authorization: `Bearer ${token}` }
84
+ * })
85
+ * const authInfo = await authRes.json()
86
+ *
87
+ * // Get detailed user info
88
+ * const userRes = await fetch(
89
+ * `https://slack.com/api/users.info?user=${authInfo.user_id}`,
90
+ * { headers: { Authorization: `Bearer ${token}` } }
91
+ * )
92
+ * const { user } = await userRes.json()
93
+ *
94
+ * return ctx.subject("user", {
95
+ * slackId: user.id,
96
+ * username: user.name,
97
+ * realName: user.real_name,
98
+ * email: user.profile?.email,
99
+ * workspace: authInfo.team_id
100
+ * })
101
+ * }
102
+ * }
103
+ * })
104
+ * ```
105
+ */
106
+ declare const SlackProvider: (config: SlackConfig) => Provider<Oauth2UserData>;
107
+ //#endregion
108
+ export { SlackConfig, SlackProvider };
@@ -0,0 +1,125 @@
1
+ import { Oauth2Provider } from "./oauth2.mjs";
2
+
3
+ //#region src/provider/slack.ts
4
+ /**
5
+ * Slack authentication provider for Draft Auth.
6
+ * Implements OAuth 2.0 flow for authenticating users with their Slack accounts.
7
+ *
8
+ * ## Quick Setup
9
+ *
10
+ * ```ts
11
+ * import { SlackProvider } from "@draftlab/auth/provider/slack"
12
+ *
13
+ * export default issuer({
14
+ * providers: {
15
+ * slack: SlackProvider({
16
+ * clientID: process.env.SLACK_CLIENT_ID,
17
+ * clientSecret: process.env.SLACK_CLIENT_SECRET,
18
+ * scopes: ["users:read", "users:read.email"]
19
+ * })
20
+ * }
21
+ * })
22
+ * ```
23
+ *
24
+ * ## Common Scopes
25
+ *
26
+ * - `users:read` - Access to user profiles
27
+ * - `users:read.email` - Access user email addresses
28
+ * - `team:read` - Access team information
29
+ * - `channels:read` - View channels
30
+ * - `groups:read` - View private channels
31
+ * - `im:read` - View direct messages
32
+ * - `mpim:read` - View group direct messages
33
+ *
34
+ * ## User Data Access
35
+ *
36
+ * ```ts
37
+ * success: async (ctx, value) => {
38
+ * if (value.provider === "slack") {
39
+ * const accessToken = value.tokenset.access
40
+ *
41
+ * // Fetch user information
42
+ * const userResponse = await fetch('https://slack.com/api/auth.test', {
43
+ * headers: { Authorization: `Bearer ${accessToken}` }
44
+ * })
45
+ * const userInfo = await userResponse.json()
46
+ *
47
+ * // Get user details
48
+ * const userDetailsResponse = await fetch(
49
+ * `https://slack.com/api/users.info?user=${userInfo.user_id}`,
50
+ * { headers: { Authorization: `Bearer ${accessToken}` } }
51
+ * )
52
+ * const { user } = await userDetailsResponse.json()
53
+ * }
54
+ * }
55
+ * ```
56
+ *
57
+ * @packageDocumentation
58
+ */
59
+ /**
60
+ * Creates a Slack OAuth 2.0 authentication provider.
61
+ * Allows users to authenticate using their Slack accounts.
62
+ *
63
+ * @param config - Slack OAuth 2.0 configuration
64
+ * @returns OAuth 2.0 provider configured for Slack
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * // Basic Slack authentication
69
+ * const basicSlack = SlackProvider({
70
+ * clientID: process.env.SLACK_CLIENT_ID,
71
+ * clientSecret: process.env.SLACK_CLIENT_SECRET
72
+ * })
73
+ *
74
+ * // Slack with user scopes
75
+ * const slackWithScopes = SlackProvider({
76
+ * clientID: process.env.SLACK_CLIENT_ID,
77
+ * clientSecret: process.env.SLACK_CLIENT_SECRET,
78
+ * scopes: ["users:read", "users:read.email", "team:read"]
79
+ * })
80
+ *
81
+ * // Using the access token to fetch user data
82
+ * export default issuer({
83
+ * providers: { slack: slackWithScopes },
84
+ * success: async (ctx, value) => {
85
+ * if (value.provider === "slack") {
86
+ * const token = value.tokenset.access
87
+ *
88
+ * // Get basic user info
89
+ * const authRes = await fetch('https://slack.com/api/auth.test', {
90
+ * headers: { Authorization: `Bearer ${token}` }
91
+ * })
92
+ * const authInfo = await authRes.json()
93
+ *
94
+ * // Get detailed user info
95
+ * const userRes = await fetch(
96
+ * `https://slack.com/api/users.info?user=${authInfo.user_id}`,
97
+ * { headers: { Authorization: `Bearer ${token}` } }
98
+ * )
99
+ * const { user } = await userRes.json()
100
+ *
101
+ * return ctx.subject("user", {
102
+ * slackId: user.id,
103
+ * username: user.name,
104
+ * realName: user.real_name,
105
+ * email: user.profile?.email,
106
+ * workspace: authInfo.team_id
107
+ * })
108
+ * }
109
+ * }
110
+ * })
111
+ * ```
112
+ */
113
+ const SlackProvider = (config) => {
114
+ return Oauth2Provider({
115
+ ...config,
116
+ type: "slack",
117
+ endpoint: {
118
+ authorization: "https://slack.com/oauth_authorize",
119
+ token: "https://slack.com/api/oauth.v2.access"
120
+ }
121
+ });
122
+ };
123
+
124
+ //#endregion
125
+ export { SlackProvider };
@@ -0,0 +1,107 @@
1
+ import { Provider } from "./provider.mjs";
2
+ import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
3
+
4
+ //#region src/provider/spotify.d.ts
5
+
6
+ /**
7
+ * Configuration options for Spotify OAuth 2.0 provider.
8
+ * Extends the base OAuth 2.0 configuration with Spotify-specific documentation.
9
+ */
10
+ interface SpotifyConfig extends Oauth2WrappedConfig {
11
+ /**
12
+ * Spotify app client ID.
13
+ * Get this from your Spotify App at https://developer.spotify.com/dashboard
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * {
18
+ * clientID: "abcdef123456"
19
+ * }
20
+ * ```
21
+ */
22
+ readonly clientID: string;
23
+ /**
24
+ * Spotify app client secret.
25
+ * Keep this secure and never expose it to client-side code.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * {
30
+ * clientSecret: process.env.SPOTIFY_CLIENT_SECRET
31
+ * }
32
+ * ```
33
+ */
34
+ readonly clientSecret: string;
35
+ /**
36
+ * Spotify OAuth scopes to request access for.
37
+ * Determines what data and actions your app can access.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * {
42
+ * scopes: [
43
+ * "user-read-private", // Access private user data
44
+ * "user-read-email", // Access user email
45
+ * "user-top-read" // Read top artists and tracks
46
+ * ]
47
+ * }
48
+ * ```
49
+ */
50
+ readonly scopes: string[];
51
+ }
52
+ /**
53
+ * Creates a Spotify OAuth 2.0 authentication provider.
54
+ * Allows users to authenticate using their Spotify accounts.
55
+ *
56
+ * @param config - Spotify OAuth 2.0 configuration
57
+ * @returns OAuth 2.0 provider configured for Spotify
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * // Basic Spotify authentication
62
+ * const basicSpotify = SpotifyProvider({
63
+ * clientID: process.env.SPOTIFY_CLIENT_ID,
64
+ * clientSecret: process.env.SPOTIFY_CLIENT_SECRET
65
+ * })
66
+ *
67
+ * // Spotify with user data access
68
+ * const spotifyWithScopes = SpotifyProvider({
69
+ * clientID: process.env.SPOTIFY_CLIENT_ID,
70
+ * clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
71
+ * scopes: ["user-read-private", "user-read-email", "user-top-read"]
72
+ * })
73
+ *
74
+ * // Using the access token to fetch user data
75
+ * export default issuer({
76
+ * providers: { spotify: spotifyWithScopes },
77
+ * success: async (ctx, value) => {
78
+ * if (value.provider === "spotify") {
79
+ * const token = value.tokenset.access
80
+ *
81
+ * const userRes = await fetch('https://api.spotify.com/v1/me', {
82
+ * headers: { Authorization: `Bearer ${token}` }
83
+ * })
84
+ * const user = await userRes.json()
85
+ *
86
+ * // Optionally fetch top tracks
87
+ * const topRes = await fetch('https://api.spotify.com/v1/me/top/tracks?limit=5', {
88
+ * headers: { Authorization: `Bearer ${token}` }
89
+ * })
90
+ * const { items: topTracks } = await topRes.json()
91
+ *
92
+ * return ctx.subject("user", {
93
+ * spotifyId: user.id,
94
+ * email: user.email,
95
+ * displayName: user.display_name,
96
+ * profileUrl: user.external_urls?.spotify,
97
+ * followers: user.followers?.total,
98
+ * topTracks: topTracks.map(t => t.name)
99
+ * })
100
+ * }
101
+ * }
102
+ * })
103
+ * ```
104
+ */
105
+ declare const SpotifyProvider: (config: SpotifyConfig) => Provider<Oauth2UserData>;
106
+ //#endregion
107
+ export { SpotifyConfig, SpotifyProvider };
@@ -0,0 +1,122 @@
1
+ import { Oauth2Provider } from "./oauth2.mjs";
2
+
3
+ //#region src/provider/spotify.ts
4
+ /**
5
+ * Spotify authentication provider for Draft Auth.
6
+ * Implements OAuth 2.0 flow for authenticating users with their Spotify accounts.
7
+ *
8
+ * ## Quick Setup
9
+ *
10
+ * ```ts
11
+ * import { SpotifyProvider } from "@draftlab/auth/provider/spotify"
12
+ *
13
+ * export default issuer({
14
+ * providers: {
15
+ * spotify: SpotifyProvider({
16
+ * clientID: process.env.SPOTIFY_CLIENT_ID,
17
+ * clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
18
+ * scopes: ["user-read-private", "user-read-email"]
19
+ * })
20
+ * }
21
+ * })
22
+ * ```
23
+ *
24
+ * ## Common Scopes
25
+ *
26
+ * - `user-read-private` - Access user's private data
27
+ * - `user-read-email` - Access user's email address
28
+ * - `user-top-read` - Read user's top artists and tracks
29
+ * - `user-read-playback-state` - Read current playback state
30
+ * - `user-modify-playback-state` - Modify playback state
31
+ * - `user-read-currently-playing` - Read currently playing track
32
+ * - `playlist-read-private` - Access private playlists
33
+ * - `playlist-read-public` - Access public playlists
34
+ * - `user-library-read` - Read user's library
35
+ * - `user-follow-read` - Read followed artists and users
36
+ *
37
+ * ## User Data Access
38
+ *
39
+ * ```ts
40
+ * success: async (ctx, value) => {
41
+ * if (value.provider === "spotify") {
42
+ * const accessToken = value.tokenset.access
43
+ *
44
+ * // Fetch user profile
45
+ * const userResponse = await fetch('https://api.spotify.com/v1/me', {
46
+ * headers: { Authorization: `Bearer ${accessToken}` }
47
+ * })
48
+ * const user = await userResponse.json()
49
+ *
50
+ * // User info: id, email, display_name, external_urls, images, followers
51
+ * }
52
+ * }
53
+ * ```
54
+ *
55
+ * @packageDocumentation
56
+ */
57
+ /**
58
+ * Creates a Spotify OAuth 2.0 authentication provider.
59
+ * Allows users to authenticate using their Spotify accounts.
60
+ *
61
+ * @param config - Spotify OAuth 2.0 configuration
62
+ * @returns OAuth 2.0 provider configured for Spotify
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * // Basic Spotify authentication
67
+ * const basicSpotify = SpotifyProvider({
68
+ * clientID: process.env.SPOTIFY_CLIENT_ID,
69
+ * clientSecret: process.env.SPOTIFY_CLIENT_SECRET
70
+ * })
71
+ *
72
+ * // Spotify with user data access
73
+ * const spotifyWithScopes = SpotifyProvider({
74
+ * clientID: process.env.SPOTIFY_CLIENT_ID,
75
+ * clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
76
+ * scopes: ["user-read-private", "user-read-email", "user-top-read"]
77
+ * })
78
+ *
79
+ * // Using the access token to fetch user data
80
+ * export default issuer({
81
+ * providers: { spotify: spotifyWithScopes },
82
+ * success: async (ctx, value) => {
83
+ * if (value.provider === "spotify") {
84
+ * const token = value.tokenset.access
85
+ *
86
+ * const userRes = await fetch('https://api.spotify.com/v1/me', {
87
+ * headers: { Authorization: `Bearer ${token}` }
88
+ * })
89
+ * const user = await userRes.json()
90
+ *
91
+ * // Optionally fetch top tracks
92
+ * const topRes = await fetch('https://api.spotify.com/v1/me/top/tracks?limit=5', {
93
+ * headers: { Authorization: `Bearer ${token}` }
94
+ * })
95
+ * const { items: topTracks } = await topRes.json()
96
+ *
97
+ * return ctx.subject("user", {
98
+ * spotifyId: user.id,
99
+ * email: user.email,
100
+ * displayName: user.display_name,
101
+ * profileUrl: user.external_urls?.spotify,
102
+ * followers: user.followers?.total,
103
+ * topTracks: topTracks.map(t => t.name)
104
+ * })
105
+ * }
106
+ * }
107
+ * })
108
+ * ```
109
+ */
110
+ const SpotifyProvider = (config) => {
111
+ return Oauth2Provider({
112
+ ...config,
113
+ type: "spotify",
114
+ endpoint: {
115
+ authorization: "https://accounts.spotify.com/authorize",
116
+ token: "https://accounts.spotify.com/api/token"
117
+ }
118
+ });
119
+ };
120
+
121
+ //#endregion
122
+ export { SpotifyProvider };
@@ -1,4 +1,4 @@
1
- import { Provider } from "./provider.js";
1
+ import { Provider } from "./provider.mjs";
2
2
 
3
3
  //#region src/provider/totp.d.ts
4
4