dn-react-router-toolkit 0.1.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 (128) hide show
  1. package/README.md +1 -0
  2. package/dist/cjs/auth-kit/apple_auth.js +60 -0
  3. package/dist/cjs/auth-kit/auth_service.js +204 -0
  4. package/dist/cjs/auth-kit/client/google_login_button.js +25 -0
  5. package/dist/cjs/auth-kit/client/redirect_page.js +21 -0
  6. package/dist/cjs/auth-kit/google_auth.js +65 -0
  7. package/dist/cjs/auth-kit/jwt.js +53 -0
  8. package/dist/cjs/auth-kit/kakao_auth.js +38 -0
  9. package/dist/cjs/auth-kit/repository.js +2 -0
  10. package/dist/cjs/auth-kit/with_auth.js +46 -0
  11. package/dist/cjs/cn.js +6 -0
  12. package/dist/cjs/components/index.js +18 -0
  13. package/dist/cjs/components/modal/fullscreen_container.js +64 -0
  14. package/dist/cjs/components/modal/hooks.js +78 -0
  15. package/dist/cjs/components/modal/index.js +19 -0
  16. package/dist/cjs/components/modal/modal.js +91 -0
  17. package/dist/cjs/components/styles.js +10 -0
  18. package/dist/cjs/date.js +31 -0
  19. package/dist/cjs/file-kit/cdn.js +9 -0
  20. package/dist/cjs/file-kit/client/drop_file_input.js +195 -0
  21. package/dist/cjs/file-kit/client/file_uploader.js +78 -0
  22. package/dist/cjs/file-kit/file_service.js +29 -0
  23. package/dist/cjs/file-kit/object_storage.js +50 -0
  24. package/dist/cjs/file-kit/repository.js +2 -0
  25. package/dist/cjs/file-kit/responsive_image.js +78 -0
  26. package/dist/cjs/http-kit/index.js +17 -0
  27. package/dist/cjs/http-kit/response.js +34 -0
  28. package/dist/cjs/index.js +20 -0
  29. package/dist/cjs/route/api/auth/login/[provider]/route.js +36 -0
  30. package/dist/cjs/route/api/auth/login/route.js +35 -0
  31. package/dist/cjs/route/api/auth/logout/route.js +22 -0
  32. package/dist/cjs/route/api/auth/refresh/route.js +23 -0
  33. package/dist/cjs/route/api/auth/route.js +12 -0
  34. package/dist/cjs/route/api/files/[fileId]/route.js +20 -0
  35. package/dist/cjs/route/api/files/route.js +34 -0
  36. package/dist/cjs/route/auth/callback/[provider]/route.js +35 -0
  37. package/dist/cjs/route/index.js +80 -0
  38. package/dist/cjs/seo-kit/index.js +19 -0
  39. package/dist/cjs/seo-kit/loader.js +17 -0
  40. package/dist/cjs/seo-kit/seo.js +286 -0
  41. package/dist/cjs/seo-kit/seo_loader.js +19 -0
  42. package/dist/cjs/singleton.js +12 -0
  43. package/dist/cjs/slug.js +10 -0
  44. package/dist/esm/auth-kit/apple_auth.d.ts +15 -0
  45. package/dist/esm/auth-kit/apple_auth.js +56 -0
  46. package/dist/esm/auth-kit/auth_service.d.ts +67 -0
  47. package/dist/esm/auth-kit/auth_service.js +197 -0
  48. package/dist/esm/auth-kit/client/google_login_button.d.ts +6 -0
  49. package/dist/esm/auth-kit/client/google_login_button.js +19 -0
  50. package/dist/esm/auth-kit/client/redirect_page.d.ts +2 -0
  51. package/dist/esm/auth-kit/client/redirect_page.js +15 -0
  52. package/dist/esm/auth-kit/google_auth.d.ts +18 -0
  53. package/dist/esm/auth-kit/google_auth.js +61 -0
  54. package/dist/esm/auth-kit/jwt.d.ts +15 -0
  55. package/dist/esm/auth-kit/jwt.js +49 -0
  56. package/dist/esm/auth-kit/kakao_auth.d.ts +15 -0
  57. package/dist/esm/auth-kit/kakao_auth.js +34 -0
  58. package/dist/esm/auth-kit/repository.d.ts +40 -0
  59. package/dist/esm/auth-kit/repository.js +1 -0
  60. package/dist/esm/auth-kit/with_auth.d.ts +12 -0
  61. package/dist/esm/auth-kit/with_auth.js +43 -0
  62. package/dist/esm/cn.d.ts +1 -0
  63. package/dist/esm/cn.js +3 -0
  64. package/dist/esm/components/index.d.ts +2 -0
  65. package/dist/esm/components/index.js +2 -0
  66. package/dist/esm/components/modal/fullscreen_container.d.ts +5 -0
  67. package/dist/esm/components/modal/fullscreen_container.js +57 -0
  68. package/dist/esm/components/modal/hooks.d.ts +15 -0
  69. package/dist/esm/components/modal/hooks.js +69 -0
  70. package/dist/esm/components/modal/index.d.ts +3 -0
  71. package/dist/esm/components/modal/index.js +3 -0
  72. package/dist/esm/components/modal/modal.d.ts +10 -0
  73. package/dist/esm/components/modal/modal.js +55 -0
  74. package/dist/esm/components/styles.d.ts +7 -0
  75. package/dist/esm/components/styles.js +7 -0
  76. package/dist/esm/date.d.ts +1 -0
  77. package/dist/esm/date.js +24 -0
  78. package/dist/esm/file-kit/cdn.d.ts +3 -0
  79. package/dist/esm/file-kit/cdn.js +5 -0
  80. package/dist/esm/file-kit/client/drop_file_input.d.ts +31 -0
  81. package/dist/esm/file-kit/client/drop_file_input.js +158 -0
  82. package/dist/esm/file-kit/client/file_uploader.d.ts +11 -0
  83. package/dist/esm/file-kit/client/file_uploader.js +74 -0
  84. package/dist/esm/file-kit/file_service.d.ts +23 -0
  85. package/dist/esm/file-kit/file_service.js +25 -0
  86. package/dist/esm/file-kit/object_storage.d.ts +13 -0
  87. package/dist/esm/file-kit/object_storage.js +46 -0
  88. package/dist/esm/file-kit/repository.d.ts +14 -0
  89. package/dist/esm/file-kit/repository.js +1 -0
  90. package/dist/esm/file-kit/responsive_image.d.ts +17 -0
  91. package/dist/esm/file-kit/responsive_image.js +70 -0
  92. package/dist/esm/http-kit/index.d.ts +1 -0
  93. package/dist/esm/http-kit/index.js +1 -0
  94. package/dist/esm/http-kit/response.d.ts +17 -0
  95. package/dist/esm/http-kit/response.js +28 -0
  96. package/dist/esm/index.d.ts +4 -0
  97. package/dist/esm/index.js +4 -0
  98. package/dist/esm/route/api/auth/login/[provider]/route.d.ts +10 -0
  99. package/dist/esm/route/api/auth/login/[provider]/route.js +32 -0
  100. package/dist/esm/route/api/auth/login/route.d.ts +6 -0
  101. package/dist/esm/route/api/auth/login/route.js +31 -0
  102. package/dist/esm/route/api/auth/logout/route.d.ts +6 -0
  103. package/dist/esm/route/api/auth/logout/route.js +18 -0
  104. package/dist/esm/route/api/auth/refresh/route.d.ts +4 -0
  105. package/dist/esm/route/api/auth/refresh/route.js +19 -0
  106. package/dist/esm/route/api/auth/route.d.ts +4 -0
  107. package/dist/esm/route/api/auth/route.js +8 -0
  108. package/dist/esm/route/api/files/[fileId]/route.d.ts +8 -0
  109. package/dist/esm/route/api/files/[fileId]/route.js +16 -0
  110. package/dist/esm/route/api/files/route.d.ts +6 -0
  111. package/dist/esm/route/api/files/route.js +30 -0
  112. package/dist/esm/route/auth/callback/[provider]/route.d.ts +11 -0
  113. package/dist/esm/route/auth/callback/[provider]/route.js +31 -0
  114. package/dist/esm/route/index.d.ts +22 -0
  115. package/dist/esm/route/index.js +76 -0
  116. package/dist/esm/seo-kit/index.d.ts +3 -0
  117. package/dist/esm/seo-kit/index.js +3 -0
  118. package/dist/esm/seo-kit/loader.d.ts +5 -0
  119. package/dist/esm/seo-kit/loader.js +14 -0
  120. package/dist/esm/seo-kit/seo.d.ts +100 -0
  121. package/dist/esm/seo-kit/seo.js +280 -0
  122. package/dist/esm/seo-kit/seo_loader.d.ts +12 -0
  123. package/dist/esm/seo-kit/seo_loader.js +13 -0
  124. package/dist/esm/singleton.d.ts +1 -0
  125. package/dist/esm/singleton.js +9 -0
  126. package/dist/esm/slug.d.ts +1 -0
  127. package/dist/esm/slug.js +6 -0
  128. package/package.json +81 -0
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Dndnsoft React Router Toolkit
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppleAuth = void 0;
4
+ const jose_1 = require("jose");
5
+ class AppleAuth {
6
+ constructor(AUTH) {
7
+ this.AUTH = AUTH;
8
+ }
9
+ async signIn(code, type = "web") {
10
+ const url = "https://appleid.apple.com/auth/token";
11
+ const client_secret = await this.generateAppleClientSecret(type);
12
+ const res = await fetch(url, {
13
+ method: "POST",
14
+ headers: {
15
+ "Content-Type": "application/x-www-form-urlencoded",
16
+ },
17
+ body: new URLSearchParams({
18
+ client_id: type === "web"
19
+ ? process.env.APPLE_SERVICE_ID
20
+ : process.env.APPLE_CLIENT_ID,
21
+ client_secret,
22
+ code,
23
+ grant_type: "authorization_code",
24
+ }),
25
+ });
26
+ if (!res.ok) {
27
+ console.error(await res.text());
28
+ throw new Error("Apple 인증에 실패했습니다.");
29
+ }
30
+ const data = await res.json();
31
+ const { id_token } = data;
32
+ const payload = (0, jose_1.decodeJwt)(id_token);
33
+ const { sub, email, name } = payload;
34
+ const user = await this.AUTH.getOrCreateUser("apple", {
35
+ id: sub,
36
+ email,
37
+ name,
38
+ });
39
+ const { accessToken, refreshToken } = await this.AUTH.issueTokenPair(user);
40
+ return { user, accessToken, refreshToken };
41
+ }
42
+ async generateAppleClientSecret(type = "web") {
43
+ const authKey = process.env.APPLE_AUTH_KEY;
44
+ const teamId = process.env.APPLE_TEAM_ID;
45
+ const keyId = process.env.APPLE_KEY_ID;
46
+ const clientId = type === "web"
47
+ ? process.env.APPLE_SERVICE_ID
48
+ : process.env.APPLE_CLIENT_ID;
49
+ const keyObject = await (0, jose_1.importPKCS8)(authKey, "ES256");
50
+ return new jose_1.SignJWT()
51
+ .setProtectedHeader({ alg: "ES256", kid: keyId })
52
+ .setIssuedAt()
53
+ .setIssuer(teamId)
54
+ .setExpirationTime("1h")
55
+ .setAudience("https://appleid.apple.com")
56
+ .setSubject(clientId)
57
+ .sign(keyObject);
58
+ }
59
+ }
60
+ exports.AppleAuth = AppleAuth;
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AuthService = exports.REFRESH_TOKEN_COOKIE = exports.ACCESS_TOKEN_COOKIE = exports.REFRESH_TOKEN_KEY = exports.ACCESS_TOKEN_KEY = void 0;
7
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
8
+ const uuid_1 = require("uuid");
9
+ const react_router_1 = require("react-router");
10
+ exports.ACCESS_TOKEN_KEY = "access_token";
11
+ exports.REFRESH_TOKEN_KEY = "refresh_token";
12
+ exports.ACCESS_TOKEN_COOKIE = (0, react_router_1.createCookie)(exports.ACCESS_TOKEN_KEY, {
13
+ path: "/",
14
+ httpOnly: process.env.NODE_ENV === "production",
15
+ secure: process.env.NODE_ENV === "production",
16
+ sameSite: "strict",
17
+ });
18
+ exports.REFRESH_TOKEN_COOKIE = (0, react_router_1.createCookie)(exports.REFRESH_TOKEN_KEY, {
19
+ path: "/",
20
+ httpOnly: process.env.NODE_ENV === "production",
21
+ secure: process.env.NODE_ENV === "production",
22
+ sameSite: "strict",
23
+ });
24
+ class AuthService {
25
+ constructor({ repository, JWT_MANAGER, OBJECT_STORAGE, }) {
26
+ this.repository = repository;
27
+ this.JWT_MANAGER = JWT_MANAGER;
28
+ this.OBJECT_STORAGE = OBJECT_STORAGE;
29
+ }
30
+ async verify(request) {
31
+ var _a;
32
+ const accessToken = ((_a = request === null || request === void 0 ? void 0 : request.headers.get("Authorization")) === null || _a === void 0 ? void 0 : _a.replace("Bearer ", "")) ||
33
+ (await this.getAccessTokenFromCookies(request));
34
+ if (accessToken) {
35
+ return this.JWT_MANAGER.verifyAccessToken(accessToken);
36
+ }
37
+ }
38
+ async verifyOrRefresh(request) {
39
+ const payload = await this.verify(request);
40
+ if (payload) {
41
+ return payload;
42
+ }
43
+ return this.refresh(request);
44
+ }
45
+ async getAccessTokenFromCookies(request) {
46
+ var _a;
47
+ const cookieStore = await exports.ACCESS_TOKEN_COOKIE.parse(request.headers.get("cookie"));
48
+ return (_a = cookieStore.get(exports.ACCESS_TOKEN_KEY)) === null || _a === void 0 ? void 0 : _a.value;
49
+ }
50
+ async getRefreshTokenFromCookies(request) {
51
+ var _a;
52
+ const cookieStore = await exports.REFRESH_TOKEN_COOKIE.parse(request.headers.get("cookie"));
53
+ return (_a = cookieStore.get(exports.REFRESH_TOKEN_KEY)) === null || _a === void 0 ? void 0 : _a.value;
54
+ }
55
+ async refresh(request) {
56
+ const refreshToken = await this.getRefreshTokenFromCookies(request);
57
+ if (refreshToken) {
58
+ try {
59
+ const refreshedAccessToken = await this.refreshAccessToken(refreshToken);
60
+ await this.getAccessTokenSetCookie(refreshedAccessToken);
61
+ const payload = this.JWT_MANAGER.decode(refreshedAccessToken);
62
+ if (payload) {
63
+ return payload;
64
+ }
65
+ }
66
+ catch (e) {
67
+ if (e instanceof Error) {
68
+ console.log(e.message);
69
+ }
70
+ return;
71
+ }
72
+ }
73
+ }
74
+ async signIn({ id, password }) {
75
+ const credential = await this.repository.findCredentialById(id);
76
+ if (!credential) {
77
+ throw Error("아이디 또는 비밀번호가 틀렸습니다.");
78
+ }
79
+ if (!(await bcryptjs_1.default.compare(password, credential.password))) {
80
+ throw Error("아이디 또는 비밀번호가 틀렸습니다.");
81
+ }
82
+ const user = await this.repository.findUserById(credential.userId);
83
+ if (!user) {
84
+ throw Error("회원 정보를 찾을 수 없습니다.");
85
+ }
86
+ const { accessToken, refreshToken } = await this.issueTokenPair(user);
87
+ return {
88
+ accessToken,
89
+ refreshToken,
90
+ };
91
+ }
92
+ async issueAccessToken(user) {
93
+ return this.JWT_MANAGER.signAccessToken({
94
+ userId: user.id,
95
+ role: user.role,
96
+ name: user.name,
97
+ });
98
+ }
99
+ async issueTokenPair(user) {
100
+ const refreshToken = await this.JWT_MANAGER.signRefreshToken({
101
+ userId: user.id,
102
+ role: user.role,
103
+ name: user.name,
104
+ });
105
+ await this.repository.updateUserRefreshToken(user.id, await bcryptjs_1.default.hash(refreshToken, 10));
106
+ const accessToken = await this.issueAccessToken(user);
107
+ return { refreshToken, accessToken };
108
+ }
109
+ async refreshAccessToken(refreshToken) {
110
+ const payload = await this.JWT_MANAGER.verifyRefreshToken(refreshToken);
111
+ if (!payload) {
112
+ throw new Error("토큰이 유효하지 않습니다.");
113
+ }
114
+ const { userId } = payload;
115
+ if (typeof userId !== "string") {
116
+ throw new Error("토큰이 유효하지 않습니다.");
117
+ }
118
+ const user = await this.repository.findUserById(userId);
119
+ if (!user) {
120
+ throw Error("이용자를 찾지 못했습니다.");
121
+ }
122
+ if (!user.refreshToken) {
123
+ throw Error("인증 정보를 찾지 못했습니다.");
124
+ }
125
+ if (await bcryptjs_1.default.compare(user.refreshToken, refreshToken)) {
126
+ throw Error("토큰이 유효하지 않습니다.");
127
+ }
128
+ const accessToken = await this.issueAccessToken(user);
129
+ return accessToken;
130
+ }
131
+ async getAccessTokenSetCookie(accessToken) {
132
+ return exports.ACCESS_TOKEN_COOKIE.serialize(accessToken, {
133
+ expires: accessToken
134
+ ? this.JWT_MANAGER.getExpirationTime(accessToken)
135
+ : new Date(0),
136
+ });
137
+ }
138
+ async getRefreshTokenSetCookie(refreshToken) {
139
+ return exports.REFRESH_TOKEN_COOKIE.serialize(refreshToken, {
140
+ expires: refreshToken
141
+ ? this.JWT_MANAGER.getExpirationTime(refreshToken)
142
+ : new Date(0),
143
+ });
144
+ }
145
+ async findUser(provider, info) {
146
+ const thirdPartyAuth = await this.repository.findThirdPartyAuth(provider, info.id);
147
+ if (thirdPartyAuth) {
148
+ const user = await this.repository.findUserById(thirdPartyAuth.userId);
149
+ if (user) {
150
+ return user;
151
+ }
152
+ }
153
+ }
154
+ async getOrCreateUser(provider, info) {
155
+ const thirdPartyAuth = await this.repository.findThirdPartyAuth(provider, info.id);
156
+ if (thirdPartyAuth) {
157
+ const user = await this.repository.findUserById(thirdPartyAuth.userId);
158
+ if (user) {
159
+ return user;
160
+ }
161
+ }
162
+ const userId = (0, uuid_1.v4)();
163
+ const email = info.email;
164
+ const name = info.name || "익명";
165
+ const picture = info.picture;
166
+ const profileImageId = (await this.savePicture(picture)) || null;
167
+ const result = await this.repository.createUser({
168
+ id: userId,
169
+ role: "user",
170
+ profileImageId,
171
+ name,
172
+ email,
173
+ });
174
+ await this.repository.createThirdPartyAuth({
175
+ id: info.id,
176
+ provider,
177
+ userId,
178
+ });
179
+ return result;
180
+ }
181
+ async savePicture(picture) {
182
+ if (!picture) {
183
+ return;
184
+ }
185
+ const res = await fetch(picture);
186
+ if (!res.ok) {
187
+ return;
188
+ }
189
+ const buffer = await res.arrayBuffer();
190
+ const id = (0, uuid_1.v4)();
191
+ const key = `/users/${id}/picture`;
192
+ await this.OBJECT_STORAGE.put(key, Buffer.from(buffer));
193
+ await this.repository.createFile({
194
+ id,
195
+ name: "picture",
196
+ type: "image/*",
197
+ key,
198
+ size: buffer.byteLength,
199
+ metadata: {},
200
+ });
201
+ return id;
202
+ }
203
+ }
204
+ exports.AuthService = AuthService;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GoogleLoginButton = GoogleLoginButton;
7
+ const react_1 = __importDefault(require("react"));
8
+ const fc_1 = require("react-icons/fc");
9
+ const react_router_1 = require("react-router");
10
+ function GoogleLoginButton({ className = "max-w-[300px] w-full", GOOGLE_CLIENT_ID, GOOGLE_REDIRECT_URI, }) {
11
+ const [searchParams] = (0, react_router_1.useSearchParams)();
12
+ const redirectUrl = searchParams.get("redirectUrl") || "";
13
+ const googleClientId = GOOGLE_CLIENT_ID || "";
14
+ const googleRedirectUrl = GOOGLE_REDIRECT_URI || "";
15
+ const href = new URL("https://accounts.google.com/o/oauth2/v2/auth");
16
+ href.searchParams.append("client_id", googleClientId);
17
+ href.searchParams.append("redirect_uri", googleRedirectUrl);
18
+ href.searchParams.append("response_type", "code");
19
+ href.searchParams.append("scope", "email profile");
20
+ href.searchParams.append("state", redirectUrl);
21
+ return (react_1.default.createElement("div", { className: className },
22
+ react_1.default.createElement("a", { href: href.toString(), className: "relative flex items-center border border-neutral-300 px-4 py-3 no-underline hover:no-underline bg-white hover:bg-neutral-100 rounded" },
23
+ react_1.default.createElement(fc_1.FcGoogle, null),
24
+ react_1.default.createElement("p", { className: "text-[14px] text-black absolute left-0 right-0 text-center" }, "\uAD6C\uAE00\uB85C \uACC4\uC18D\uD558\uAE30"))));
25
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RedirectPage = RedirectPage;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_2 = require("react");
9
+ const react_router_1 = require("react-router");
10
+ function RedirectPage() {
11
+ const navigate = (0, react_router_1.useNavigate)();
12
+ (0, react_2.useEffect)(() => {
13
+ const searchParams = new URLSearchParams(window.location.search);
14
+ const redirectUrl = searchParams.get("redirectUrl") ||
15
+ new URL("/", window.location.origin).toString();
16
+ if (redirectUrl) {
17
+ navigate(redirectUrl);
18
+ }
19
+ }, [navigate]);
20
+ return react_1.default.createElement(react_1.default.Fragment, null);
21
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GoogleAuth = void 0;
4
+ const response_1 = require("../http-kit/response");
5
+ class GoogleAuth {
6
+ constructor(AUTH, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URI) {
7
+ this.GOOGLE_CLIENT_ID = GOOGLE_CLIENT_ID;
8
+ this.GOOGLE_CLIENT_SECRET = GOOGLE_CLIENT_SECRET;
9
+ this.GOOGLE_REDIRECT_URI = GOOGLE_REDIRECT_URI;
10
+ this.AUTH = AUTH;
11
+ }
12
+ async signIn(code) {
13
+ const tokenRes = await fetch("https://oauth2.googleapis.com/token", {
14
+ method: "POST",
15
+ headers: {
16
+ "Content-Type": "application/x-www-form-urlencoded",
17
+ },
18
+ body: new URLSearchParams({
19
+ code,
20
+ client_id: this.GOOGLE_CLIENT_ID,
21
+ client_secret: this.GOOGLE_CLIENT_SECRET,
22
+ redirect_uri: this.GOOGLE_REDIRECT_URI,
23
+ grant_type: "authorization_code",
24
+ }),
25
+ });
26
+ if (!tokenRes.ok) {
27
+ if (process.env.NODE_ENV === "development") {
28
+ throw (0, response_1.INTERNAL_SERVER_ERROR)(`구글 토큰 발급에 실패했습니다. status: ${tokenRes.status}, message: ${await tokenRes.text()}`);
29
+ }
30
+ throw (0, response_1.INTERNAL_SERVER_ERROR)("인증에 실패했습니다.");
31
+ }
32
+ const { access_token } = await tokenRes.json();
33
+ const userRes = await fetch("https://www.googleapis.com/oauth2/v1/userinfo", {
34
+ headers: {
35
+ Authorization: `Bearer ${access_token}`,
36
+ },
37
+ });
38
+ if (!userRes.ok) {
39
+ throw (0, response_1.BAD_REQUEST)("유저 정보를 가져오는데 실패했습니다.");
40
+ }
41
+ const { id, email, name, picture } = await userRes.json();
42
+ const user = await this.AUTH.findUser("google", {
43
+ id,
44
+ email,
45
+ name,
46
+ picture,
47
+ });
48
+ if (!user) {
49
+ throw (0, response_1.createJsonResponse)(404)({
50
+ provider: "google",
51
+ id,
52
+ name,
53
+ picture,
54
+ message: "사용자를 찾을 수 없습니다.",
55
+ });
56
+ }
57
+ const { accessToken, refreshToken } = await this.AUTH.issueTokenPair(user);
58
+ return {
59
+ user,
60
+ accessToken,
61
+ refreshToken,
62
+ };
63
+ }
64
+ }
65
+ exports.GoogleAuth = GoogleAuth;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JWTManager = void 0;
4
+ const jose_1 = require("jose");
5
+ class JWTManager {
6
+ constructor(siteOrigin) {
7
+ this.siteOrigin = siteOrigin;
8
+ }
9
+ async verify(token, secret) {
10
+ try {
11
+ const result = await (0, jose_1.jwtVerify)(token, new TextEncoder().encode(secret));
12
+ return result.payload;
13
+ }
14
+ catch (_) {
15
+ return;
16
+ }
17
+ }
18
+ async verifyAccessToken(token) {
19
+ return this.verify(token, process.env.ACCESS_TOKEN_SECRET);
20
+ }
21
+ async verifyRefreshToken(token) {
22
+ return this.verify(token, process.env.REFRESH_TOKEN_SECRET);
23
+ }
24
+ async sign(payload, secret, { expiresIn } = {}) {
25
+ let builder = new jose_1.SignJWT(payload)
26
+ .setProtectedHeader({ alg: "HS256", typ: "JWT" })
27
+ .setIssuedAt();
28
+ if (this.siteOrigin) {
29
+ builder = builder.setIssuer(this.siteOrigin);
30
+ }
31
+ if (expiresIn) {
32
+ builder = builder.setExpirationTime(expiresIn);
33
+ }
34
+ return builder.sign(new TextEncoder().encode(secret));
35
+ }
36
+ async signAccessToken(payload) {
37
+ return this.sign(payload, process.env.ACCESS_TOKEN_SECRET, {
38
+ expiresIn: process.env.ACCESS_TOKEN_EXPIRES_IN || "10s",
39
+ });
40
+ }
41
+ async signRefreshToken(payload) {
42
+ return this.sign(payload, process.env.REFRESH_TOKEN_SECRET, {
43
+ expiresIn: process.env.REFRESH_TOKEN_EXPIRES_IN || "1d",
44
+ });
45
+ }
46
+ decode(token) {
47
+ return (0, jose_1.decodeJwt)(token);
48
+ }
49
+ getExpirationTime(token) {
50
+ return new Date(Number((0, jose_1.decodeJwt)(token).exp) * 1000);
51
+ }
52
+ }
53
+ exports.JWTManager = JWTManager;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KakaoAuth = void 0;
4
+ const http_kit_1 = require("../http-kit");
5
+ class KakaoAuth {
6
+ constructor(AUTH) {
7
+ this.AUTH = AUTH;
8
+ }
9
+ async signIn(kakaoAccessToken) {
10
+ const userRes = await fetch("https://kapi.kakao.com/v2/user/me", {
11
+ headers: {
12
+ Authorization: `Bearer ${kakaoAccessToken}`,
13
+ },
14
+ });
15
+ if (!userRes.ok) {
16
+ throw new Error("유저 정보를 가져오는데 실패했습니다.");
17
+ }
18
+ const { id, kakao_account } = await userRes.json();
19
+ const { email, profile } = kakao_account;
20
+ const payload = {
21
+ id,
22
+ email,
23
+ name: profile.nickname,
24
+ picture: profile.thumbnail_image_url,
25
+ };
26
+ const user = await this.AUTH.findUser("kakao", payload);
27
+ if (!user) {
28
+ throw (0, http_kit_1.createJsonResponse)(404)(Object.assign(Object.assign({ provider: "kakao" }, payload), { message: "사용자를 찾을 수 없습니다." }));
29
+ }
30
+ const { accessToken, refreshToken } = await this.AUTH.issueTokenPair(user);
31
+ return {
32
+ user,
33
+ accessToken,
34
+ refreshToken,
35
+ };
36
+ }
37
+ }
38
+ exports.KakaoAuth = KakaoAuth;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWithAuthHandler = createWithAuthHandler;
4
+ const auth_service_1 = require("./auth_service");
5
+ function createWithAuthHandler({ JWT_MANAGER, AUTH, }) {
6
+ return function (fn) {
7
+ return async function (arg) {
8
+ const cookie = arg.request.headers.get("cookie");
9
+ const accessToken = await auth_service_1.ACCESS_TOKEN_COOKIE.parse(cookie);
10
+ if (accessToken) {
11
+ const payload = await JWT_MANAGER.verifyAccessToken(accessToken);
12
+ if (payload) {
13
+ return fn(payload)(arg);
14
+ }
15
+ }
16
+ const refreshToken = await auth_service_1.REFRESH_TOKEN_COOKIE.parse(cookie);
17
+ if (refreshToken) {
18
+ try {
19
+ const refreshedAccessToken = await AUTH.refreshAccessToken(refreshToken);
20
+ const setCookieHeader = await AUTH.getRefreshTokenSetCookie(refreshedAccessToken);
21
+ return new Response("Temporary Redirect", {
22
+ status: 307,
23
+ headers: {
24
+ "Set-Cookie": setCookieHeader,
25
+ Location: arg.request.url,
26
+ },
27
+ });
28
+ }
29
+ catch (e) {
30
+ if (e instanceof Error) {
31
+ console.log(e.message);
32
+ }
33
+ const setCookieHeader = await AUTH.getRefreshTokenSetCookie(null);
34
+ return new Response("Temporary Redirect", {
35
+ status: 307,
36
+ headers: {
37
+ "Set-Cookie": setCookieHeader,
38
+ Location: arg.request.url,
39
+ },
40
+ });
41
+ }
42
+ }
43
+ return fn(undefined)(arg);
44
+ };
45
+ };
46
+ }
package/dist/cjs/cn.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cn = cn;
4
+ function cn(...classes) {
5
+ return classes.filter(Boolean).join(" ").trim();
6
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./modal"), exports);
18
+ __exportStar(require("./styles"), exports);
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.default = FullscreenContainer;
18
+ exports.useFullscreen = useFullscreen;
19
+ const cn_1 = require("../../cn");
20
+ const react_1 = __importDefault(require("react"));
21
+ const react_2 = require("react");
22
+ function FullscreenContainer(_a) {
23
+ var { className, children } = _a, props = __rest(_a, ["className", "children"]);
24
+ const containerRef = (0, react_2.useRef)(null);
25
+ useFullscreen(containerRef);
26
+ return (react_1.default.createElement("div", Object.assign({ ref: containerRef }, props, { className: (0, cn_1.cn)("fixed left-0 right-0 top-0 bottom-0", className) }), children));
27
+ }
28
+ function useFullscreen(ref) {
29
+ (0, react_2.useEffect)(() => {
30
+ const container = ref.current;
31
+ if (!container) {
32
+ return;
33
+ }
34
+ const scroll = () => {
35
+ if (scrollY > 0) {
36
+ window.scrollTo({
37
+ top: 0,
38
+ behavior: "instant",
39
+ });
40
+ }
41
+ };
42
+ const resize = () => {
43
+ if (!visualViewport) {
44
+ return;
45
+ }
46
+ container.classList.remove("bottom-0");
47
+ container.style.height = `${visualViewport === null || visualViewport === void 0 ? void 0 : visualViewport.height}px`;
48
+ if (visualViewport.height < window.innerHeight) {
49
+ window.addEventListener("scroll", scroll);
50
+ }
51
+ else {
52
+ window.removeEventListener("scroll", scroll);
53
+ }
54
+ };
55
+ resize();
56
+ visualViewport === null || visualViewport === void 0 ? void 0 : visualViewport.addEventListener("resize", resize);
57
+ scroll();
58
+ return () => {
59
+ window.removeEventListener("scroll", scroll);
60
+ visualViewport === null || visualViewport === void 0 ? void 0 : visualViewport.removeEventListener("resize", resize);
61
+ };
62
+ }, [ref]);
63
+ return "fixed inset-0";
64
+ }