{"_id":"@astralweb/nova-recently-viewed-product","_rev":"3-ff6895cdc49247cb4efeaecd081142eb","name":"@astralweb/nova-recently-viewed-product","dist-tags":{"latest":"0.0.3"},"versions":{"0.0.1":{"name":"@astralweb/nova-recently-viewed-product","version":"0.0.1","keywords":["recently-viewed-product","magento","nuxt-module"],"author":{"name":"Astral Web"},"license":"Proprietary","_id":"@astralweb/nova-recently-viewed-product@0.0.1","maintainers":[{"name":"jimsu","email":"jim@astralwebinc.com"},{"name":"astralweb-darren","email":"darren@astralwebinc.com"},{"name":"infoaw","email":"info@astralwebinc.com"}],"homepage":"https://github.com/AstralWebTW/nova-packages/tree/main/packages/recently-viewed-product","bugs":{"url":"https://github.com/AstralWebTW/nova-packages/issues"},"dist":{"shasum":"030bb8d0a35fa616cf859903a35e02bbc16826b9","tarball":"https://registry.npmjs.org/@astralweb/nova-recently-viewed-product/-/nova-recently-viewed-product-0.0.1.tgz","fileCount":28,"integrity":"sha512-EyhNgx+YPknt/gK1thmKMFBeVNlPM/mYtJnDF/Qzn6u1pTXio2C96KA56oGUvbSAb4g/dTyMfvoNpf3nOvv4jg==","signatures":[{"sig":"MEYCIQDH3MOu8whPz6OHGIajDFSvdIIHENZUgmdxNPgGrTUkiAIhAPMUMVA8NaFv5qnpXSP+o3rw4MC5OkLMUVOpcxwnR+Rl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18550},"main":"./dist/module.mjs","type":"module","_from":"file:astralweb-nova-recently-viewed-product-0.0.1.tgz","engines":{"node":">=20.0.0","pnpm":">=10.0.0"},"exports":{".":{"types":"./dist/module.d.mts","import":"./dist/module.mjs"},"./api":{"types":"./dist/runtime/api/index.d.ts","import":"./dist/runtime/api/index.js"},"./composables":{"types":"./dist/runtime/composables/index.d.ts","import":"./dist/runtime/composables/index.js"}},"scripts":{"dev":"pnpm run dev:prepare && nuxi dev playground","lint":"eslint .","test":"vitest run","build":"nuxt-module-build build","lint:fix":"eslint . --fix","dev:build":"nuxi build playground","typecheck":"tsc --noEmit","test:types":"vue-tsc --noEmit && cd playground && vue-tsc --noEmit","test:watch":"vitest watch","dev:prepare":"nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground","dev:preview":"nuxi preview playground --port 3001","build:prepare":"nuxt-module-build prepare && nuxi prepare playground"},"_npmUser":{"name":"infoaw","email":"info@astralwebinc.com"},"_resolved":"/tmp/cf0c70b2aadc2b28681ad7b648e681f9/astralweb-nova-recently-viewed-product-0.0.1.tgz","_integrity":"sha512-EyhNgx+YPknt/gK1thmKMFBeVNlPM/mYtJnDF/Qzn6u1pTXio2C96KA56oGUvbSAb4g/dTyMfvoNpf3nOvv4jg==","repository":{"url":"git+https://github.com/AstralWebTW/nova-packages.git","type":"git","directory":"packages/recently-viewed-product"},"_npmVersion":"10.8.2","description":"Recently Viewed Product module for Nova e-commerce platform (Internal Use Only)","directories":{},"_nodeVersion":"20.19.5","dependencies":{"@nuxt/kit":"^4.1.3"},"typesVersions":{"*":{".":["./dist/types.d.mts"]}},"_hasShrinkwrap":false,"devDependencies":{"nuxt":"^4.1.3","eslint":"^9.37.0","vitest":"^3.2.4","vue-tsc":"^3.1.1","typescript":"^5.9.3","@types/node":"latest","@nuxt/schema":"^4.1.3","@nuxt/devtools":"^2.6.5","@nuxt/test-utils":"^3.19.2","@nuxt/eslint-config":"^1.9.0","@nuxt/module-builder":"^1.0.2","@astralweb/eslint-config":"1.0.6"},"peerDependencies":{"nuxt":"^3.0.0 || ^4.0.0","@vue-storefront/sdk":"^3.2.0","@vue-storefront/middleware":"^5.4.0","@vue-storefront/magento-api":"^6.3.0"},"_npmOperationalInternal":{"tmp":"tmp/nova-recently-viewed-product_0.0.1_1761731593730_0.4486167847118978","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@astralweb/nova-recently-viewed-product","version":"0.0.2","keywords":["recently-viewed-product","magento","nuxt-module"],"author":{"name":"Astral Web"},"license":"Proprietary","_id":"@astralweb/nova-recently-viewed-product@0.0.2","maintainers":[{"name":"jimsu","email":"jim@astralwebinc.com"},{"name":"astralweb-darren","email":"darren@astralwebinc.com"},{"name":"infoaw","email":"info@astralwebinc.com"}],"homepage":"https://github.com/AstralWebTW/nova-packages/tree/main/packages/recently-viewed-product","bugs":{"url":"https://github.com/AstralWebTW/nova-packages/issues"},"dist":{"shasum":"25dbe6df16e056fc2d0de1f0f55706f5f5ee7141","tarball":"https://registry.npmjs.org/@astralweb/nova-recently-viewed-product/-/nova-recently-viewed-product-0.0.2.tgz","fileCount":30,"integrity":"sha512-JRfAOZshkm4KoqrcFyNX55bDMKLGAnCOKXoWKtkqY5BlBZJrtRJmCQJCM0Kb1frWvYbl9vDBb083Nyq5SNUazw==","signatures":[{"sig":"MEYCIQD2PWlOUHDTmnna0olAlQADLG1Xe5m4zqRuZ5J1U09LygIhAPXHPjOHp3ZUfGlewC6TI2v8F3bEZXKUeU91PX1uA4f7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":22294},"main":"./dist/module.mjs","type":"module","_from":"file:astralweb-nova-recently-viewed-product-0.0.2.tgz","engines":{"node":">=20.0.0","pnpm":">=10.0.0"},"exports":{".":{"types":"./dist/module.d.mts","import":"./dist/module.mjs"},"./api":{"types":"./dist/runtime/api/index.d.ts","import":"./dist/runtime/api/index.js"},"./composables":{"types":"./dist/runtime/composables/index.d.ts","import":"./dist/runtime/composables/index.js"}},"scripts":{"dev":"pnpm run dev:prepare && nuxi dev playground","lint":"eslint .","test":"vitest run","build":"nuxt-module-build build","lint:fix":"eslint . --fix","dev:build":"nuxi build playground","typecheck":"tsc --noEmit","test:types":"vue-tsc --noEmit && cd playground && vue-tsc --noEmit","test:watch":"vitest watch","dev:prepare":"nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground","dev:preview":"nuxi preview playground --port 3001","build:prepare":"nuxt-module-build prepare && nuxi prepare playground"},"_npmUser":{"name":"infoaw","email":"info@astralwebinc.com"},"_resolved":"/tmp/46e262a38d52fd3b4487f9e022d05f8e/astralweb-nova-recently-viewed-product-0.0.2.tgz","_integrity":"sha512-JRfAOZshkm4KoqrcFyNX55bDMKLGAnCOKXoWKtkqY5BlBZJrtRJmCQJCM0Kb1frWvYbl9vDBb083Nyq5SNUazw==","repository":{"url":"git+https://github.com/AstralWebTW/nova-packages.git","type":"git","directory":"packages/recently-viewed-product"},"_npmVersion":"10.8.2","description":"Recently Viewed Product module for Nova e-commerce platform (Internal Use Only)","directories":{},"_nodeVersion":"20.19.5","dependencies":{"@nuxt/kit":"^4.1.3"},"typesVersions":{"*":{".":["./dist/types.d.mts"]}},"_hasShrinkwrap":false,"devDependencies":{"nuxt":"^4.1.3","eslint":"^9.37.0","vitest":"^3.2.4","vue-tsc":"^3.1.1","typescript":"^5.9.3","@types/node":"latest","@nuxt/schema":"^4.1.3","@nuxt/devtools":"^2.6.5","@nuxt/test-utils":"^3.19.2","@nuxt/eslint-config":"^1.9.0","@nuxt/module-builder":"^1.0.2","@astralweb/eslint-config":"1.0.6"},"peerDependencies":{"nuxt":"^3.0.0 || ^4.0.0","@vue-storefront/sdk":"^3.2.0","@vue-storefront/middleware":"^5.4.0","@vue-storefront/magento-api":"^6.3.0"},"_npmOperationalInternal":{"tmp":"tmp/nova-recently-viewed-product_0.0.2_1762160464853_0.9512053225112649","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@astralweb/nova-recently-viewed-product","version":"0.0.3","description":"Recently Viewed Product module for Nova e-commerce platform (Internal Use Only)","license":"Proprietary","type":"module","exports":{".":{"types":"./dist/module.d.mts","import":"./dist/module.mjs"},"./api":{"types":"./dist/runtime/api/index.d.ts","import":"./dist/runtime/api/index.js"},"./composables":{"types":"./dist/runtime/composables/index.d.ts","import":"./dist/runtime/composables/index.js"}},"main":"./dist/module.mjs","typesVersions":{"*":{".":["./dist/types.d.mts"]}},"dependencies":{"@nuxt/kit":"^4.1.3"},"peerDependencies":{"@vue-storefront/magento-api":"^6.3.0","@vue-storefront/middleware":"^5.4.0","@vue-storefront/sdk":"^3.2.0","nuxt":"^3.0.0 || ^4.0.0"},"devDependencies":{"@nuxt/devtools":"^2.6.5","@nuxt/eslint-config":"^1.9.0","@nuxt/module-builder":"^1.0.2","@nuxt/schema":"^4.1.3","@nuxt/test-utils":"^3.19.2","@types/node":"latest","eslint":"^9.37.0","nuxt":"^4.1.3","typescript":"^5.9.3","vitest":"^3.2.4","vue-tsc":"^3.1.1","@astralweb/eslint-config":"1.0.6"},"repository":{"type":"git","url":"git+https://github.com/AstralWebTW/nova-packages.git","directory":"packages/recently-viewed-product"},"keywords":["recently-viewed-product","magento","nuxt-module"],"author":{"name":"Astral Web"},"homepage":"https://github.com/AstralWebTW/nova-packages/tree/main/packages/recently-viewed-product","engines":{"node":">=20.0.0","pnpm":">=10.0.0"},"scripts":{"build:prepare":"nuxt-module-build prepare && nuxi prepare playground","build":"nuxt-module-build build","dev":"pnpm run dev:prepare && nuxi dev playground","dev:build":"nuxi build playground","dev:preview":"nuxi preview playground --port 3001","dev:prepare":"nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground","typecheck":"tsc --noEmit","lint":"eslint .","lint:fix":"eslint . --fix","test":"vitest run","test:watch":"vitest watch","test:types":"vue-tsc --noEmit && cd playground && vue-tsc --noEmit"},"_id":"@astralweb/nova-recently-viewed-product@0.0.3","bugs":{"url":"https://github.com/AstralWebTW/nova-packages/issues"},"_integrity":"sha512-fslkG7CtGFrJNXp4UdUziuiif7f/uFzfQRq0SwDfnj4Ne/sKDktrD06PdxQ/o40RrmH612vGMtOE25TDid2RcQ==","_resolved":"/tmp/efafd350ce6fcf1202caebc89c031a9c/astralweb-nova-recently-viewed-product-0.0.3.tgz","_from":"file:astralweb-nova-recently-viewed-product-0.0.3.tgz","_nodeVersion":"20.19.5","_npmVersion":"10.8.2","dist":{"integrity":"sha512-fslkG7CtGFrJNXp4UdUziuiif7f/uFzfQRq0SwDfnj4Ne/sKDktrD06PdxQ/o40RrmH612vGMtOE25TDid2RcQ==","shasum":"ca8d306ebbee46fd1e4fcacae5183a3eec416f17","tarball":"https://registry.npmjs.org/@astralweb/nova-recently-viewed-product/-/nova-recently-viewed-product-0.0.3.tgz","fileCount":30,"unpackedSize":22329,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDmvMT3ok9SRawQflA2PYitkLNGmr4DtA5FNxqOZt80/wIgbv8SjOZ4KEGe38SKwPOEvAxVXDZzsE3mfRdnD49iwZ8="}]},"_npmUser":{"name":"infoaw","email":"info@astralwebinc.com"},"directories":{},"maintainers":[{"name":"jimsu","email":"jim@astralwebinc.com"},{"name":"astralweb-darren","email":"darren@astralwebinc.com"},{"name":"infoaw","email":"info@astralwebinc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nova-recently-viewed-product_0.0.3_1762164709481_0.9084625902294945"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-29T09:53:13.659Z","modified":"2025-11-03T10:11:49.927Z","0.0.1":"2025-10-29T09:53:13.913Z","0.0.2":"2025-11-03T09:01:05.046Z","0.0.3":"2025-11-03T10:11:49.667Z"},"bugs":{"url":"https://github.com/AstralWebTW/nova-packages/issues"},"author":{"name":"Astral Web"},"license":"Proprietary","homepage":"https://github.com/AstralWebTW/nova-packages/tree/main/packages/recently-viewed-product","keywords":["recently-viewed-product","magento","nuxt-module"],"repository":{"type":"git","url":"git+https://github.com/AstralWebTW/nova-packages.git","directory":"packages/recently-viewed-product"},"description":"Recently Viewed Product module for Nova e-commerce platform (Internal Use Only)","maintainers":[{"name":"jimsu","email":"jim@astralwebinc.com"},{"name":"astralweb-darren","email":"darren@astralwebinc.com"},{"name":"infoaw","email":"info@astralwebinc.com"}],"readme":"# Recently Viewed Product 模組使用指南\n\n> ⚠️ **內部使用套件** - 此套件僅供 Astral Web 內部使用，未經授權不得用於其他用途。\n\n## 概覽\n\nRecently Viewed Product 是一個 Nuxt 3 模組，提供完整的最近瀏覽商品追蹤與管理功能。模組採用 Nuxt Module 架構設計，支援本地儲存與伺服器同步、訪客與會員資料自動合併，並提供靈活的配置選項。\n\n## 安裝與設定\n\n### 1. 安裝套件\n\n#### 在 apps/web 和 apps/server 安裝\n\n```bash\nyarn add @astralweb/nova-recently-viewed-product\n```\n\n### 2. Middleware 擴充\n\n```typescript\n// apps/server/extendApiMethods/index.ts\n\nexport {\n  recentlyViewedProducts,\n  addRecentlyViewedProducts,\n} from '@astralweb/nova-recently-viewed-product/api';\n```\n\n### 3. 註冊模組\n\n```typescript\n// apps/web/nuxt.config.ts\n\nexport default defineNuxtConfig({\n  modules: [\n    '@astralweb/nova-recently-viewed-product',\n  ],\n})\n```\n\n## 架構設計\n\n### 三層架構\n\n1. **API Layer** (`useRecentlyViewedApi`)\n   - 處理與 GraphQL 後端的通信\n   - 提供 `syncToServer` 和 `fetchFromServer` 方法\n\n2. **Storage Layer** (`useRecentlyViewedStorage`)\n   - 管理本地儲存與核心業務邏輯\n   - 處理訪客/會員資料合併\n   - 提供完整的 CRUD 操作\n\n3. **List Layer** (`useRecentlyViewedList`)\n   - 高階封裝，適用於產品詳情頁\n   - 自動處理初始化、登入狀態變化、SKU 更新\n   - 提供開箱即用的體驗\n\n## 使用方式\n\n適合產品詳情頁，自動處理所有邏輯。\n\n```vue\n<template>\n  <ProductSlider :products-sku=\"recentlyViewedSkus\" />\n</template>\n\n<script setup lang=\"ts\">\nconst { recentlyViewedSkus } = useRecentlyViewedList({\n  currentSku: computed(() => product.value?.sku ?? ''),\n  isLoggedIn: computed(() => !!user.value),\n  enableServerSync: true,\n});\n</script>\n```\n\n**自動處理：**\n- ✅ 組件掛載時初始化\n- ✅ SKU 變化時更新列表\n- ✅ 登入狀態變化時合併資料\n- ✅ 本地緩存優化\n\n\n## API 參考\n\n### useRecentlyViewedList\n\n```typescript\nconst { recentlyViewedSkus } = useRecentlyViewedList({\n  currentSku: Ref<string> | ComputedRef<string>,\n  isLoggedIn: ComputedRef<boolean>,\n  maxItems?: number,              // 預設：20\n  guestStorageKey?: string,       // 預設：'recently-viewed-guest'\n  customerStorageKey?: string,    // 預設：'recently-viewed-customer'\n  enableServerSync?: boolean,     // 預設：true\n  autoInit?: boolean,             // 預設：true\n});\n```\n\n**返回值：**\n- `recentlyViewedSkus`: `Ref<string[]>` - 最近瀏覽商品的 SKU 列表\n\n### useRecentlyViewedStorage\n\n核心 composable，提供完整的儲存管理功能。\n\n```typescript\nconst {\n  addRecentlyViewed,\n  getRecentlyViewedSkus,\n  getSkusFromLocalStorage,\n  clearAllRecentlyViewed,\n  mergeGuestToCustomer,\n  isLoggedIn,\n} = useRecentlyViewedStorage(config, isLoggedIn);\n```\n\n**配置選項：**\n```typescript\ninterface RecentlyViewedConfig {\n  maxItems?: number;              // 最多儲存數量（預設：20）\n  guestStorageKey?: string;       // 訪客 localStorage key\n  customerStorageKey?: string;    // 會員 localStorage key\n  enableServerSync?: boolean;     // 啟用伺服器同步（預設：true）\n}\n```\n\n**方法：**\n- `addRecentlyViewed(sku: string): Promise<void>` - 添加商品到最近瀏覽\n- `getRecentlyViewedSkus(excludeSku?: string): Promise<string[]>` - 獲取 SKU 列表（伺服器優先）\n- `getSkusFromLocalStorage(excludeSku?: string): string[]` - 從本地儲存獲取 SKU 列表\n- `clearAllRecentlyViewed(): void` - 清除所有記錄\n- `mergeGuestToCustomer(): Promise<void>` - 合併訪客資料到會員帳戶\n\n### useRecentlyViewedApi\n\nAPI 層 composable，處理與後端的通信。\n\n```typescript\nconst {\n  syncToServer,\n  fetchFromServer,\n} = useRecentlyViewedApi();\n```\n\n**方法：**\n- `syncToServer(input: AddRecentlyViewedInputItem[]): Promise<void>` - 同步資料到伺服器\n- `fetchFromServer(): Promise<AddRecentlyViewedInputItem[]>` - 從伺服器獲取資料\n\n## 工作原理\n\n### 訪客模式\n\n- 資料保存在 `localStorage`（key: `recently-viewed-guest`）\n- 不進行伺服器同步\n- 本地去重與數量限制\n\n### 登入模式\n\n- 主要資料來源：伺服器\n- 本地緩存：加速 UI 更新\n- 新增時：同步到伺服器 → 更新本地緩存\n\n### 登入時資料合併\n\n1. 讀取訪客 `localStorage` 資料\n2. 同步到伺服器（合併到會員帳戶）\n3. 清除訪客資料\n4. 從伺服器獲取最新資料\n\n## 授權\n\n此套件僅供 Astral Web 內部使用，未經授權不得用於其他用途。\n","readmeFilename":"README.md"}