antarctic 0.2.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 (145) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +155 -0
  3. package/dist/auth.d.ts +63 -0
  4. package/dist/auth.js +191 -0
  5. package/dist/client.d.ts +16 -0
  6. package/dist/client.js +105 -0
  7. package/dist/index.d.ts +70 -0
  8. package/dist/index.js +69 -0
  9. package/dist/oauth2.d.ts +16 -0
  10. package/dist/oauth2.js +67 -0
  11. package/dist/oidc.d.ts +1 -0
  12. package/dist/oidc.js +11 -0
  13. package/dist/providers/42.d.ts +16 -0
  14. package/dist/providers/42.js +75 -0
  15. package/dist/providers/amazon-cognito.d.ts +21 -0
  16. package/dist/providers/amazon-cognito.js +76 -0
  17. package/dist/providers/anilist.d.ts +14 -0
  18. package/dist/providers/anilist.js +91 -0
  19. package/dist/providers/apple.d.ts +22 -0
  20. package/dist/providers/apple.js +106 -0
  21. package/dist/providers/atlassian.d.ts +17 -0
  22. package/dist/providers/atlassian.js +83 -0
  23. package/dist/providers/auth0.d.ts +21 -0
  24. package/dist/providers/auth0.js +80 -0
  25. package/dist/providers/authentik.d.ts +21 -0
  26. package/dist/providers/authentik.js +75 -0
  27. package/dist/providers/autodesk.d.ts +16 -0
  28. package/dist/providers/autodesk.js +60 -0
  29. package/dist/providers/battlenet.d.ts +16 -0
  30. package/dist/providers/battlenet.js +69 -0
  31. package/dist/providers/bitbucket.d.ts +15 -0
  32. package/dist/providers/bitbucket.js +79 -0
  33. package/dist/providers/box.d.ts +18 -0
  34. package/dist/providers/box.js +90 -0
  35. package/dist/providers/bungie.d.ts +17 -0
  36. package/dist/providers/bungie.js +72 -0
  37. package/dist/providers/coinbase.d.ts +18 -0
  38. package/dist/providers/coinbase.js +95 -0
  39. package/dist/providers/discord.d.ts +16 -0
  40. package/dist/providers/discord.js +68 -0
  41. package/dist/providers/donation-alerts.d.ts +17 -0
  42. package/dist/providers/donation-alerts.js +86 -0
  43. package/dist/providers/dribbble.d.ts +16 -0
  44. package/dist/providers/dribbble.js +73 -0
  45. package/dist/providers/dropbox.d.ts +16 -0
  46. package/dist/providers/dropbox.js +96 -0
  47. package/dist/providers/epicgames.d.ts +16 -0
  48. package/dist/providers/epicgames.js +60 -0
  49. package/dist/providers/etsy.d.ts +15 -0
  50. package/dist/providers/etsy.js +68 -0
  51. package/dist/providers/facebook.d.ts +16 -0
  52. package/dist/providers/facebook.js +80 -0
  53. package/dist/providers/figma.d.ts +15 -0
  54. package/dist/providers/figma.js +56 -0
  55. package/dist/providers/gitea.d.ts +19 -0
  56. package/dist/providers/gitea.js +62 -0
  57. package/dist/providers/github.d.ts +17 -0
  58. package/dist/providers/github.js +142 -0
  59. package/dist/providers/gitlab.d.ts +21 -0
  60. package/dist/providers/gitlab.js +64 -0
  61. package/dist/providers/google.d.ts +16 -0
  62. package/dist/providers/google.js +70 -0
  63. package/dist/providers/intuit.d.ts +16 -0
  64. package/dist/providers/intuit.js +66 -0
  65. package/dist/providers/kakao.d.ts +17 -0
  66. package/dist/providers/kakao.js +95 -0
  67. package/dist/providers/keycloak.d.ts +21 -0
  68. package/dist/providers/keycloak.js +74 -0
  69. package/dist/providers/kick.d.ts +18 -0
  70. package/dist/providers/kick.js +103 -0
  71. package/dist/providers/lichess.d.ts +14 -0
  72. package/dist/providers/lichess.js +63 -0
  73. package/dist/providers/line.d.ts +17 -0
  74. package/dist/providers/line.js +98 -0
  75. package/dist/providers/linear.d.ts +16 -0
  76. package/dist/providers/linear.js +112 -0
  77. package/dist/providers/linkedin.d.ts +17 -0
  78. package/dist/providers/linkedin.js +89 -0
  79. package/dist/providers/mastodon.d.ts +20 -0
  80. package/dist/providers/mastodon.js +67 -0
  81. package/dist/providers/mercadolibre.d.ts +17 -0
  82. package/dist/providers/mercadolibre.js +95 -0
  83. package/dist/providers/mercadopago.d.ts +17 -0
  84. package/dist/providers/mercadopago.js +95 -0
  85. package/dist/providers/microsoft-entra-id.d.ts +20 -0
  86. package/dist/providers/microsoft-entra-id.js +120 -0
  87. package/dist/providers/myanimelist.d.ts +15 -0
  88. package/dist/providers/myanimelist.js +56 -0
  89. package/dist/providers/naver.d.ts +17 -0
  90. package/dist/providers/naver.js +83 -0
  91. package/dist/providers/notion.d.ts +14 -0
  92. package/dist/providers/notion.js +65 -0
  93. package/dist/providers/okta.d.ts +22 -0
  94. package/dist/providers/okta.js +85 -0
  95. package/dist/providers/osu.d.ts +17 -0
  96. package/dist/providers/osu.js +82 -0
  97. package/dist/providers/patreon.d.ts +17 -0
  98. package/dist/providers/patreon.js +89 -0
  99. package/dist/providers/polar.d.ts +18 -0
  100. package/dist/providers/polar.js +100 -0
  101. package/dist/providers/reddit.d.ts +15 -0
  102. package/dist/providers/reddit.js +55 -0
  103. package/dist/providers/roblox.d.ts +16 -0
  104. package/dist/providers/roblox.js +67 -0
  105. package/dist/providers/salesforce.d.ts +21 -0
  106. package/dist/providers/salesforce.js +74 -0
  107. package/dist/providers/shikimori.d.ts +17 -0
  108. package/dist/providers/shikimori.js +81 -0
  109. package/dist/providers/slack.d.ts +14 -0
  110. package/dist/providers/slack.js +59 -0
  111. package/dist/providers/spotify.d.ts +15 -0
  112. package/dist/providers/spotify.js +67 -0
  113. package/dist/providers/startgg.d.ts +17 -0
  114. package/dist/providers/startgg.js +143 -0
  115. package/dist/providers/strava.d.ts +17 -0
  116. package/dist/providers/strava.js +85 -0
  117. package/dist/providers/synology.d.ts +9 -0
  118. package/dist/providers/synology.js +20 -0
  119. package/dist/providers/tiktok.d.ts +18 -0
  120. package/dist/providers/tiktok.js +109 -0
  121. package/dist/providers/tiltify.d.ts +17 -0
  122. package/dist/providers/tiltify.js +90 -0
  123. package/dist/providers/tumblr.d.ts +15 -0
  124. package/dist/providers/tumblr.js +63 -0
  125. package/dist/providers/twitch.d.ts +17 -0
  126. package/dist/providers/twitch.js +91 -0
  127. package/dist/providers/twitter.d.ts +16 -0
  128. package/dist/providers/twitter.js +67 -0
  129. package/dist/providers/vk.d.ts +16 -0
  130. package/dist/providers/vk.js +82 -0
  131. package/dist/providers/withings.d.ts +16 -0
  132. package/dist/providers/withings.js +120 -0
  133. package/dist/providers/workos.d.ts +16 -0
  134. package/dist/providers/workos.js +82 -0
  135. package/dist/providers/yahoo.d.ts +15 -0
  136. package/dist/providers/yahoo.js +65 -0
  137. package/dist/providers/yandex.d.ts +15 -0
  138. package/dist/providers/yandex.js +66 -0
  139. package/dist/providers/zoom.d.ts +16 -0
  140. package/dist/providers/zoom.js +66 -0
  141. package/dist/request.d.ts +26 -0
  142. package/dist/request.js +182 -0
  143. package/dist/utils.d.ts +2 -0
  144. package/dist/utils.js +20 -0
  145. package/package.json +42 -0
@@ -0,0 +1,98 @@
1
+ import { createS256CodeChallenge } from "../oauth2.js";
2
+ import { createOAuth2Request, sendTokenRequest } from "../request.js";
3
+ import { decodeIdToken } from "../oidc.js";
4
+ import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
5
+ const authorizationEndpoint = "https://access.line.me/oauth2/v2.1/authorize";
6
+ const tokenEndpoint = "https://api.line.me/oauth2/v2.1/token";
7
+ const userinfoEndpoint = "https://api.line.me/oauth2/v2.1/userinfo";
8
+ const envPrefix = "LINE";
9
+ const defaultScopes = ["openid", "profile", "email"];
10
+ export class Line {
11
+ clientId;
12
+ clientSecret;
13
+ redirectURI;
14
+ auth = null;
15
+ constructor(clientIdOrOptions, clientSecret, redirectURI) {
16
+ if (typeof clientIdOrOptions === "object") {
17
+ this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
18
+ clientSecret: true,
19
+ redirectURI: true
20
+ });
21
+ this.clientId = this.auth.clientId;
22
+ this.clientSecret = this.auth.clientSecret ?? "";
23
+ this.redirectURI = this.auth.redirectURI ?? "";
24
+ }
25
+ else {
26
+ this.clientId = clientIdOrOptions;
27
+ this.clientSecret = clientSecret ?? "";
28
+ this.redirectURI = redirectURI ?? "";
29
+ }
30
+ }
31
+ createAuthorizationURL(state, codeVerifier, scopes) {
32
+ const url = new URL(authorizationEndpoint);
33
+ url.searchParams.set("response_type", "code");
34
+ url.searchParams.set("client_id", this.clientId);
35
+ url.searchParams.set("state", state);
36
+ if (scopes.length > 0) {
37
+ url.searchParams.set("scope", scopes.join(" "));
38
+ }
39
+ url.searchParams.set("redirect_uri", this.redirectURI);
40
+ const codeChallenge = createS256CodeChallenge(codeVerifier);
41
+ url.searchParams.set("code_challenge_method", "S256");
42
+ url.searchParams.set("code_challenge", codeChallenge);
43
+ return url;
44
+ }
45
+ async validateAuthorizationCode(code, codeVerifier) {
46
+ const body = new URLSearchParams();
47
+ body.set("grant_type", "authorization_code");
48
+ body.set("code", code);
49
+ body.set("code_verifier", codeVerifier);
50
+ body.set("redirect_uri", this.redirectURI);
51
+ body.set("client_id", this.clientId);
52
+ body.set("client_secret", this.clientSecret);
53
+ const request = createOAuth2Request(tokenEndpoint, body);
54
+ const tokens = await sendTokenRequest(request);
55
+ return tokens;
56
+ }
57
+ async refreshAccessToken(refreshToken) {
58
+ const body = new URLSearchParams();
59
+ body.set("grant_type", "refresh_token");
60
+ body.set("refresh_token", refreshToken);
61
+ body.set("client_id", this.clientId);
62
+ body.set("client_secret", this.clientSecret);
63
+ const request = createOAuth2Request(tokenEndpoint, body);
64
+ const tokens = await sendTokenRequest(request);
65
+ return tokens;
66
+ }
67
+ async getAuthorizationURL(scopes) {
68
+ const auth = requireAuthConfig(this.auth);
69
+ const state = generateOAuthState();
70
+ const codeVerifier = generateOAuthCodeVerifier();
71
+ const url = this.createAuthorizationURL(state, codeVerifier, resolveScopes(scopes, auth, defaultScopes));
72
+ await saveOAuthState(auth.store, state, { codeVerifier });
73
+ return url;
74
+ }
75
+ async getUser(query) {
76
+ const auth = requireAuthConfig(this.auth);
77
+ const { code, state } = parseCallbackQuery(query);
78
+ const stored = await consumeOAuthState(auth.store, state);
79
+ if (typeof stored.codeVerifier !== "string") {
80
+ throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
81
+ }
82
+ const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
83
+ let claims;
84
+ if ("id_token" in tokens.data) {
85
+ claims = decodeIdToken(tokens.idToken());
86
+ }
87
+ else {
88
+ // The userinfo endpoint never includes email; only the id_token does.
89
+ claims = await fetchUserProfile(userinfoEndpoint, tokens.accessToken());
90
+ }
91
+ return {
92
+ id: profileId(claims.sub),
93
+ name: profileString(claims.name),
94
+ email: profileString(claims.email),
95
+ image: profileString(claims.picture)
96
+ };
97
+ }
98
+ }
@@ -0,0 +1,16 @@
1
+ import type { OAuth2Tokens } from "../oauth2.js";
2
+ import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
3
+ export interface LinearOptions extends ProviderOptions {
4
+ }
5
+ export declare class Linear {
6
+ private clientId;
7
+ private clientSecret;
8
+ private redirectURI;
9
+ private auth;
10
+ constructor(options: LinearOptions);
11
+ constructor(clientId: string, clientSecret: string, redirectURI: string);
12
+ createAuthorizationURL(state: string, scopes: string[]): URL;
13
+ validateAuthorizationCode(code: string): Promise<OAuth2Tokens>;
14
+ getAuthorizationURL(scopes?: string[]): Promise<URL>;
15
+ getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
16
+ }
@@ -0,0 +1,112 @@
1
+ import { createOAuth2Request, sendTokenRequest } from "../request.js";
2
+ import { consumeOAuthState, generateOAuthState, OAuthProviderError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
3
+ const authorizationEndpoint = "https://linear.app/oauth/authorize";
4
+ const tokenEndpoint = "https://api.linear.app/oauth/token";
5
+ const graphqlEndpoint = "https://api.linear.app/graphql";
6
+ const envPrefix = "LINEAR";
7
+ const defaultScopes = ["read"];
8
+ export class Linear {
9
+ clientId;
10
+ clientSecret;
11
+ redirectURI;
12
+ auth = null;
13
+ constructor(clientIdOrOptions, clientSecret, redirectURI) {
14
+ if (typeof clientIdOrOptions === "object") {
15
+ this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
16
+ clientSecret: true,
17
+ redirectURI: true
18
+ });
19
+ this.clientId = this.auth.clientId;
20
+ this.clientSecret = this.auth.clientSecret ?? "";
21
+ this.redirectURI = this.auth.redirectURI ?? "";
22
+ }
23
+ else {
24
+ this.clientId = clientIdOrOptions;
25
+ this.clientSecret = clientSecret ?? "";
26
+ this.redirectURI = redirectURI ?? "";
27
+ }
28
+ }
29
+ createAuthorizationURL(state, scopes) {
30
+ const url = new URL(authorizationEndpoint);
31
+ url.searchParams.set("response_type", "code");
32
+ url.searchParams.set("client_id", this.clientId);
33
+ url.searchParams.set("state", state);
34
+ if (scopes.length > 0) {
35
+ url.searchParams.set("scope", scopes.join(" "));
36
+ }
37
+ url.searchParams.set("redirect_uri", this.redirectURI);
38
+ return url;
39
+ }
40
+ async validateAuthorizationCode(code) {
41
+ const body = new URLSearchParams();
42
+ body.set("grant_type", "authorization_code");
43
+ body.set("code", code);
44
+ body.set("redirect_uri", this.redirectURI);
45
+ body.set("client_id", this.clientId);
46
+ body.set("client_secret", this.clientSecret);
47
+ const request = createOAuth2Request(tokenEndpoint, body);
48
+ const tokens = await sendTokenRequest(request);
49
+ return tokens;
50
+ }
51
+ async getAuthorizationURL(scopes) {
52
+ const auth = requireAuthConfig(this.auth);
53
+ const state = generateOAuthState();
54
+ const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
55
+ await saveOAuthState(auth.store, state, {});
56
+ return url;
57
+ }
58
+ async getUser(query) {
59
+ const auth = requireAuthConfig(this.auth);
60
+ const { code, state } = parseCallbackQuery(query);
61
+ await consumeOAuthState(auth.store, state);
62
+ const tokens = await this.validateAuthorizationCode(code);
63
+ const viewer = await fetchViewer(tokens.accessToken());
64
+ return {
65
+ id: profileId(viewer.id),
66
+ name: profileString(viewer.name),
67
+ email: profileString(viewer.email),
68
+ image: profileString(viewer.avatarUrl)
69
+ };
70
+ }
71
+ }
72
+ async function fetchViewer(accessToken) {
73
+ let response;
74
+ try {
75
+ response = await fetch(graphqlEndpoint, {
76
+ method: "POST",
77
+ headers: {
78
+ Authorization: `Bearer ${accessToken}`,
79
+ "Content-Type": "application/json"
80
+ },
81
+ body: JSON.stringify({ query: "{ viewer { id name email avatarUrl } }" })
82
+ });
83
+ }
84
+ catch {
85
+ throw new OAuthProviderError("Failed to fetch user profile");
86
+ }
87
+ if (!response.ok) {
88
+ if (response.body !== null) {
89
+ await response.body.cancel();
90
+ }
91
+ throw new OAuthProviderError(`User profile request failed with status ${response.status}`);
92
+ }
93
+ let body;
94
+ try {
95
+ body = await response.json();
96
+ }
97
+ catch {
98
+ throw new OAuthProviderError("User profile response was not valid JSON");
99
+ }
100
+ if (typeof body !== "object" || body === null) {
101
+ throw new OAuthProviderError("Unexpected user profile response body");
102
+ }
103
+ const data = body.data;
104
+ if (typeof data !== "object" || data === null) {
105
+ throw new OAuthProviderError("Unexpected user profile response body");
106
+ }
107
+ const viewer = data.viewer;
108
+ if (typeof viewer !== "object" || viewer === null) {
109
+ throw new OAuthProviderError("Unexpected user profile response body");
110
+ }
111
+ return viewer;
112
+ }
@@ -0,0 +1,17 @@
1
+ import type { OAuth2Tokens } from "../oauth2.js";
2
+ import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
3
+ export interface LinkedInOptions extends ProviderOptions {
4
+ }
5
+ export declare class LinkedIn {
6
+ private clientId;
7
+ private clientSecret;
8
+ private redirectURI;
9
+ private auth;
10
+ constructor(options: LinkedInOptions);
11
+ constructor(clientId: string, clientSecret: string, redirectURI: string);
12
+ createAuthorizationURL(state: string, scopes: string[]): URL;
13
+ validateAuthorizationCode(code: string): Promise<OAuth2Tokens>;
14
+ refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
15
+ getAuthorizationURL(scopes?: string[]): Promise<URL>;
16
+ getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
17
+ }
@@ -0,0 +1,89 @@
1
+ // LinkedIn doesn't seem to support HTTP Basic Auth
2
+ import { createOAuth2Request, sendTokenRequest } from "../request.js";
3
+ import { decodeIdToken } from "../oidc.js";
4
+ import { consumeOAuthState, fetchUserProfile, generateOAuthState, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
5
+ const authorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization";
6
+ const tokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
7
+ const userinfoEndpoint = "https://api.linkedin.com/v2/userinfo";
8
+ const envPrefix = "LINKEDIN";
9
+ const defaultScopes = ["openid", "profile", "email"];
10
+ export class LinkedIn {
11
+ clientId;
12
+ clientSecret;
13
+ redirectURI;
14
+ auth = null;
15
+ constructor(clientIdOrOptions, clientSecret, redirectURI) {
16
+ if (typeof clientIdOrOptions === "object") {
17
+ this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
18
+ clientSecret: true,
19
+ redirectURI: true
20
+ });
21
+ this.clientId = this.auth.clientId;
22
+ this.clientSecret = this.auth.clientSecret ?? "";
23
+ this.redirectURI = this.auth.redirectURI ?? "";
24
+ }
25
+ else {
26
+ this.clientId = clientIdOrOptions;
27
+ this.clientSecret = clientSecret ?? "";
28
+ this.redirectURI = redirectURI ?? "";
29
+ }
30
+ }
31
+ createAuthorizationURL(state, scopes) {
32
+ const url = new URL(authorizationEndpoint);
33
+ url.searchParams.set("response_type", "code");
34
+ url.searchParams.set("client_id", this.clientId);
35
+ url.searchParams.set("state", state);
36
+ if (scopes.length > 0) {
37
+ url.searchParams.set("scope", scopes.join(" "));
38
+ }
39
+ url.searchParams.set("redirect_uri", this.redirectURI);
40
+ return url;
41
+ }
42
+ async validateAuthorizationCode(code) {
43
+ const body = new URLSearchParams();
44
+ body.set("grant_type", "authorization_code");
45
+ body.set("code", code);
46
+ body.set("redirect_uri", this.redirectURI);
47
+ body.set("client_id", this.clientId);
48
+ body.set("client_secret", this.clientSecret);
49
+ const request = createOAuth2Request(tokenEndpoint, body);
50
+ const tokens = await sendTokenRequest(request);
51
+ return tokens;
52
+ }
53
+ async refreshAccessToken(refreshToken) {
54
+ const body = new URLSearchParams();
55
+ body.set("grant_type", "refresh_token");
56
+ body.set("refresh_token", refreshToken);
57
+ body.set("client_id", this.clientId);
58
+ body.set("client_secret", this.clientSecret);
59
+ const request = createOAuth2Request(tokenEndpoint, body);
60
+ const tokens = await sendTokenRequest(request);
61
+ return tokens;
62
+ }
63
+ async getAuthorizationURL(scopes) {
64
+ const auth = requireAuthConfig(this.auth);
65
+ const state = generateOAuthState();
66
+ const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
67
+ await saveOAuthState(auth.store, state, {});
68
+ return url;
69
+ }
70
+ async getUser(query) {
71
+ const auth = requireAuthConfig(this.auth);
72
+ const { code, state } = parseCallbackQuery(query);
73
+ await consumeOAuthState(auth.store, state);
74
+ const tokens = await this.validateAuthorizationCode(code);
75
+ let claims;
76
+ if ("id_token" in tokens.data) {
77
+ claims = decodeIdToken(tokens.idToken());
78
+ }
79
+ else {
80
+ claims = await fetchUserProfile(userinfoEndpoint, tokens.accessToken());
81
+ }
82
+ return {
83
+ id: profileId(claims.sub),
84
+ name: profileString(claims.name),
85
+ email: profileString(claims.email),
86
+ image: profileString(claims.picture)
87
+ };
88
+ }
89
+ }
@@ -0,0 +1,20 @@
1
+ import type { OAuth2Tokens } from "../oauth2.js";
2
+ import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
3
+ export interface MastodonOptions extends ProviderOptions {
4
+ baseURL?: string;
5
+ }
6
+ export declare class Mastodon {
7
+ private authorizationEndpoint;
8
+ private tokenEndpoint;
9
+ private tokenRevocationEndpoint;
10
+ private userEndpoint;
11
+ private client;
12
+ private auth;
13
+ constructor(options: MastodonOptions);
14
+ constructor(baseURL: string, clientId: string, clientSecret: string, redirectURI: string);
15
+ createAuthorizationURL(state: string, codeVerifier: string, scopes: string[]): URL;
16
+ validateAuthorizationCode(code: string, codeVerifier: string): Promise<OAuth2Tokens>;
17
+ revokeToken(token: string): Promise<void>;
18
+ getAuthorizationURL(scopes?: string[]): Promise<URL>;
19
+ getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
20
+ }
@@ -0,0 +1,67 @@
1
+ import { OAuth2Client, CodeChallengeMethod } from "../client.js";
2
+ import { joinURIAndPath } from "../request.js";
3
+ import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, requireProviderOption, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
4
+ const envPrefix = "MASTODON";
5
+ const defaultScopes = ["read:accounts"];
6
+ export class Mastodon {
7
+ authorizationEndpoint;
8
+ tokenEndpoint;
9
+ tokenRevocationEndpoint;
10
+ userEndpoint;
11
+ client;
12
+ auth = null;
13
+ constructor(baseURLOrOptions, clientId, clientSecret, redirectURI) {
14
+ let baseURL;
15
+ if (typeof baseURLOrOptions === "object") {
16
+ this.auth = resolveAuthConfig(envPrefix, baseURLOrOptions, {
17
+ clientSecret: true,
18
+ redirectURI: true
19
+ });
20
+ baseURL = requireProviderOption(baseURLOrOptions.baseURL, envPrefix, "BASE_URL", "baseURL");
21
+ this.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
22
+ }
23
+ else {
24
+ baseURL = baseURLOrOptions;
25
+ this.client = new OAuth2Client(clientId ?? "", clientSecret ?? null, redirectURI ?? null);
26
+ }
27
+ this.authorizationEndpoint = joinURIAndPath(baseURL, "/api/v1/oauth/authorize");
28
+ this.tokenEndpoint = joinURIAndPath(baseURL, "/api/v1/oauth/token");
29
+ this.tokenRevocationEndpoint = joinURIAndPath(baseURL, "/api/v1/oauth/revoke");
30
+ this.userEndpoint = joinURIAndPath(baseURL, "/api/v1/accounts/verify_credentials");
31
+ }
32
+ createAuthorizationURL(state, codeVerifier, scopes) {
33
+ const url = this.client.createAuthorizationURLWithPKCE(this.authorizationEndpoint, state, CodeChallengeMethod.S256, codeVerifier, scopes);
34
+ return url;
35
+ }
36
+ async validateAuthorizationCode(code, codeVerifier) {
37
+ const tokens = await this.client.validateAuthorizationCode(this.tokenEndpoint, code, codeVerifier);
38
+ return tokens;
39
+ }
40
+ async revokeToken(token) {
41
+ await this.client.revokeToken(this.tokenRevocationEndpoint, token);
42
+ }
43
+ async getAuthorizationURL(scopes) {
44
+ const auth = requireAuthConfig(this.auth);
45
+ const state = generateOAuthState();
46
+ const codeVerifier = generateOAuthCodeVerifier();
47
+ const url = this.createAuthorizationURL(state, codeVerifier, resolveScopes(scopes, auth, defaultScopes));
48
+ await saveOAuthState(auth.store, state, { codeVerifier });
49
+ return url;
50
+ }
51
+ async getUser(query) {
52
+ const auth = requireAuthConfig(this.auth);
53
+ const { code, state } = parseCallbackQuery(query);
54
+ const stored = await consumeOAuthState(auth.store, state);
55
+ if (typeof stored.codeVerifier !== "string") {
56
+ throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
57
+ }
58
+ const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
59
+ const profile = await fetchUserProfile(this.userEndpoint, tokens.accessToken());
60
+ return {
61
+ id: profileId(profile.id),
62
+ name: profileString(profile.display_name) ?? profileString(profile.username),
63
+ email: null,
64
+ image: profileString(profile.avatar)
65
+ };
66
+ }
67
+ }
@@ -0,0 +1,17 @@
1
+ import type { OAuth2Tokens } from "../oauth2.js";
2
+ import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
3
+ export interface MercadoLibreOptions extends ProviderOptions {
4
+ }
5
+ export declare class MercadoLibre {
6
+ clientId: string;
7
+ private clientSecret;
8
+ private redirectURI;
9
+ private auth;
10
+ constructor(options: MercadoLibreOptions);
11
+ constructor(clientId: string, clientSecret: string, redirectURI: string);
12
+ createAuthorizationURL(state: string, codeVerifier: string): URL;
13
+ validateAuthorizationCode(code: string, codeVerifier: string): Promise<OAuth2Tokens>;
14
+ refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
15
+ getAuthorizationURL(_scopes?: string[]): Promise<URL>;
16
+ getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
17
+ }
@@ -0,0 +1,95 @@
1
+ import { createS256CodeChallenge } from "../oauth2.js";
2
+ import { createOAuth2Request, sendTokenRequest } from "../request.js";
3
+ import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, saveOAuthState } from "../auth.js";
4
+ const authorizationEndpoint = "https://auth.mercadolibre.com/authorization";
5
+ const tokenEndpoint = "https://api.mercadolibre.com/oauth/token";
6
+ const userEndpoint = "https://api.mercadolibre.com/users/me";
7
+ const envPrefix = "MERCADO_LIBRE";
8
+ export class MercadoLibre {
9
+ clientId;
10
+ clientSecret;
11
+ redirectURI;
12
+ auth = null;
13
+ constructor(clientIdOrOptions, clientSecret, redirectURI) {
14
+ if (typeof clientIdOrOptions === "object") {
15
+ this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
16
+ clientSecret: true,
17
+ redirectURI: true
18
+ });
19
+ this.clientId = this.auth.clientId;
20
+ this.clientSecret = this.auth.clientSecret ?? "";
21
+ this.redirectURI = this.auth.redirectURI ?? "";
22
+ }
23
+ else {
24
+ this.clientId = clientIdOrOptions;
25
+ this.clientSecret = clientSecret ?? "";
26
+ this.redirectURI = redirectURI ?? "";
27
+ }
28
+ }
29
+ // `scopes` not required since they are defined in the application settings
30
+ createAuthorizationURL(state, codeVerifier) {
31
+ const url = new URL(authorizationEndpoint);
32
+ url.searchParams.set("response_type", "code");
33
+ url.searchParams.set("client_id", this.clientId);
34
+ url.searchParams.set("redirect_uri", this.redirectURI);
35
+ url.searchParams.set("state", state);
36
+ const codeChallenge = createS256CodeChallenge(codeVerifier);
37
+ url.searchParams.set("code_challenge_method", "S256");
38
+ url.searchParams.set("code_challenge", codeChallenge);
39
+ return url;
40
+ }
41
+ async validateAuthorizationCode(code, codeVerifier) {
42
+ const body = new URLSearchParams();
43
+ body.set("grant_type", "authorization_code");
44
+ body.set("code", code);
45
+ body.set("redirect_uri", this.redirectURI);
46
+ body.set("code_verifier", codeVerifier);
47
+ body.set("client_id", this.clientId);
48
+ body.set("client_secret", this.clientSecret);
49
+ const request = createOAuth2Request(tokenEndpoint, body);
50
+ const tokens = await sendTokenRequest(request);
51
+ return tokens;
52
+ }
53
+ async refreshAccessToken(refreshToken) {
54
+ const body = new URLSearchParams();
55
+ body.set("grant_type", "refresh_token");
56
+ body.set("refresh_token", refreshToken);
57
+ body.set("client_id", this.clientId);
58
+ body.set("client_secret", this.clientSecret);
59
+ const request = createOAuth2Request(tokenEndpoint, body);
60
+ const tokens = await sendTokenRequest(request);
61
+ return tokens;
62
+ }
63
+ // Scopes are defined in the application settings, so the argument is ignored.
64
+ async getAuthorizationURL(_scopes) {
65
+ const auth = requireAuthConfig(this.auth);
66
+ const state = generateOAuthState();
67
+ const codeVerifier = generateOAuthCodeVerifier();
68
+ const url = this.createAuthorizationURL(state, codeVerifier);
69
+ await saveOAuthState(auth.store, state, { codeVerifier });
70
+ return url;
71
+ }
72
+ async getUser(query) {
73
+ const auth = requireAuthConfig(this.auth);
74
+ const { code, state } = parseCallbackQuery(query);
75
+ const stored = await consumeOAuthState(auth.store, state);
76
+ if (typeof stored.codeVerifier !== "string") {
77
+ throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
78
+ }
79
+ const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
80
+ const profile = await fetchUserProfile(userEndpoint, tokens.accessToken());
81
+ const firstName = profileString(profile.first_name);
82
+ const lastName = profileString(profile.last_name);
83
+ const fullName = [firstName, lastName].filter((part) => part !== null).join(" ");
84
+ let image = null;
85
+ if (typeof profile.thumbnail === "object" && profile.thumbnail !== null) {
86
+ image = profileString(profile.thumbnail.picture_url);
87
+ }
88
+ return {
89
+ id: profileId(profile.id),
90
+ name: fullName !== "" ? fullName : profileString(profile.nickname),
91
+ email: profileString(profile.email),
92
+ image
93
+ };
94
+ }
95
+ }
@@ -0,0 +1,17 @@
1
+ import type { OAuth2Tokens } from "../oauth2.js";
2
+ import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
3
+ export interface MercadoPagoOptions extends ProviderOptions {
4
+ }
5
+ export declare class MercadoPago {
6
+ clientId: string;
7
+ private clientSecret;
8
+ private redirectURI;
9
+ private auth;
10
+ constructor(options: MercadoPagoOptions);
11
+ constructor(clientId: string, clientSecret: string, redirectURI: string);
12
+ createAuthorizationURL(state: string, codeVerifier: string): URL;
13
+ validateAuthorizationCode(code: string, codeVerifier: string): Promise<OAuth2Tokens>;
14
+ refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
15
+ getAuthorizationURL(_scopes?: string[]): Promise<URL>;
16
+ getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
17
+ }
@@ -0,0 +1,95 @@
1
+ import { createS256CodeChallenge } from "../oauth2.js";
2
+ import { createOAuth2Request, sendTokenRequest } from "../request.js";
3
+ import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, saveOAuthState } from "../auth.js";
4
+ const authorizationEndpoint = "https://auth.mercadopago.com/authorization";
5
+ const tokenEndpoint = "https://api.mercadopago.com/oauth/token";
6
+ const userEndpoint = "https://api.mercadopago.com/users/me";
7
+ const envPrefix = "MERCADO_PAGO";
8
+ export class MercadoPago {
9
+ clientId;
10
+ clientSecret;
11
+ redirectURI;
12
+ auth = null;
13
+ constructor(clientIdOrOptions, clientSecret, redirectURI) {
14
+ if (typeof clientIdOrOptions === "object") {
15
+ this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
16
+ clientSecret: true,
17
+ redirectURI: true
18
+ });
19
+ this.clientId = this.auth.clientId;
20
+ this.clientSecret = this.auth.clientSecret ?? "";
21
+ this.redirectURI = this.auth.redirectURI ?? "";
22
+ }
23
+ else {
24
+ this.clientId = clientIdOrOptions;
25
+ this.clientSecret = clientSecret ?? "";
26
+ this.redirectURI = redirectURI ?? "";
27
+ }
28
+ }
29
+ // `scopes` not required since they are defined in the application settings
30
+ createAuthorizationURL(state, codeVerifier) {
31
+ const url = new URL(authorizationEndpoint);
32
+ url.searchParams.set("response_type", "code");
33
+ url.searchParams.set("client_id", this.clientId);
34
+ url.searchParams.set("redirect_uri", this.redirectURI);
35
+ url.searchParams.set("state", state);
36
+ const codeChallenge = createS256CodeChallenge(codeVerifier);
37
+ url.searchParams.set("code_challenge_method", "S256");
38
+ url.searchParams.set("code_challenge", codeChallenge);
39
+ return url;
40
+ }
41
+ async validateAuthorizationCode(code, codeVerifier) {
42
+ const body = new URLSearchParams();
43
+ body.set("grant_type", "authorization_code");
44
+ body.set("code", code);
45
+ body.set("redirect_uri", this.redirectURI);
46
+ body.set("code_verifier", codeVerifier);
47
+ body.set("client_id", this.clientId);
48
+ body.set("client_secret", this.clientSecret);
49
+ const request = createOAuth2Request(tokenEndpoint, body);
50
+ const tokens = await sendTokenRequest(request);
51
+ return tokens;
52
+ }
53
+ async refreshAccessToken(refreshToken) {
54
+ const body = new URLSearchParams();
55
+ body.set("grant_type", "refresh_token");
56
+ body.set("refresh_token", refreshToken);
57
+ body.set("client_id", this.clientId);
58
+ body.set("client_secret", this.clientSecret);
59
+ const request = createOAuth2Request(tokenEndpoint, body);
60
+ const tokens = await sendTokenRequest(request);
61
+ return tokens;
62
+ }
63
+ // Scopes are defined in the application settings, so the argument is ignored.
64
+ async getAuthorizationURL(_scopes) {
65
+ const auth = requireAuthConfig(this.auth);
66
+ const state = generateOAuthState();
67
+ const codeVerifier = generateOAuthCodeVerifier();
68
+ const url = this.createAuthorizationURL(state, codeVerifier);
69
+ await saveOAuthState(auth.store, state, { codeVerifier });
70
+ return url;
71
+ }
72
+ async getUser(query) {
73
+ const auth = requireAuthConfig(this.auth);
74
+ const { code, state } = parseCallbackQuery(query);
75
+ const stored = await consumeOAuthState(auth.store, state);
76
+ if (typeof stored.codeVerifier !== "string") {
77
+ throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
78
+ }
79
+ const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
80
+ const profile = await fetchUserProfile(userEndpoint, tokens.accessToken());
81
+ const firstName = profileString(profile.first_name);
82
+ const lastName = profileString(profile.last_name);
83
+ const fullName = [firstName, lastName].filter((part) => part !== null).join(" ");
84
+ let image = null;
85
+ if (typeof profile.thumbnail === "object" && profile.thumbnail !== null) {
86
+ image = profileString(profile.thumbnail.picture_url);
87
+ }
88
+ return {
89
+ id: profileId(profile.id),
90
+ name: fullName !== "" ? fullName : profileString(profile.nickname),
91
+ email: profileString(profile.email),
92
+ image
93
+ };
94
+ }
95
+ }