Skip to content

Commit a122099

Browse files
Feat(extension, client): separate extension send token environment (#319)
* feat: VITE_GOOGLE_REDIRECT_URI 하나로 통합 * feat: extension build dev와 prod 환경 분리하도록 script, turbo.json 설정 * feat: extension build 시점에 dev, prod가 name env 기준으로 나뉘도록 앱 분리 설정 * feat: extension login popup 창 열릴 때 dev, prod 환경 분리되도록 동적 url 변수 설정 * feat: extension background webUrl 설정 시 동적으로 분기로직 추가 * setting: update extension version to 1.0.3 * fix: build script 패키지 매니저 yarn에서 pnpm으로 수정 * refactor: ALLOWED_ORIGINS 없는 경우 예외처리 추가 * refactor: split(,)에 따라 [] 배열 생성으로 인한 엣지 케이스 에러 방지 로직 추가
1 parent 06cc804 commit a122099

File tree

12 files changed

+99
-54
lines changed

12 files changed

+99
-54
lines changed

apps/client/src/pages/onBoarding/GoogleCallback.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ const GoogleCallback = () => {
4646
}
4747
};
4848

49-
const redirectUri = import.meta.env.PROD
50-
? import.meta.env.VITE_GOOGLE_REDIRECT_URI_PROD
51-
: import.meta.env.VITE_GOOGLE_REDIRECT_URI_DEV;
49+
const redirectUri = import.meta.env.VITE_GOOGLE_REDIRECT_URI;
5250

5351
const loginWithCode = async (code: string) => {
5452
try {

apps/client/src/shared/utils/handleGoogleLogin.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
export const handleGoogleLogin = () => {
22
const clientId = import.meta.env.VITE_GOOGLE_CLIENT_ID;
33

4-
const redirectUri = import.meta.env.PROD
5-
? import.meta.env.VITE_GOOGLE_REDIRECT_URI_PROD
6-
: import.meta.env.VITE_GOOGLE_REDIRECT_URI_DEV;
4+
const redirectUri = import.meta.env.VITE_GOOGLE_REDIRECT_URI;
75

86
if (!clientId || !redirectUri) {
97
alert('Google OAuth 설정이 누락되었습니다.');
108
return;
119
}
10+
1211
const googleAuthUrl =
1312
`https://accounts.google.com/o/oauth2/v2/auth?` +
1413
`client_id=${clientId}` +

apps/extension/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
# misc
1616
.DS_Store
1717
.env.local
18+
.env.development
1819
.env.development.local
1920
.env.test.local
21+
.env.production
2022
.env.production.local
2123

2224
npm-debug.log*

apps/extension/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "Pinback 핀백 - 북마크 관리와 리마인드 도구",
4-
"version": "1.0.2",
4+
"version": "1.0.3",
55
"action": { "default_popup": "popup.html" },
66
"icons": {
77
"128": "icon.png",

apps/extension/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
"private": true,
55
"type": "module",
66
"scripts": {
7-
"dev": "vite",
8-
"build": "tsc -b && vite build",
7+
"dev": "vite --mode development",
8+
"build": "pnpm build:prod",
9+
"build:dev": "tsc -b && vite build --mode development",
10+
"build:prod": "tsc -b && vite build --mode production",
911
"lint": "eslint .",
1012
"format": "prettier -w .",
11-
"zip": "vite build && node scripts/zip.mjs"
13+
"zip": "pnpm build:prod && node scripts/zip.mjs"
1214
},
1315
"dependencies": {
1416
"@pinback/contracts": "workspace:*",

apps/extension/src/background.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { EXTENSION_MESSAGE_TYPE } from '@pinback/contracts/extension-messages';
22

3+
const webUrl = import.meta.env.VITE_WEB_URL || 'https://pinback.today';
4+
35
chrome.runtime.onInstalled.addListener((details) => {
46
if (details.reason === 'install') {
57
chrome.identity.getProfileUserInfo(function (info) {
@@ -8,7 +10,7 @@ chrome.runtime.onInstalled.addListener((details) => {
810
});
911
setTimeout(() => {
1012
chrome.tabs.create({
11-
url: `https://pinback.today/onboarding?email=${info.email}`,
13+
url: `${webUrl}/onboarding?email=${info.email}`,
1214
});
1315
}, 1000);
1416
});
@@ -21,9 +23,7 @@ chrome.runtime.onMessage.addListener((message) => {
2123
console.log('Token saved!');
2224
});
2325
}
24-
});
2526

26-
chrome.runtime.onMessage.addListener((message) => {
2727
if (message.type === EXTENSION_MESSAGE_TYPE.logout) {
2828
chrome.storage.local.remove('token', () => {
2929
console.log('Token removed!');

apps/extension/src/content.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
import { EXTENSION_MESSAGE_TYPE } from '@pinback/contracts/extension-messages';
22

3+
const ALLOWED_ORIGINS = __ALLOWED_ORIGINS__;
4+
5+
if (ALLOWED_ORIGINS.length === 0) {
6+
console.warn(
7+
'[Pinback] 허용된 도메인(ALLOWED_ORIGINS) 설정이 비어 있습니다. 토큰 동기화가 작동하지 않으니 .env 파일을 확인해주세요.'
8+
);
9+
}
10+
311
window.addEventListener('message', (event) => {
412
if (event.source !== window) return;
5-
if (event.data.type === EXTENSION_MESSAGE_TYPE.setToken) {
13+
14+
if (!ALLOWED_ORIGINS.includes(event.origin)) return;
15+
16+
const { type, token } = event.data;
17+
18+
if (type === EXTENSION_MESSAGE_TYPE.setToken) {
619
chrome.runtime.sendMessage({
720
type: EXTENSION_MESSAGE_TYPE.setToken,
8-
token: event.data.token,
21+
token,
922
});
10-
chrome.storage.local.set({ token: event.data.token }, () => {
11-
console.log('Token saved!');
23+
24+
chrome.storage.local.set({ token }, () => {
25+
console.log(`[${event.origin}] Token saved!`);
1226
});
1327
}
14-
});
1528

16-
window.addEventListener('message', (event) => {
17-
if (event.source !== window) return;
18-
if (event.data.type === EXTENSION_MESSAGE_TYPE.logout) {
29+
// 토큰 삭제 (로그아웃)
30+
if (type === EXTENSION_MESSAGE_TYPE.logout) {
1931
chrome.storage.local.remove('token', () => {
20-
console.log('Token removed!');
32+
console.log(`[${event.origin}] Token removed!`);
2133
});
2234
}
2335
});

apps/extension/src/pages/LogOutPop.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Icon } from '@pinback/design-system/icons';
22
import LogOutImg from '/logout_chippi.svg';
33
const LogOutPop = () => {
4+
const webUrl = import.meta.env.VITE_WEB_URL || 'https://pinback.today';
5+
46
return (
57
<div className="bg-white-bg common-shadow flex h-[37.5rem] w-[35.2rem] flex-col items-center justify-center rounded-[1.2rem] px-[3.2rem] py-[2.4rem] leading-normal">
68
<div className="mr-auto">
@@ -25,7 +27,7 @@ const LogOutPop = () => {
2527
type="button"
2628
onClick={() => {
2729
chrome.tabs.create({
28-
url: 'https://pinback.today/onboarding?step=SOCIAL_LOGIN',
30+
url: `${webUrl}/onboarding?step=SOCIAL_LOGIN`,
2931
});
3032
}}
3133
>

apps/extension/src/vite-env.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/// <reference types="vite/client" />
2+
3+
declare const __ALLOWED_ORIGINS__: string[];

apps/extension/vite.config.ts

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,50 @@
1-
// vite.config.ts
2-
import { defineConfig } from 'vite';
1+
import { crx } from '@crxjs/vite-plugin';
2+
import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite';
33
import tailwindcss from '@tailwindcss/vite';
44
import react from '@vitejs/plugin-react-swc';
5-
import tsconfigPaths from 'vite-tsconfig-paths';
65
import { resolve } from 'path';
7-
import { crx } from '@crxjs/vite-plugin';
6+
import { defineConfig, loadEnv } from 'vite';
7+
import tsconfigPaths from 'vite-tsconfig-paths';
88
import manifest from './manifest.json';
9-
import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite';
109

11-
export default defineConfig({
12-
plugins: [
13-
react(),
14-
tsconfigPaths({
15-
projects: [resolve(__dirname, './tsconfig.json')],
16-
}),
17-
tailwindcss(),
18-
crx({ manifest }),
19-
svgSpritePlugin({
20-
iconDirs: ['../../packages/design-system/src/icons/source'],
21-
symbolId: 'icon-[name]',
22-
inject: 'body-last',
23-
}),
24-
],
10+
export default defineConfig(({ mode }) => {
11+
const env = loadEnv(mode, process.cwd());
12+
13+
const dynamicManifest = {
14+
...manifest,
15+
name: env.VITE_EXTENSION_NAME || manifest.name,
16+
};
17+
18+
return {
19+
define: {
20+
__ALLOWED_ORIGINS__: JSON.stringify(
21+
env.VITE_ALLOWED_ORIGINS?.split(',').filter(Boolean) || []
22+
),
23+
},
24+
25+
plugins: [
26+
react(),
27+
tsconfigPaths({
28+
projects: [resolve(__dirname, './tsconfig.json')],
29+
}),
30+
tailwindcss(),
31+
crx({ manifest: dynamicManifest }),
32+
svgSpritePlugin({
33+
iconDirs: ['../../packages/design-system/src/icons/source'],
34+
symbolId: 'icon-[name]',
35+
inject: 'body-last',
36+
}),
37+
],
2538

26-
build: {
27-
outDir: 'dist',
28-
copyPublicDir: true,
29-
},
30-
publicDir: 'public',
39+
build: {
40+
outDir: 'dist',
41+
copyPublicDir: true,
42+
},
43+
publicDir: 'public',
3144

32-
server: {
33-
port: 5175,
34-
strictPort: true,
35-
},
45+
server: {
46+
port: 5175,
47+
strictPort: true,
48+
},
49+
};
3650
});

0 commit comments

Comments
 (0)