diff --git a/apps/client/src/pages/onBoarding/GoogleCallback.tsx b/apps/client/src/pages/onBoarding/GoogleCallback.tsx index a742e7fe..b4d03e64 100644 --- a/apps/client/src/pages/onBoarding/GoogleCallback.tsx +++ b/apps/client/src/pages/onBoarding/GoogleCallback.tsx @@ -46,9 +46,7 @@ const GoogleCallback = () => { } }; - const redirectUri = import.meta.env.PROD - ? import.meta.env.VITE_GOOGLE_REDIRECT_URI_PROD - : import.meta.env.VITE_GOOGLE_REDIRECT_URI_DEV; + const redirectUri = import.meta.env.VITE_GOOGLE_REDIRECT_URI; const loginWithCode = async (code: string) => { try { diff --git a/apps/client/src/shared/utils/handleGoogleLogin.ts b/apps/client/src/shared/utils/handleGoogleLogin.ts index 8b0ff14b..f70ac974 100644 --- a/apps/client/src/shared/utils/handleGoogleLogin.ts +++ b/apps/client/src/shared/utils/handleGoogleLogin.ts @@ -1,14 +1,13 @@ export const handleGoogleLogin = () => { const clientId = import.meta.env.VITE_GOOGLE_CLIENT_ID; - const redirectUri = import.meta.env.PROD - ? import.meta.env.VITE_GOOGLE_REDIRECT_URI_PROD - : import.meta.env.VITE_GOOGLE_REDIRECT_URI_DEV; + const redirectUri = import.meta.env.VITE_GOOGLE_REDIRECT_URI; if (!clientId || !redirectUri) { alert('Google OAuth 설정이 누락되었습니다.'); return; } + const googleAuthUrl = `https://accounts.google.com/o/oauth2/v2/auth?` + `client_id=${clientId}` + diff --git a/apps/extension/.gitignore b/apps/extension/.gitignore index 800f3a80..7a22cca6 100644 --- a/apps/extension/.gitignore +++ b/apps/extension/.gitignore @@ -15,8 +15,10 @@ # misc .DS_Store .env.local +.env.development .env.development.local .env.test.local +.env.production .env.production.local npm-debug.log* diff --git a/apps/extension/manifest.json b/apps/extension/manifest.json index f0b3aa5a..9ae1f400 100644 --- a/apps/extension/manifest.json +++ b/apps/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Pinback 핀백 - 북마크 관리와 리마인드 도구", - "version": "1.0.2", + "version": "1.0.3", "action": { "default_popup": "popup.html" }, "icons": { "128": "icon.png", diff --git a/apps/extension/package.json b/apps/extension/package.json index f1f7715f..84779808 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -4,11 +4,13 @@ "private": true, "type": "module", "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", + "dev": "vite --mode development", + "build": "pnpm build:prod", + "build:dev": "tsc -b && vite build --mode development", + "build:prod": "tsc -b && vite build --mode production", "lint": "eslint .", "format": "prettier -w .", - "zip": "vite build && node scripts/zip.mjs" + "zip": "pnpm build:prod && node scripts/zip.mjs" }, "dependencies": { "@pinback/contracts": "workspace:*", diff --git a/apps/extension/src/background.ts b/apps/extension/src/background.ts index 42b17fcd..a089b710 100644 --- a/apps/extension/src/background.ts +++ b/apps/extension/src/background.ts @@ -1,5 +1,7 @@ import { EXTENSION_MESSAGE_TYPE } from '@pinback/contracts/extension-messages'; +const webUrl = import.meta.env.VITE_WEB_URL || 'https://pinback.today'; + chrome.runtime.onInstalled.addListener((details) => { if (details.reason === 'install') { chrome.identity.getProfileUserInfo(function (info) { @@ -8,7 +10,7 @@ chrome.runtime.onInstalled.addListener((details) => { }); setTimeout(() => { chrome.tabs.create({ - url: `https://pinback.today/onboarding?email=${info.email}`, + url: `${webUrl}/onboarding?email=${info.email}`, }); }, 1000); }); @@ -21,9 +23,7 @@ chrome.runtime.onMessage.addListener((message) => { console.log('Token saved!'); }); } -}); -chrome.runtime.onMessage.addListener((message) => { if (message.type === EXTENSION_MESSAGE_TYPE.logout) { chrome.storage.local.remove('token', () => { console.log('Token removed!'); diff --git a/apps/extension/src/content.ts b/apps/extension/src/content.ts index 92002d60..30dd9146 100644 --- a/apps/extension/src/content.ts +++ b/apps/extension/src/content.ts @@ -1,23 +1,35 @@ import { EXTENSION_MESSAGE_TYPE } from '@pinback/contracts/extension-messages'; +const ALLOWED_ORIGINS = __ALLOWED_ORIGINS__; + +if (ALLOWED_ORIGINS.length === 0) { + console.warn( + '[Pinback] 허용된 도메인(ALLOWED_ORIGINS) 설정이 비어 있습니다. 토큰 동기화가 작동하지 않으니 .env 파일을 확인해주세요.' + ); +} + window.addEventListener('message', (event) => { if (event.source !== window) return; - if (event.data.type === EXTENSION_MESSAGE_TYPE.setToken) { + + if (!ALLOWED_ORIGINS.includes(event.origin)) return; + + const { type, token } = event.data; + + if (type === EXTENSION_MESSAGE_TYPE.setToken) { chrome.runtime.sendMessage({ type: EXTENSION_MESSAGE_TYPE.setToken, - token: event.data.token, + token, }); - chrome.storage.local.set({ token: event.data.token }, () => { - console.log('Token saved!'); + + chrome.storage.local.set({ token }, () => { + console.log(`[${event.origin}] Token saved!`); }); } -}); -window.addEventListener('message', (event) => { - if (event.source !== window) return; - if (event.data.type === EXTENSION_MESSAGE_TYPE.logout) { + // 토큰 삭제 (로그아웃) + if (type === EXTENSION_MESSAGE_TYPE.logout) { chrome.storage.local.remove('token', () => { - console.log('Token removed!'); + console.log(`[${event.origin}] Token removed!`); }); } }); diff --git a/apps/extension/src/pages/LogOutPop.tsx b/apps/extension/src/pages/LogOutPop.tsx index c515a224..4f8f2e97 100644 --- a/apps/extension/src/pages/LogOutPop.tsx +++ b/apps/extension/src/pages/LogOutPop.tsx @@ -1,6 +1,8 @@ import { Icon } from '@pinback/design-system/icons'; import LogOutImg from '/logout_chippi.svg'; const LogOutPop = () => { + const webUrl = import.meta.env.VITE_WEB_URL || 'https://pinback.today'; + return (
@@ -25,7 +27,7 @@ const LogOutPop = () => { type="button" onClick={() => { chrome.tabs.create({ - url: 'https://pinback.today/onboarding?step=SOCIAL_LOGIN', + url: `${webUrl}/onboarding?step=SOCIAL_LOGIN`, }); }} > diff --git a/apps/extension/src/vite-env.d.ts b/apps/extension/src/vite-env.d.ts new file mode 100644 index 00000000..ffefc447 --- /dev/null +++ b/apps/extension/src/vite-env.d.ts @@ -0,0 +1,3 @@ +/// + +declare const __ALLOWED_ORIGINS__: string[]; diff --git a/apps/extension/vite.config.ts b/apps/extension/vite.config.ts index 84ab1ff4..c1c3d914 100644 --- a/apps/extension/vite.config.ts +++ b/apps/extension/vite.config.ts @@ -1,36 +1,50 @@ -// vite.config.ts -import { defineConfig } from 'vite'; +import { crx } from '@crxjs/vite-plugin'; +import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite'; import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react-swc'; -import tsconfigPaths from 'vite-tsconfig-paths'; import { resolve } from 'path'; -import { crx } from '@crxjs/vite-plugin'; +import { defineConfig, loadEnv } from 'vite'; +import tsconfigPaths from 'vite-tsconfig-paths'; import manifest from './manifest.json'; -import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite'; -export default defineConfig({ - plugins: [ - react(), - tsconfigPaths({ - projects: [resolve(__dirname, './tsconfig.json')], - }), - tailwindcss(), - crx({ manifest }), - svgSpritePlugin({ - iconDirs: ['../../packages/design-system/src/icons/source'], - symbolId: 'icon-[name]', - inject: 'body-last', - }), - ], +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd()); + + const dynamicManifest = { + ...manifest, + name: env.VITE_EXTENSION_NAME || manifest.name, + }; + + return { + define: { + __ALLOWED_ORIGINS__: JSON.stringify( + env.VITE_ALLOWED_ORIGINS?.split(',').filter(Boolean) || [] + ), + }, + + plugins: [ + react(), + tsconfigPaths({ + projects: [resolve(__dirname, './tsconfig.json')], + }), + tailwindcss(), + crx({ manifest: dynamicManifest }), + svgSpritePlugin({ + iconDirs: ['../../packages/design-system/src/icons/source'], + symbolId: 'icon-[name]', + inject: 'body-last', + }), + ], - build: { - outDir: 'dist', - copyPublicDir: true, - }, - publicDir: 'public', + build: { + outDir: 'dist', + copyPublicDir: true, + }, + publicDir: 'public', - server: { - port: 5175, - strictPort: true, - }, + server: { + port: 5175, + strictPort: true, + }, + }; }); diff --git a/package.json b/package.json index b4d1c485..73cec766 100644 --- a/package.json +++ b/package.json @@ -3,14 +3,16 @@ "private": true, "scripts": { "build": "turbo run build", + "build:dev": "turbo run build:dev --filter=@pinback/extension", + "build:prod": "turbo run build:prod --filter=@pinback/extension", + "build-storybook": "storybook build", "dev": "turbo run dev", "dev:client": "turbo run dev --filter=@pinback/client", + "storybook": "storybook dev -p 6006", "lint": "turbo run lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"", "check-types": "turbo run check-types", - "test": "turbo run test", - "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "test": "turbo run test" }, "devDependencies": { "@chromatic-com/storybook": "^4.1.1", diff --git a/turbo.json b/turbo.json index e8616fb8..f040fdaa 100644 --- a/turbo.json +++ b/turbo.json @@ -7,6 +7,17 @@ "inputs": ["$TURBO_DEFAULT$", ".env*", "!.env.sample"], "outputs": [".next/**", "!.next/cache/**", "dist/**"] }, + + "build:dev": { + "dependsOn": ["^build"], + "inputs": ["$TURBO_DEFAULT$", ".env*", "!.env.sample"], + "outputs": ["dist/**"] + }, + "build:prod": { + "dependsOn": ["^build"], + "inputs": ["$TURBO_DEFAULT$", ".env*", "!.env.sample"], + "outputs": ["dist/**"] + }, "dev": { "cache": false, "persistent": true