Skip to content

Commit cd98172

Browse files
committed
chore: prepare extension for Chrome Web Store submission
- Fix description: include Perplexity, 100% local message, 128-char limit - Remove unused 'cookies' permission (CWS rejects unnecessary sensitive perms) - Remove dead getCookie helper (no caller; matched the permission removal) - Open welcome page (migrate.hacklm.dev/aichatbackup/welcome) on fresh install - Fix all UI copy that omitted Perplexity (popup hint, options empty state) - Add scripts/zip.mjs: packages dist/ into CWS-ready ZIP via PowerShell - Add 'zip' and 'build:zip' npm scripts - Gitignore dist.pem (extension signing key)
1 parent bc9e946 commit cd98172

File tree

8 files changed

+74
-15
lines changed

8 files changed

+74
-15
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ dist/
77

88
*storybook.log
99
storybook-static
10+
dist.pem

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"dev": "vite",
88
"build": "tsc && vite build",
99
"preview": "vite preview",
10-
"gen-icons": "node scripts/gen-icons.mjs"
10+
"gen-icons": "node scripts/gen-icons.mjs",
11+
"zip": "node scripts/zip.mjs",
12+
"build:zip": "npm run build && npm run zip"
1113
},
1214
"keywords": [
1315
"chrome-extension",

scripts/zip.mjs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* scripts/zip.mjs
3+
*
4+
* Packages the dist/ folder into a Chrome Web Store–ready ZIP.
5+
* Output: dist-zip/ai-chat-backup-<version>.zip
6+
*
7+
* Usage:
8+
* node scripts/zip.mjs
9+
* npm run zip (after adding "zip" to package.json scripts)
10+
*/
11+
12+
import { execSync } from "node:child_process";
13+
import fs from "node:fs";
14+
import path from "node:path";
15+
import { createReadStream, createWriteStream } from "node:fs";
16+
import { pipeline } from "node:stream/promises";
17+
18+
const __dirname = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Za-z]:)/, "$1"));
19+
const root = path.resolve(__dirname, "..");
20+
const distDir = path.join(root, "dist");
21+
const outDir = path.join(root, "dist-zip");
22+
23+
/* ── read version from built manifest.json ────────────────── */
24+
const manifestPath = path.join(distDir, "manifest.json");
25+
if (!fs.existsSync(manifestPath)) {
26+
console.error("ERROR: dist/manifest.json not found. Run `npm run build` first.");
27+
process.exit(1);
28+
}
29+
const { version } = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
30+
31+
/* ── ensure output dir ────────────────────────────────────── */
32+
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
33+
34+
const zipName = `ai-chat-backup-${version}.zip`;
35+
const zipPath = path.join(outDir, zipName);
36+
37+
/* ── remove stale zip ─────────────────────────────────────── */
38+
if (fs.existsSync(zipPath)) fs.rmSync(zipPath);
39+
40+
/* ── zip using platform tools ─────────────────────────────── */
41+
const isWindows = process.platform === "win32";
42+
43+
try {
44+
if (isWindows) {
45+
// PowerShell 5+ Compress-Archive (available on all modern Windows)
46+
const distEscaped = distDir.replace(/'/g, "''");
47+
const zipEscaped = zipPath.replace(/'/g, "''");
48+
execSync(
49+
`powershell -NoProfile -Command "Compress-Archive -Path '${distEscaped}\\*' -DestinationPath '${zipEscaped}' -Force"`,
50+
{ stdio: "inherit" }
51+
);
52+
} else {
53+
// Unix: zip -r
54+
execSync(`zip -r "${zipPath}" .`, { cwd: distDir, stdio: "inherit" });
55+
}
56+
57+
console.log(`\nPackaged: dist-zip/${zipName}`);
58+
console.log(`Upload this file at: https://chrome.google.com/webstore/developer/dashboard\n`);
59+
} catch (err) {
60+
console.error("Packaging failed:", err.message);
61+
process.exit(1);
62+
}

src/background/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ import { generateSeedPrompt } from "../utils/seeder";
1818

1919
/* ── install / uninstall lifecycle ───────────────────────── */
2020

21-
chrome.runtime.onInstalled.addListener(() => {
21+
chrome.runtime.onInstalled.addListener((details) => {
22+
if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {
23+
chrome.tabs.create({ url: "https://migrate.hacklm.dev/aichatbackup/welcome" });
24+
}
2225
chrome.runtime.setUninstallURL(
2326
"https://docs.google.com/forms/d/e/1FAIpQLSfWyb7DJUjVJLzRTWwV208JI4dqLGPjoExx7uJNBsPeT2_4lA/viewform?usp=pp_url&entry.1264997455=AI+Chat+Backup"
2427
);

src/manifest.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ const manifest: ManifestV3Export = {
55
name: "AI Chat Backup",
66
version: "0.1.0",
77
description:
8-
"Back up your AI chat history from ChatGPT, Claude, Gemini & Grok and continue conversations anywhere.",
8+
"Save AI chats from ChatGPT, Claude, Gemini, Grok & Perplexity. Browse, search, and resume them. 100% local — no server, no sync.",
99
icons: {
1010
"16": "icons/icon16.png",
1111
"48": "icons/icon48.png",
1212
"128": "icons/icon128.png",
1313
},
14-
permissions: ["storage", "unlimitedStorage", "cookies", "activeTab"],
14+
permissions: ["storage", "unlimitedStorage", "activeTab"],
1515
host_permissions: [
1616
"https://chatgpt.com/*",
1717
"https://chat.openai.com/*",

src/options/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ export default function App() {
385385
<Inbox size={36} className="mx-auto mb-4 text-faint" strokeWidth={1.5} />
386386
<p className="text-lg font-medium">Select a chat to view</p>
387387
<p className="text-sm font-mono mt-2 text-faint">
388-
Save chats from ChatGPT, Claude, Gemini, or Grok
388+
Save chats from ChatGPT, Claude, Gemini, Grok, or Perplexity
389389
</p>
390390
</div>
391391

src/popup/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export default function App() {
112112
</button>
113113

114114
<p className="text-[10px] text-faint text-center">
115-
Visit ChatGPT, Claude, Gemini, or Grok to save chats.
115+
Visit ChatGPT, Claude, Gemini, Grok, or Perplexity to save chats.
116116
</p>
117117

118118
<div className="flex justify-between items-center w-full px-2">

src/utils/helpers.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,6 @@ export function sleep(ms: number): Promise<void> {
88
return new Promise((resolve) => setTimeout(resolve, ms));
99
}
1010

11-
/** Get a cookie value for a given URL + name via chrome.cookies API. */
12-
export async function getCookie(
13-
url: string,
14-
name: string
15-
): Promise<string | undefined> {
16-
const cookie = await chrome.cookies.get({ url, name });
17-
return cookie?.value;
18-
}
19-
2011
/** Jittered delay between min and max ms. */
2112
export function jitteredDelay(min: number, max: number): Promise<void> {
2213
const ms = min + Math.random() * (max - min);

0 commit comments

Comments
 (0)