@shware/security 2.5.3 → 3.0.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.
- package/dist/auth/index.cjs +519 -561
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +104 -106
- package/dist/auth/index.d.cts.map +1 -0
- package/dist/auth/index.d.mts +109 -0
- package/dist/auth/index.d.mts.map +1 -0
- package/dist/auth/index.mjs +512 -536
- package/dist/auth/index.mjs.map +1 -1
- package/dist/auth/types.cjs +0 -19
- package/dist/auth/types.d.cts +44 -44
- package/dist/auth/types.d.cts.map +1 -0
- package/dist/auth/types.d.mts +50 -0
- package/dist/auth/types.d.mts.map +1 -0
- package/dist/auth/types.mjs +1 -1
- package/dist/core/index.cjs +18 -59
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +13 -24
- package/dist/core/index.d.cts.map +1 -0
- package/dist/core/index.d.mts +21 -0
- package/dist/core/index.d.mts.map +1 -0
- package/dist/core/index.mjs +17 -33
- package/dist/core/index.mjs.map +1 -1
- package/dist/email/schema.cjs +13 -38
- package/dist/email/schema.cjs.map +1 -1
- package/dist/email/schema.d.cts +11 -12
- package/dist/email/schema.d.cts.map +1 -0
- package/dist/email/schema.d.mts +12 -0
- package/dist/email/schema.d.mts.map +1 -0
- package/dist/email/schema.mjs +10 -11
- package/dist/email/schema.mjs.map +1 -1
- package/dist/index.cjs +18 -54
- package/dist/index.d.cts +10 -15
- package/dist/index.d.mts +10 -0
- package/dist/index.mjs +5 -17
- package/dist/oauth2/client.cjs +109 -145
- package/dist/oauth2/client.cjs.map +1 -1
- package/dist/oauth2/client.d.cts +55 -56
- package/dist/oauth2/client.d.cts.map +1 -0
- package/dist/oauth2/client.d.mts +58 -0
- package/dist/oauth2/client.d.mts.map +1 -0
- package/dist/oauth2/client.mjs +104 -116
- package/dist/oauth2/client.mjs.map +1 -1
- package/dist/oauth2/error.cjs +19 -44
- package/dist/oauth2/error.cjs.map +1 -1
- package/dist/oauth2/error.d.cts +8 -6
- package/dist/oauth2/error.d.cts.map +1 -0
- package/dist/oauth2/{error.d.ts → error.d.mts} +8 -6
- package/dist/oauth2/error.d.mts.map +1 -0
- package/dist/oauth2/error.mjs +18 -19
- package/dist/oauth2/error.mjs.map +1 -1
- package/dist/oauth2/provider/apple.cjs +75 -88
- package/dist/oauth2/provider/apple.cjs.map +1 -1
- package/dist/oauth2/provider/apple.d.cts +31 -30
- package/dist/oauth2/provider/apple.d.cts.map +1 -0
- package/dist/oauth2/provider/apple.d.mts +42 -0
- package/dist/oauth2/provider/apple.d.mts.map +1 -0
- package/dist/oauth2/provider/apple.mjs +71 -60
- package/dist/oauth2/provider/apple.mjs.map +1 -1
- package/dist/oauth2/provider/common.cjs +86 -109
- package/dist/oauth2/provider/common.cjs.map +1 -1
- package/dist/oauth2/provider/common.d.cts +19 -18
- package/dist/oauth2/provider/common.d.cts.map +1 -0
- package/dist/oauth2/provider/common.d.mts +30 -0
- package/dist/oauth2/provider/common.d.mts.map +1 -0
- package/dist/oauth2/provider/common.mjs +80 -79
- package/dist/oauth2/provider/common.mjs.map +1 -1
- package/dist/oauth2/provider/facebook.cjs +93 -109
- package/dist/oauth2/provider/facebook.cjs.map +1 -1
- package/dist/oauth2/provider/facebook.d.cts +29 -28
- package/dist/oauth2/provider/facebook.d.cts.map +1 -0
- package/dist/oauth2/provider/facebook.d.mts +45 -0
- package/dist/oauth2/provider/facebook.d.mts.map +1 -0
- package/dist/oauth2/provider/facebook.mjs +89 -81
- package/dist/oauth2/provider/facebook.mjs.map +1 -1
- package/dist/oauth2/provider/github.cjs +64 -91
- package/dist/oauth2/provider/github.cjs.map +1 -1
- package/dist/oauth2/provider/github.d.cts +52 -51
- package/dist/oauth2/provider/github.d.cts.map +1 -0
- package/dist/oauth2/provider/github.d.mts +60 -0
- package/dist/oauth2/provider/github.d.mts.map +1 -0
- package/dist/oauth2/provider/github.mjs +60 -63
- package/dist/oauth2/provider/github.mjs.map +1 -1
- package/dist/oauth2/provider/google.cjs +105 -122
- package/dist/oauth2/provider/google.cjs.map +1 -1
- package/dist/oauth2/provider/google.d.cts +34 -33
- package/dist/oauth2/provider/google.d.cts.map +1 -0
- package/dist/oauth2/provider/google.d.mts +44 -0
- package/dist/oauth2/provider/google.d.mts.map +1 -0
- package/dist/oauth2/provider/google.mjs +101 -94
- package/dist/oauth2/provider/google.mjs.map +1 -1
- package/dist/oauth2/provider/index.cjs +13 -46
- package/dist/oauth2/provider/index.d.cts +7 -7
- package/dist/oauth2/provider/index.d.mts +7 -0
- package/dist/oauth2/provider/index.mjs +1 -10
- package/dist/oauth2/provider/wechat.cjs +77 -99
- package/dist/oauth2/provider/wechat.cjs.map +1 -1
- package/dist/oauth2/provider/wechat.d.cts +28 -27
- package/dist/oauth2/provider/wechat.d.cts.map +1 -0
- package/dist/oauth2/provider/wechat.d.mts +39 -0
- package/dist/oauth2/provider/wechat.d.mts.map +1 -0
- package/dist/oauth2/provider/wechat.mjs +74 -72
- package/dist/oauth2/provider/wechat.mjs.map +1 -1
- package/dist/oauth2/provider/x.cjs +102 -125
- package/dist/oauth2/provider/x.cjs.map +1 -1
- package/dist/oauth2/provider/x.d.cts +51 -50
- package/dist/oauth2/provider/x.d.cts.map +1 -0
- package/dist/oauth2/provider/x.d.mts +69 -0
- package/dist/oauth2/provider/x.d.mts.map +1 -0
- package/dist/oauth2/provider/x.mjs +99 -103
- package/dist/oauth2/provider/x.mjs.map +1 -1
- package/dist/oauth2/types.cjs +12 -37
- package/dist/oauth2/types.cjs.map +1 -1
- package/dist/oauth2/types.d.cts +176 -180
- package/dist/oauth2/types.d.cts.map +1 -0
- package/dist/oauth2/types.d.mts +207 -0
- package/dist/oauth2/types.d.mts.map +1 -0
- package/dist/oauth2/types.mjs +12 -13
- package/dist/oauth2/types.mjs.map +1 -1
- package/dist/session/common.cjs +17 -43
- package/dist/session/common.cjs.map +1 -1
- package/dist/session/common.d.cts +4 -4
- package/dist/session/common.d.cts.map +1 -0
- package/dist/session/{common.d.ts → common.d.mts} +4 -4
- package/dist/session/common.d.mts.map +1 -0
- package/dist/session/common.mjs +14 -16
- package/dist/session/common.mjs.map +1 -1
- package/dist/session/db.cjs +88 -123
- package/dist/session/db.cjs.map +1 -1
- package/dist/session/db.d.cts +36 -36
- package/dist/session/db.d.cts.map +1 -0
- package/dist/session/db.d.mts +44 -0
- package/dist/session/db.d.mts.map +1 -0
- package/dist/session/db.mjs +84 -95
- package/dist/session/db.mjs.map +1 -1
- package/dist/session/map-session.cjs +71 -103
- package/dist/session/map-session.cjs.map +1 -1
- package/dist/session/map-session.d.cts +24 -24
- package/dist/session/map-session.d.cts.map +1 -0
- package/dist/session/map-session.d.mts +27 -0
- package/dist/session/map-session.d.mts.map +1 -0
- package/dist/session/map-session.mjs +70 -78
- package/dist/session/map-session.mjs.map +1 -1
- package/dist/session/redis.cjs +270 -319
- package/dist/session/redis.cjs.map +1 -1
- package/dist/session/redis.d.cts +51 -51
- package/dist/session/redis.d.cts.map +1 -0
- package/dist/session/redis.d.mts +58 -0
- package/dist/session/redis.d.mts.map +1 -0
- package/dist/session/redis.mjs +266 -291
- package/dist/session/redis.mjs.map +1 -1
- package/dist/session/types.cjs +0 -19
- package/dist/session/types.d.cts +34 -33
- package/dist/session/types.d.cts.map +1 -0
- package/dist/session/types.d.mts +45 -0
- package/dist/session/types.d.mts.map +1 -0
- package/dist/session/types.mjs +1 -1
- package/dist/utils/http.cjs +31 -55
- package/dist/utils/http.cjs.map +1 -1
- package/dist/utils/http.d.cts +7 -10
- package/dist/utils/http.d.cts.map +1 -0
- package/dist/utils/{http.d.ts → http.d.mts} +7 -10
- package/dist/utils/http.d.mts.map +1 -0
- package/dist/utils/http.mjs +24 -24
- package/dist/utils/http.mjs.map +1 -1
- package/dist/utils/oauth2.cjs +6 -30
- package/dist/utils/oauth2.cjs.map +1 -1
- package/dist/utils/oauth2.d.cts +3 -1
- package/dist/utils/oauth2.d.cts.map +1 -0
- package/dist/utils/oauth2.d.mts +5 -0
- package/dist/utils/oauth2.d.mts.map +1 -0
- package/dist/utils/oauth2.mjs +5 -5
- package/dist/utils/oauth2.mjs.map +1 -1
- package/dist/utils/timing.cjs +49 -70
- package/dist/utils/timing.cjs.map +1 -1
- package/dist/utils/timing.d.cts +10 -8
- package/dist/utils/timing.d.cts.map +1 -0
- package/dist/utils/timing.d.mts +15 -0
- package/dist/utils/timing.d.mts.map +1 -0
- package/dist/utils/timing.mjs +48 -45
- package/dist/utils/timing.mjs.map +1 -1
- package/dist/utils/valid.cjs +50 -71
- package/dist/utils/valid.cjs.map +1 -1
- package/dist/utils/valid.d.cts +17 -16
- package/dist/utils/valid.d.cts.map +1 -0
- package/dist/utils/valid.d.mts +28 -0
- package/dist/utils/valid.d.mts.map +1 -0
- package/dist/utils/valid.mjs +47 -44
- package/dist/utils/valid.mjs.map +1 -1
- package/package.json +22 -12
- package/dist/auth/index.d.ts +0 -111
- package/dist/auth/types.cjs.map +0 -1
- package/dist/auth/types.d.ts +0 -50
- package/dist/auth/types.mjs.map +0 -1
- package/dist/core/index.d.ts +0 -32
- package/dist/email/schema.d.ts +0 -13
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -15
- package/dist/index.mjs.map +0 -1
- package/dist/oauth2/client.d.ts +0 -59
- package/dist/oauth2/provider/apple.d.ts +0 -41
- package/dist/oauth2/provider/common.d.ts +0 -29
- package/dist/oauth2/provider/facebook.d.ts +0 -44
- package/dist/oauth2/provider/github.d.ts +0 -59
- package/dist/oauth2/provider/google.d.ts +0 -43
- package/dist/oauth2/provider/index.cjs.map +0 -1
- package/dist/oauth2/provider/index.d.ts +0 -7
- package/dist/oauth2/provider/index.mjs.map +0 -1
- package/dist/oauth2/provider/wechat.d.ts +0 -38
- package/dist/oauth2/provider/x.d.ts +0 -68
- package/dist/oauth2/types.d.ts +0 -211
- package/dist/session/__tests__/redis.test.cjs +0 -247
- package/dist/session/__tests__/redis.test.cjs.map +0 -1
- package/dist/session/__tests__/redis.test.d.cts +0 -2
- package/dist/session/__tests__/redis.test.d.ts +0 -2
- package/dist/session/__tests__/redis.test.mjs +0 -252
- package/dist/session/__tests__/redis.test.mjs.map +0 -1
- package/dist/session/db.d.ts +0 -44
- package/dist/session/map-session.d.ts +0 -27
- package/dist/session/redis.d.ts +0 -58
- package/dist/session/types.cjs.map +0 -1
- package/dist/session/types.d.ts +0 -44
- package/dist/session/types.mjs.map +0 -1
- package/dist/utils/oauth2.d.ts +0 -3
- package/dist/utils/timing.d.ts +0 -13
- package/dist/utils/valid.d.ts +0 -27
|
@@ -1,76 +1,78 @@
|
|
|
1
|
-
// src/oauth2/provider/wechat.ts
|
|
2
|
-
import { invariant } from "@shware/utils";
|
|
3
1
|
import { OAuth2Error } from "../error.mjs";
|
|
2
|
+
import { invariant } from "@shware/utils";
|
|
3
|
+
//#region src/oauth2/provider/wechat.ts
|
|
4
|
+
/**
|
|
5
|
+
* reference: https://developers.weixin.qq.com/doc/offiaccount/en/OA_Web_Apps/Wechat_webpage_authorization.html
|
|
6
|
+
*/
|
|
4
7
|
function createWechatProvider(options = { isWechatBrowser: false }) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
8
|
+
const { isWechatBrowser } = options;
|
|
9
|
+
return {
|
|
10
|
+
authorizationUri: isWechatBrowser ? "https://open.weixin.qq.com/connect/oauth2/authorize" : "https://open.weixin.qq.com/connect/qrconnect",
|
|
11
|
+
tokenUri: "https://api.weixin.qq.com/sns/oauth2/access_token",
|
|
12
|
+
tokenRefreshUri: "https://api.weixin.qq.com/sns/oauth2/refresh_token",
|
|
13
|
+
userInfoUri: "https://api.weixin.qq.com/sns/userinfo",
|
|
14
|
+
defaultScope: [isWechatBrowser ? "snsapi_userinfo" : "snsapi_login"],
|
|
15
|
+
createAuthorizationUri(params) {
|
|
16
|
+
const url = new URL(this.authorizationUri);
|
|
17
|
+
url.searchParams.set("appid", params.clientId);
|
|
18
|
+
url.searchParams.set("scope", (params.scope ?? this.defaultScope).join(","));
|
|
19
|
+
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
20
|
+
url.searchParams.set("response_type", "code");
|
|
21
|
+
url.searchParams.set("state", params.state);
|
|
22
|
+
return url;
|
|
23
|
+
},
|
|
24
|
+
async exchangeAuthorizationCode(params) {
|
|
25
|
+
const url = new URL(this.tokenUri);
|
|
26
|
+
url.searchParams.set("appid", params.clientId);
|
|
27
|
+
url.searchParams.set("secret", params.clientSecret);
|
|
28
|
+
url.searchParams.set("code", params.code);
|
|
29
|
+
url.searchParams.set("grant_type", "authorization_code");
|
|
30
|
+
const response = await fetch(url.href);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const { errcode, errmsg } = await response.json();
|
|
33
|
+
throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);
|
|
34
|
+
}
|
|
35
|
+
return await response.json();
|
|
36
|
+
},
|
|
37
|
+
async getUserInfo({ access_token, openid }) {
|
|
38
|
+
invariant(this.userInfoUri, "userInfoUri is required");
|
|
39
|
+
invariant(openid && typeof openid === "string", "openid is required");
|
|
40
|
+
const url = new URL(this.userInfoUri);
|
|
41
|
+
url.searchParams.set("access_token", access_token);
|
|
42
|
+
url.searchParams.set("openid", openid);
|
|
43
|
+
const response = await fetch(url.href);
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
const { errcode, errmsg } = await response.json();
|
|
46
|
+
throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);
|
|
47
|
+
}
|
|
48
|
+
const data = await response.json();
|
|
49
|
+
return {
|
|
50
|
+
data,
|
|
51
|
+
claims: {
|
|
52
|
+
sub: data.unionid ?? data.openid,
|
|
53
|
+
name: data.nickname,
|
|
54
|
+
picture: `${data.headimgurl.split("/").slice(0, -1).join("/")}/0`,
|
|
55
|
+
gender: data.sex === 1 ? "male" : data.sex === 2 ? "female" : void 0
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
async refreshAccessToken(params) {
|
|
60
|
+
invariant(this.tokenRefreshUri, "tokenRefreshUri is required");
|
|
61
|
+
const url = new URL(this.tokenRefreshUri);
|
|
62
|
+
url.searchParams.set("appid", params.clientId);
|
|
63
|
+
url.searchParams.set("grant_type", "refresh_token");
|
|
64
|
+
url.searchParams.set("refresh_token", params.refreshToken);
|
|
65
|
+
const response = await fetch(url.href);
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const { errcode, errmsg } = await response.json();
|
|
68
|
+
throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);
|
|
69
|
+
}
|
|
70
|
+
return await response.json();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
70
73
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
74
|
+
const wechat = createWechatProvider();
|
|
75
|
+
//#endregion
|
|
76
|
+
export { createWechatProvider, wechat };
|
|
77
|
+
|
|
76
78
|
//# sourceMappingURL=wechat.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/wechat.ts"],"sourcesContent":["import { invariant } from '@shware/utils';\nimport { OAuth2Error } from '../error';\nimport type { OAuth2Token, Provider } from '../types';\n\nexport type Options = { isWechatBrowser: boolean };\n\n/**\n * reference: https://developers.weixin.qq.com/doc/offiaccount/en/OA_Web_Apps/Wechat_webpage_authorization.html\n */\nexport function createWechatProvider(options: Options = { isWechatBrowser: false }): Provider {\n const { isWechatBrowser } = options;\n return {\n authorizationUri: isWechatBrowser\n ? 'https://open.weixin.qq.com/connect/oauth2/authorize'\n : 'https://open.weixin.qq.com/connect/qrconnect',\n tokenUri: 'https://api.weixin.qq.com/sns/oauth2/access_token',\n tokenRefreshUri: 'https://api.weixin.qq.com/sns/oauth2/refresh_token',\n userInfoUri: 'https://api.weixin.qq.com/sns/userinfo',\n defaultScope: [isWechatBrowser ? 'snsapi_userinfo' : 'snsapi_login'],\n createAuthorizationUri(params) {\n const url = new URL(this.authorizationUri);\n url.searchParams.set('appid', params.clientId);\n url.searchParams.set('scope', (params.scope ?? this.defaultScope).join(','));\n url.searchParams.set('redirect_uri', params.redirectUri);\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('state', params.state);\n return url;\n },\n async exchangeAuthorizationCode(params) {\n const url = new URL(this.tokenUri);\n url.searchParams.set('appid', params.clientId);\n url.searchParams.set('secret', params.clientSecret);\n url.searchParams.set('code', params.code);\n url.searchParams.set('grant_type', 'authorization_code');\n const response = await fetch(url.href);\n if (!response.ok) {\n const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n }\n return (await response.json()) as WechatToken;\n },\n async getUserInfo({ access_token, openid }) {\n invariant(this.userInfoUri, 'userInfoUri is required');\n invariant(openid && typeof openid === 'string', 'openid is required');\n const url = new URL(this.userInfoUri);\n url.searchParams.set('access_token', access_token);\n url.searchParams.set('openid', openid);\n const response = await fetch(url.href);\n if (!response.ok) {\n const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n }\n const data = (await response.json()) as WechatUserInfo;\n\n return {\n data,\n claims: {\n sub: data.unionid ?? data.openid,\n name: data.nickname,\n picture: `${data.headimgurl.split('/').slice(0, -1).join('/')}/0`,\n gender: data.sex === 1 ? 'male' : data.sex === 2 ? 'female' : undefined,\n },\n };\n },\n async refreshAccessToken(params) {\n invariant(this.tokenRefreshUri, 'tokenRefreshUri is required');\n const url = new URL(this.tokenRefreshUri);\n url.searchParams.set('appid', params.clientId);\n url.searchParams.set('grant_type', 'refresh_token');\n url.searchParams.set('refresh_token', params.refreshToken);\n const response = await fetch(url.href);\n if (!response.ok) {\n const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n }\n return (await response.json()) as WechatToken;\n },\n };\n}\n\nexport const wechat = createWechatProvider();\n\nexport interface WechatUserInfo {\n openid: string;\n nickname: string;\n sex: 0 | 1 | 2; // 0: unknown, 1: male, 2: female\n province: string;\n city: string;\n country: string;\n /**\n * User's profile photo. The last numeric value represents the size of a square profile photo\n * (The value can be 0, 46, 64, 96, or 132. The value 0 represents a 640*640 square profile\n * photo). This parameter is left blank if a user has no profile photo. If the user changes the\n * profile photo, the URL of the original profile photo will expire.\n * e.g. http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46\n */\n headimgurl: string;\n privilege: string[];\n unionid?: string;\n}\n\nexport interface WechatToken extends OAuth2Token {\n access_token: string;\n expires_in: number;\n refresh_token: string;\n openid: string;\n scope: string;\n unionid?: string;\n}\n\ninterface WechatErrorResponse {\n errcode: number;\n errmsg: string;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"wechat.mjs","names":[],"sources":["../../../src/oauth2/provider/wechat.ts"],"sourcesContent":["import { invariant } from '@shware/utils';\nimport { OAuth2Error } from '../error';\nimport type { OAuth2Token, Provider } from '../types';\n\nexport type Options = { isWechatBrowser: boolean };\n\n/**\n * reference: https://developers.weixin.qq.com/doc/offiaccount/en/OA_Web_Apps/Wechat_webpage_authorization.html\n */\nexport function createWechatProvider(options: Options = { isWechatBrowser: false }): Provider {\n const { isWechatBrowser } = options;\n return {\n authorizationUri: isWechatBrowser\n ? 'https://open.weixin.qq.com/connect/oauth2/authorize'\n : 'https://open.weixin.qq.com/connect/qrconnect',\n tokenUri: 'https://api.weixin.qq.com/sns/oauth2/access_token',\n tokenRefreshUri: 'https://api.weixin.qq.com/sns/oauth2/refresh_token',\n userInfoUri: 'https://api.weixin.qq.com/sns/userinfo',\n defaultScope: [isWechatBrowser ? 'snsapi_userinfo' : 'snsapi_login'],\n createAuthorizationUri(params) {\n const url = new URL(this.authorizationUri);\n url.searchParams.set('appid', params.clientId);\n url.searchParams.set('scope', (params.scope ?? this.defaultScope).join(','));\n url.searchParams.set('redirect_uri', params.redirectUri);\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('state', params.state);\n return url;\n },\n async exchangeAuthorizationCode(params) {\n const url = new URL(this.tokenUri);\n url.searchParams.set('appid', params.clientId);\n url.searchParams.set('secret', params.clientSecret);\n url.searchParams.set('code', params.code);\n url.searchParams.set('grant_type', 'authorization_code');\n const response = await fetch(url.href);\n if (!response.ok) {\n const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n }\n return (await response.json()) as WechatToken;\n },\n async getUserInfo({ access_token, openid }) {\n invariant(this.userInfoUri, 'userInfoUri is required');\n invariant(openid && typeof openid === 'string', 'openid is required');\n const url = new URL(this.userInfoUri);\n url.searchParams.set('access_token', access_token);\n url.searchParams.set('openid', openid);\n const response = await fetch(url.href);\n if (!response.ok) {\n const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n }\n const data = (await response.json()) as WechatUserInfo;\n\n return {\n data,\n claims: {\n sub: data.unionid ?? data.openid,\n name: data.nickname,\n picture: `${data.headimgurl.split('/').slice(0, -1).join('/')}/0`,\n gender: data.sex === 1 ? 'male' : data.sex === 2 ? 'female' : undefined,\n },\n };\n },\n async refreshAccessToken(params) {\n invariant(this.tokenRefreshUri, 'tokenRefreshUri is required');\n const url = new URL(this.tokenRefreshUri);\n url.searchParams.set('appid', params.clientId);\n url.searchParams.set('grant_type', 'refresh_token');\n url.searchParams.set('refresh_token', params.refreshToken);\n const response = await fetch(url.href);\n if (!response.ok) {\n const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n }\n return (await response.json()) as WechatToken;\n },\n };\n}\n\nexport const wechat = createWechatProvider();\n\nexport interface WechatUserInfo {\n openid: string;\n nickname: string;\n sex: 0 | 1 | 2; // 0: unknown, 1: male, 2: female\n province: string;\n city: string;\n country: string;\n /**\n * User's profile photo. The last numeric value represents the size of a square profile photo\n * (The value can be 0, 46, 64, 96, or 132. The value 0 represents a 640*640 square profile\n * photo). This parameter is left blank if a user has no profile photo. If the user changes the\n * profile photo, the URL of the original profile photo will expire.\n * e.g. http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46\n */\n headimgurl: string;\n privilege: string[];\n unionid?: string;\n}\n\nexport interface WechatToken extends OAuth2Token {\n access_token: string;\n expires_in: number;\n refresh_token: string;\n openid: string;\n scope: string;\n unionid?: string;\n}\n\ninterface WechatErrorResponse {\n errcode: number;\n errmsg: string;\n}\n"],"mappings":";;;;;;AASA,SAAgB,qBAAqB,UAAmB,EAAE,iBAAiB,MAAM,GAAa;CAC5F,MAAM,EAAE,oBAAoB;CAC5B,OAAO;EACL,kBAAkB,kBACd,wDACA;EACJ,UAAU;EACV,iBAAiB;EACjB,aAAa;EACb,cAAc,CAAC,kBAAkB,oBAAoB,cAAc;EACnE,uBAAuB,QAAQ;GAC7B,MAAM,MAAM,IAAI,IAAI,KAAK,gBAAgB;GACzC,IAAI,aAAa,IAAI,SAAS,OAAO,QAAQ;GAC7C,IAAI,aAAa,IAAI,UAAU,OAAO,SAAS,KAAK,aAAA,CAAc,KAAK,GAAG,CAAC;GAC3E,IAAI,aAAa,IAAI,gBAAgB,OAAO,WAAW;GACvD,IAAI,aAAa,IAAI,iBAAiB,MAAM;GAC5C,IAAI,aAAa,IAAI,SAAS,OAAO,KAAK;GAC1C,OAAO;EACT;EACA,MAAM,0BAA0B,QAAQ;GACtC,MAAM,MAAM,IAAI,IAAI,KAAK,QAAQ;GACjC,IAAI,aAAa,IAAI,SAAS,OAAO,QAAQ;GAC7C,IAAI,aAAa,IAAI,UAAU,OAAO,YAAY;GAClD,IAAI,aAAa,IAAI,QAAQ,OAAO,IAAI;GACxC,IAAI,aAAa,IAAI,cAAc,oBAAoB;GACvD,MAAM,WAAW,MAAM,MAAM,IAAI,IAAI;GACrC,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,EAAE,SAAS,WAAY,MAAM,SAAS,KAAK;IACjD,MAAM,IAAI,YAAY,SAAS,QAAQ,QAAQ,YAAY,SAAS;GACtE;GACA,OAAQ,MAAM,SAAS,KAAK;EAC9B;EACA,MAAM,YAAY,EAAE,cAAc,UAAU;GAC1C,UAAU,KAAK,aAAa,yBAAyB;GACrD,UAAU,UAAU,OAAO,WAAW,UAAU,oBAAoB;GACpE,MAAM,MAAM,IAAI,IAAI,KAAK,WAAW;GACpC,IAAI,aAAa,IAAI,gBAAgB,YAAY;GACjD,IAAI,aAAa,IAAI,UAAU,MAAM;GACrC,MAAM,WAAW,MAAM,MAAM,IAAI,IAAI;GACrC,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,EAAE,SAAS,WAAY,MAAM,SAAS,KAAK;IACjD,MAAM,IAAI,YAAY,SAAS,QAAQ,QAAQ,YAAY,SAAS;GACtE;GACA,MAAM,OAAQ,MAAM,SAAS,KAAK;GAElC,OAAO;IACL;IACA,QAAQ;KACN,KAAK,KAAK,WAAW,KAAK;KAC1B,MAAM,KAAK;KACX,SAAS,GAAG,KAAK,WAAW,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,GAAG,EAAE;KAC9D,QAAQ,KAAK,QAAQ,IAAI,SAAS,KAAK,QAAQ,IAAI,WAAW,KAAA;IAChE;GACF;EACF;EACA,MAAM,mBAAmB,QAAQ;GAC/B,UAAU,KAAK,iBAAiB,6BAA6B;GAC7D,MAAM,MAAM,IAAI,IAAI,KAAK,eAAe;GACxC,IAAI,aAAa,IAAI,SAAS,OAAO,QAAQ;GAC7C,IAAI,aAAa,IAAI,cAAc,eAAe;GAClD,IAAI,aAAa,IAAI,iBAAiB,OAAO,YAAY;GACzD,MAAM,WAAW,MAAM,MAAM,IAAI,IAAI;GACrC,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,EAAE,SAAS,WAAY,MAAM,SAAS,KAAK;IACjD,MAAM,IAAI,YAAY,SAAS,QAAQ,QAAQ,YAAY,SAAS;GACtE;GACA,OAAQ,MAAM,SAAS,KAAK;EAC9B;CACF;AACF;AAEA,MAAa,SAAS,qBAAqB"}
|
|
@@ -1,129 +1,106 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/oauth2/provider/x.ts
|
|
21
|
-
var x_exports = {};
|
|
22
|
-
__export(x_exports, {
|
|
23
|
-
createXProvider: () => createXProvider,
|
|
24
|
-
x: () => x
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(x_exports);
|
|
27
|
-
var import_utils = require("@shware/utils");
|
|
28
|
-
var import_error = require("../error.cjs");
|
|
29
|
-
var import_common = require("./common.cjs");
|
|
30
|
-
var defaultUserFields = [
|
|
31
|
-
"id",
|
|
32
|
-
"name",
|
|
33
|
-
"profile_image_url",
|
|
34
|
-
"url",
|
|
35
|
-
"username",
|
|
36
|
-
"location",
|
|
37
|
-
"verified"
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_oauth2_error = require("../error.cjs");
|
|
3
|
+
const require_oauth2_provider_common = require("./common.cjs");
|
|
4
|
+
let _shware_utils = require("@shware/utils");
|
|
5
|
+
//#region src/oauth2/provider/x.ts
|
|
6
|
+
const defaultUserFields = [
|
|
7
|
+
"id",
|
|
8
|
+
"name",
|
|
9
|
+
"profile_image_url",
|
|
10
|
+
"url",
|
|
11
|
+
"username",
|
|
12
|
+
"location",
|
|
13
|
+
"verified"
|
|
38
14
|
];
|
|
39
15
|
function createXProvider(options) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
16
|
+
return {
|
|
17
|
+
authorizationUri: "https://x.com/i/oauth2/authorize",
|
|
18
|
+
tokenUri: "https://api.x.com/2/oauth2/token",
|
|
19
|
+
tokenRefreshUri: "https://api.x.com/2/oauth2/token",
|
|
20
|
+
tokenRevokeUri: "https://api.x.com/2/oauth2/revoke",
|
|
21
|
+
userInfoUri: "https://api.x.com/2/users/me",
|
|
22
|
+
defaultScope: [
|
|
23
|
+
"users.read",
|
|
24
|
+
"tweet.read",
|
|
25
|
+
"offline.access"
|
|
26
|
+
],
|
|
27
|
+
createAuthorizationUri(params) {
|
|
28
|
+
if (!params.pkce) throw new Error("pkce is required for x");
|
|
29
|
+
return require_oauth2_provider_common.createAuthorizationUri({
|
|
30
|
+
...params,
|
|
31
|
+
scope: params.scope ?? this.defaultScope,
|
|
32
|
+
authorizationUri: this.authorizationUri
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
async exchangeAuthorizationCode(params) {
|
|
36
|
+
if (!params.pkce) throw new Error("pkce is required for x");
|
|
37
|
+
const response = await require_oauth2_provider_common.exchangeAuthorizationCode({
|
|
38
|
+
...params,
|
|
39
|
+
tokenUri: this.tokenUri,
|
|
40
|
+
authentication: "basic"
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const { error, error_description } = await response.json();
|
|
44
|
+
throw new require_oauth2_error.OAuth2Error(response.status, error, error_description);
|
|
45
|
+
}
|
|
46
|
+
return await response.json();
|
|
47
|
+
},
|
|
48
|
+
async getUserInfo({ access_token }) {
|
|
49
|
+
(0, _shware_utils.invariant)(access_token, "access_token is required");
|
|
50
|
+
(0, _shware_utils.invariant)(this.userInfoUri, "userInfoUri is required");
|
|
51
|
+
const userFields = options?.userFields ?? defaultUserFields;
|
|
52
|
+
const headers = {
|
|
53
|
+
Accept: "application/json",
|
|
54
|
+
Authorization: `Bearer ${access_token}`
|
|
55
|
+
};
|
|
56
|
+
const url = new URL(this.userInfoUri);
|
|
57
|
+
userFields.forEach((field) => url.searchParams.append("user.fields", field));
|
|
58
|
+
const response = await fetch(this.userInfoUri, { headers });
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const { errors } = await response.json();
|
|
61
|
+
throw new require_oauth2_error.OAuth2Error(response.status, "invalid_request", `Failed to fetch user info: ${errors.at(0)?.detail ?? errors.at(0)?.title}`);
|
|
62
|
+
}
|
|
63
|
+
const profile = await response.json();
|
|
64
|
+
return {
|
|
65
|
+
data: profile,
|
|
66
|
+
claims: {
|
|
67
|
+
sub: profile.data.id,
|
|
68
|
+
name: profile.data.name,
|
|
69
|
+
picture: profile.data.profile_image_url,
|
|
70
|
+
email: profile.data.email,
|
|
71
|
+
email_verified: profile.data.verified || false,
|
|
72
|
+
preferred_username: profile.data.username,
|
|
73
|
+
profile: `https://x.com/${profile.data.username}`,
|
|
74
|
+
website: profile.data.url
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
async refreshAccessToken(params) {
|
|
79
|
+
(0, _shware_utils.invariant)(this.tokenRefreshUri, "tokenRefreshUri is required");
|
|
80
|
+
const response = await require_oauth2_provider_common.refreshAccessToken({
|
|
81
|
+
...params,
|
|
82
|
+
tokenUri: this.tokenRefreshUri,
|
|
83
|
+
authentication: "basic"
|
|
84
|
+
});
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
const { error, error_description } = await response.json();
|
|
87
|
+
throw new require_oauth2_error.OAuth2Error(response.status, error, error_description);
|
|
88
|
+
}
|
|
89
|
+
return await response.json();
|
|
90
|
+
},
|
|
91
|
+
async revokeToken(params) {
|
|
92
|
+
(0, _shware_utils.invariant)(this.tokenRevokeUri, "tokenRevokeUri is required");
|
|
93
|
+
return require_oauth2_provider_common.revokeToken({
|
|
94
|
+
...params,
|
|
95
|
+
tokenRevokeUri: this.tokenRevokeUri,
|
|
96
|
+
authentication: "basic"
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
};
|
|
122
100
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
});
|
|
101
|
+
const x = createXProvider();
|
|
102
|
+
//#endregion
|
|
103
|
+
exports.createXProvider = createXProvider;
|
|
104
|
+
exports.x = x;
|
|
105
|
+
|
|
129
106
|
//# sourceMappingURL=x.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/x.ts"],"sourcesContent":["import { invariant } from '@shware/utils';\nimport { OAuth2Error } from '../error';\nimport type { OAuth2Token, Provider } from '../types';\nimport {\n createAuthorizationUri,\n exchangeAuthorizationCode,\n refreshAccessToken,\n revokeToken,\n} from './common';\n\nexport interface XOptions {\n userFields?: UserField[];\n}\n\nconst defaultUserFields = [\n 'id',\n 'name',\n 'profile_image_url',\n 'url',\n 'username',\n 'location',\n 'verified',\n];\n\nexport function createXProvider(options?: XOptions): Provider {\n return {\n authorizationUri: 'https://x.com/i/oauth2/authorize',\n tokenUri: 'https://api.x.com/2/oauth2/token',\n tokenRefreshUri: 'https://api.x.com/2/oauth2/token',\n tokenRevokeUri: 'https://api.x.com/2/oauth2/revoke',\n // https://docs.x.com/x-api/users/user-lookup-me\n userInfoUri: 'https://api.x.com/2/users/me',\n defaultScope: ['users.read', 'tweet.read', 'offline.access'],\n createAuthorizationUri(params) {\n if (!params.pkce) throw new Error('pkce is required for x');\n return createAuthorizationUri({\n ...params,\n scope: params.scope ?? this.defaultScope,\n authorizationUri: this.authorizationUri,\n });\n },\n async exchangeAuthorizationCode(params) {\n if (!params.pkce) throw new Error('pkce is required for x');\n const response = await exchangeAuthorizationCode({\n ...params,\n tokenUri: this.tokenUri,\n authentication: 'basic',\n });\n if (!response.ok) {\n const { error, error_description } = (await response.json()) as XErrorResponse;\n throw new OAuth2Error(response.status, error, error_description);\n }\n return (await response.json()) as XToken;\n },\n async getUserInfo({ access_token }) {\n invariant(access_token, 'access_token is required');\n invariant(this.userInfoUri, 'userInfoUri is required');\n\n const userFields = options?.userFields ?? defaultUserFields;\n const headers = { Accept: 'application/json', Authorization: `Bearer ${access_token}` };\n\n const url = new URL(this.userInfoUri);\n userFields.forEach((field) => url.searchParams.append('user.fields', field));\n\n const response = await fetch(this.userInfoUri, { headers });\n if (!response.ok) {\n const { errors } = (await response.json()) as XAPIErrorResponse;\n throw new OAuth2Error(\n response.status,\n 'invalid_request',\n `Failed to fetch user info: ${errors.at(0)?.detail ?? errors.at(0)?.title}`\n );\n }\n const profile = (await response.json()) as XUserInfo;\n return {\n data: profile,\n claims: {\n sub: profile.data.id,\n name: profile.data.name,\n picture: profile.data.profile_image_url,\n email: profile.data.email,\n email_verified: profile.data.verified || false,\n preferred_username: profile.data.username,\n profile: `https://x.com/${profile.data.username}`,\n website: profile.data.url,\n },\n };\n },\n async refreshAccessToken(params) {\n invariant(this.tokenRefreshUri, 'tokenRefreshUri is required');\n const response = await refreshAccessToken({\n ...params,\n tokenUri: this.tokenRefreshUri,\n authentication: 'basic',\n });\n if (!response.ok) {\n const { error, error_description } = (await response.json()) as XErrorResponse;\n throw new OAuth2Error(response.status, error, error_description);\n }\n return (await response.json()) as XToken;\n },\n async revokeToken(params) {\n invariant(this.tokenRevokeUri, 'tokenRevokeUri is required');\n return revokeToken({\n ...params,\n tokenRevokeUri: this.tokenRevokeUri,\n authentication: 'basic',\n });\n },\n };\n}\n\nexport const x = createXProvider();\n\ntype UserField =\n | 'affiliation'\n | 'connection_status'\n | 'created_at'\n | 'description'\n | 'entities'\n | 'id'\n | 'is_identity_verified'\n | 'location'\n | 'most_recent_tweet_id'\n | 'name'\n | 'parody'\n | 'pinned_tweet_id'\n | 'profile_banner_url'\n | 'profile_image_url'\n | 'protected'\n | 'public_metrics'\n | 'receives_your_dm'\n | 'subscription'\n | 'subscription_type'\n | 'url'\n | 'username'\n | 'verified'\n | 'verified_followers_count'\n | 'verified_type'\n | 'withheld';\n\nexport interface XUser {\n id: string;\n name: string;\n email?: string;\n username: string;\n location?: string;\n entities?: {\n url: { urls: UrlEntity[] };\n description: {\n hashtags: HashtagEntity[];\n cashtags: HashtagEntity[];\n mentions: MentionEntity[];\n };\n };\n verified?: boolean;\n description?: string;\n url?: string;\n profile_image_url?: string;\n protected?: boolean;\n pinned_tweet_id?: string;\n created_at?: string;\n}\n\nexport interface XUserInfo {\n data: XUser;\n includes?: { tweets?: { id: string; text: string }[]; users?: XUser[] };\n}\n\ntype UrlEntity = {\n start: number;\n end: number;\n url: string;\n display_url: string;\n expanded_url: string;\n};\ntype HashtagEntity = { start: number; end: number; tag: string };\ntype MentionEntity = { start: number; end: string; username: string };\n\nexport interface XToken extends OAuth2Token {\n token_type: string;\n expires_in: number;\n access_token: string;\n scope: string;\n refresh_token: string;\n}\n\ntype XErrorResponse = { error: string; error_description: string };\ntype XAPIErrorResponse = {\n errors: { title: string; type: string; detail?: string; status?: number }[];\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"x.cjs","names":["createAuthorizationUri","exchangeAuthorizationCode","OAuth2Error","refreshAccessToken","revokeToken"],"sources":["../../../src/oauth2/provider/x.ts"],"sourcesContent":["import { invariant } from '@shware/utils';\nimport { OAuth2Error } from '../error';\nimport type { OAuth2Token, Provider } from '../types';\nimport {\n createAuthorizationUri,\n exchangeAuthorizationCode,\n refreshAccessToken,\n revokeToken,\n} from './common';\n\nexport interface XOptions {\n userFields?: UserField[];\n}\n\nconst defaultUserFields = [\n 'id',\n 'name',\n 'profile_image_url',\n 'url',\n 'username',\n 'location',\n 'verified',\n];\n\nexport function createXProvider(options?: XOptions): Provider {\n return {\n authorizationUri: 'https://x.com/i/oauth2/authorize',\n tokenUri: 'https://api.x.com/2/oauth2/token',\n tokenRefreshUri: 'https://api.x.com/2/oauth2/token',\n tokenRevokeUri: 'https://api.x.com/2/oauth2/revoke',\n // https://docs.x.com/x-api/users/user-lookup-me\n userInfoUri: 'https://api.x.com/2/users/me',\n defaultScope: ['users.read', 'tweet.read', 'offline.access'],\n createAuthorizationUri(params) {\n if (!params.pkce) throw new Error('pkce is required for x');\n return createAuthorizationUri({\n ...params,\n scope: params.scope ?? this.defaultScope,\n authorizationUri: this.authorizationUri,\n });\n },\n async exchangeAuthorizationCode(params) {\n if (!params.pkce) throw new Error('pkce is required for x');\n const response = await exchangeAuthorizationCode({\n ...params,\n tokenUri: this.tokenUri,\n authentication: 'basic',\n });\n if (!response.ok) {\n const { error, error_description } = (await response.json()) as XErrorResponse;\n throw new OAuth2Error(response.status, error, error_description);\n }\n return (await response.json()) as XToken;\n },\n async getUserInfo({ access_token }) {\n invariant(access_token, 'access_token is required');\n invariant(this.userInfoUri, 'userInfoUri is required');\n\n const userFields = options?.userFields ?? defaultUserFields;\n const headers = { Accept: 'application/json', Authorization: `Bearer ${access_token}` };\n\n const url = new URL(this.userInfoUri);\n userFields.forEach((field) => url.searchParams.append('user.fields', field));\n\n const response = await fetch(this.userInfoUri, { headers });\n if (!response.ok) {\n const { errors } = (await response.json()) as XAPIErrorResponse;\n throw new OAuth2Error(\n response.status,\n 'invalid_request',\n `Failed to fetch user info: ${errors.at(0)?.detail ?? errors.at(0)?.title}`\n );\n }\n const profile = (await response.json()) as XUserInfo;\n return {\n data: profile,\n claims: {\n sub: profile.data.id,\n name: profile.data.name,\n picture: profile.data.profile_image_url,\n email: profile.data.email,\n email_verified: profile.data.verified || false,\n preferred_username: profile.data.username,\n profile: `https://x.com/${profile.data.username}`,\n website: profile.data.url,\n },\n };\n },\n async refreshAccessToken(params) {\n invariant(this.tokenRefreshUri, 'tokenRefreshUri is required');\n const response = await refreshAccessToken({\n ...params,\n tokenUri: this.tokenRefreshUri,\n authentication: 'basic',\n });\n if (!response.ok) {\n const { error, error_description } = (await response.json()) as XErrorResponse;\n throw new OAuth2Error(response.status, error, error_description);\n }\n return (await response.json()) as XToken;\n },\n async revokeToken(params) {\n invariant(this.tokenRevokeUri, 'tokenRevokeUri is required');\n return revokeToken({\n ...params,\n tokenRevokeUri: this.tokenRevokeUri,\n authentication: 'basic',\n });\n },\n };\n}\n\nexport const x = createXProvider();\n\ntype UserField =\n | 'affiliation'\n | 'connection_status'\n | 'created_at'\n | 'description'\n | 'entities'\n | 'id'\n | 'is_identity_verified'\n | 'location'\n | 'most_recent_tweet_id'\n | 'name'\n | 'parody'\n | 'pinned_tweet_id'\n | 'profile_banner_url'\n | 'profile_image_url'\n | 'protected'\n | 'public_metrics'\n | 'receives_your_dm'\n | 'subscription'\n | 'subscription_type'\n | 'url'\n | 'username'\n | 'verified'\n | 'verified_followers_count'\n | 'verified_type'\n | 'withheld';\n\nexport interface XUser {\n id: string;\n name: string;\n email?: string;\n username: string;\n location?: string;\n entities?: {\n url: { urls: UrlEntity[] };\n description: {\n hashtags: HashtagEntity[];\n cashtags: HashtagEntity[];\n mentions: MentionEntity[];\n };\n };\n verified?: boolean;\n description?: string;\n url?: string;\n profile_image_url?: string;\n protected?: boolean;\n pinned_tweet_id?: string;\n created_at?: string;\n}\n\nexport interface XUserInfo {\n data: XUser;\n includes?: { tweets?: { id: string; text: string }[]; users?: XUser[] };\n}\n\ntype UrlEntity = {\n start: number;\n end: number;\n url: string;\n display_url: string;\n expanded_url: string;\n};\ntype HashtagEntity = { start: number; end: number; tag: string };\ntype MentionEntity = { start: number; end: string; username: string };\n\nexport interface XToken extends OAuth2Token {\n token_type: string;\n expires_in: number;\n access_token: string;\n scope: string;\n refresh_token: string;\n}\n\ntype XErrorResponse = { error: string; error_description: string };\ntype XAPIErrorResponse = {\n errors: { title: string; type: string; detail?: string; status?: number }[];\n};\n"],"mappings":";;;;;AAcA,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,gBAAgB,SAA8B;CAC5D,OAAO;EACL,kBAAkB;EAClB,UAAU;EACV,iBAAiB;EACjB,gBAAgB;EAEhB,aAAa;EACb,cAAc;GAAC;GAAc;GAAc;EAAgB;EAC3D,uBAAuB,QAAQ;GAC7B,IAAI,CAAC,OAAO,MAAM,MAAM,IAAI,MAAM,wBAAwB;GAC1D,OAAOA,+BAAAA,uBAAuB;IAC5B,GAAG;IACH,OAAO,OAAO,SAAS,KAAK;IAC5B,kBAAkB,KAAK;GACzB,CAAC;EACH;EACA,MAAM,0BAA0B,QAAQ;GACtC,IAAI,CAAC,OAAO,MAAM,MAAM,IAAI,MAAM,wBAAwB;GAC1D,MAAM,WAAW,MAAMC,+BAAAA,0BAA0B;IAC/C,GAAG;IACH,UAAU,KAAK;IACf,gBAAgB;GAClB,CAAC;GACD,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,EAAE,OAAO,sBAAuB,MAAM,SAAS,KAAK;IAC1D,MAAM,IAAIC,qBAAAA,YAAY,SAAS,QAAQ,OAAO,iBAAiB;GACjE;GACA,OAAQ,MAAM,SAAS,KAAK;EAC9B;EACA,MAAM,YAAY,EAAE,gBAAgB;GAClC,CAAA,GAAA,cAAA,UAAA,CAAU,cAAc,0BAA0B;GAClD,CAAA,GAAA,cAAA,UAAA,CAAU,KAAK,aAAa,yBAAyB;GAErD,MAAM,aAAa,SAAS,cAAc;GAC1C,MAAM,UAAU;IAAE,QAAQ;IAAoB,eAAe,UAAU;GAAe;GAEtF,MAAM,MAAM,IAAI,IAAI,KAAK,WAAW;GACpC,WAAW,SAAS,UAAU,IAAI,aAAa,OAAO,eAAe,KAAK,CAAC;GAE3E,MAAM,WAAW,MAAM,MAAM,KAAK,aAAa,EAAE,QAAQ,CAAC;GAC1D,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,EAAE,WAAY,MAAM,SAAS,KAAK;IACxC,MAAM,IAAIA,qBAAAA,YACR,SAAS,QACT,mBACA,8BAA8B,OAAO,GAAG,CAAC,CAAC,EAAE,UAAU,OAAO,GAAG,CAAC,CAAC,EAAE,OACtE;GACF;GACA,MAAM,UAAW,MAAM,SAAS,KAAK;GACrC,OAAO;IACL,MAAM;IACN,QAAQ;KACN,KAAK,QAAQ,KAAK;KAClB,MAAM,QAAQ,KAAK;KACnB,SAAS,QAAQ,KAAK;KACtB,OAAO,QAAQ,KAAK;KACpB,gBAAgB,QAAQ,KAAK,YAAY;KACzC,oBAAoB,QAAQ,KAAK;KACjC,SAAS,iBAAiB,QAAQ,KAAK;KACvC,SAAS,QAAQ,KAAK;IACxB;GACF;EACF;EACA,MAAM,mBAAmB,QAAQ;GAC/B,CAAA,GAAA,cAAA,UAAA,CAAU,KAAK,iBAAiB,6BAA6B;GAC7D,MAAM,WAAW,MAAMC,+BAAAA,mBAAmB;IACxC,GAAG;IACH,UAAU,KAAK;IACf,gBAAgB;GAClB,CAAC;GACD,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,EAAE,OAAO,sBAAuB,MAAM,SAAS,KAAK;IAC1D,MAAM,IAAID,qBAAAA,YAAY,SAAS,QAAQ,OAAO,iBAAiB;GACjE;GACA,OAAQ,MAAM,SAAS,KAAK;EAC9B;EACA,MAAM,YAAY,QAAQ;GACxB,CAAA,GAAA,cAAA,UAAA,CAAU,KAAK,gBAAgB,4BAA4B;GAC3D,OAAOE,+BAAAA,YAAY;IACjB,GAAG;IACH,gBAAgB,KAAK;IACrB,gBAAgB;GAClB,CAAC;EACH;CACF;AACF;AAEA,MAAa,IAAI,gBAAgB"}
|
|
@@ -1,68 +1,69 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { OAuth2Token, Provider } from "../types.cjs";
|
|
2
|
+
//#region src/oauth2/provider/x.d.ts
|
|
3
3
|
interface XOptions {
|
|
4
|
-
|
|
4
|
+
userFields?: UserField[];
|
|
5
5
|
}
|
|
6
6
|
declare function createXProvider(options?: XOptions): Provider;
|
|
7
7
|
declare const x: Provider;
|
|
8
8
|
type UserField = 'affiliation' | 'connection_status' | 'created_at' | 'description' | 'entities' | 'id' | 'is_identity_verified' | 'location' | 'most_recent_tweet_id' | 'name' | 'parody' | 'pinned_tweet_id' | 'profile_banner_url' | 'profile_image_url' | 'protected' | 'public_metrics' | 'receives_your_dm' | 'subscription' | 'subscription_type' | 'url' | 'username' | 'verified' | 'verified_followers_count' | 'verified_type' | 'withheld';
|
|
9
9
|
interface XUser {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
};
|
|
19
|
-
description: {
|
|
20
|
-
hashtags: HashtagEntity[];
|
|
21
|
-
cashtags: HashtagEntity[];
|
|
22
|
-
mentions: MentionEntity[];
|
|
23
|
-
};
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
email?: string;
|
|
13
|
+
username: string;
|
|
14
|
+
location?: string;
|
|
15
|
+
entities?: {
|
|
16
|
+
url: {
|
|
17
|
+
urls: UrlEntity[];
|
|
24
18
|
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
description: {
|
|
20
|
+
hashtags: HashtagEntity[];
|
|
21
|
+
cashtags: HashtagEntity[];
|
|
22
|
+
mentions: MentionEntity[];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
verified?: boolean;
|
|
26
|
+
description?: string;
|
|
27
|
+
url?: string;
|
|
28
|
+
profile_image_url?: string;
|
|
29
|
+
protected?: boolean;
|
|
30
|
+
pinned_tweet_id?: string;
|
|
31
|
+
created_at?: string;
|
|
32
32
|
}
|
|
33
33
|
interface XUserInfo {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
data: XUser;
|
|
35
|
+
includes?: {
|
|
36
|
+
tweets?: {
|
|
37
|
+
id: string;
|
|
38
|
+
text: string;
|
|
39
|
+
}[];
|
|
40
|
+
users?: XUser[];
|
|
41
|
+
};
|
|
42
42
|
}
|
|
43
43
|
type UrlEntity = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
start: number;
|
|
45
|
+
end: number;
|
|
46
|
+
url: string;
|
|
47
|
+
display_url: string;
|
|
48
|
+
expanded_url: string;
|
|
49
49
|
};
|
|
50
50
|
type HashtagEntity = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
start: number;
|
|
52
|
+
end: number;
|
|
53
|
+
tag: string;
|
|
54
54
|
};
|
|
55
55
|
type MentionEntity = {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
start: number;
|
|
57
|
+
end: string;
|
|
58
|
+
username: string;
|
|
59
59
|
};
|
|
60
60
|
interface XToken extends OAuth2Token {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
token_type: string;
|
|
62
|
+
expires_in: number;
|
|
63
|
+
access_token: string;
|
|
64
|
+
scope: string;
|
|
65
|
+
refresh_token: string;
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
export {
|
|
67
|
+
//#endregion
|
|
68
|
+
export { XOptions, XToken, XUser, XUserInfo, createXProvider, x };
|
|
69
|
+
//# sourceMappingURL=x.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x.d.cts","names":[],"sources":["../../../src/oauth2/provider/x.ts"],"mappings":";;UAUiB;EACf,aAAa;;iBAaC,gBAAgB,UAAU,WAAW;cAwFxC,GAAC;KAET;UA2BY;EACf;EACA;EACA;EACA;EACA;EACA;IACE;MAAO,MAAM;;IACb;MACE,UAAU;MACV,UAAU;MACV,UAAU;;;EAGd;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf,MAAM;EACN;IAAa;MAAW;MAAY;;IAAkB,QAAQ;;;KAG3D;EACH;EACA;EACA;EACA;EACA;;KAEG;EAAkB;EAAe;EAAa;;KAC9C;EAAkB;EAAe;EAAa;;UAElC,eAAe;EAC9B;EACA;EACA;EACA;EACA"}
|