Skip to content

Commit 0456945

Browse files
committed
Merge feature/browser-extension: add-to-cart browser extension + token auth
2 parents 86690f1 + e5957bc commit 0456945

34 files changed

Lines changed: 4154 additions & 4 deletions

cmd/shoplit-api/main.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/mayur-tolexo/shoplit/internal/config"
1919
"github.com/mayur-tolexo/shoplit/internal/db"
2020
sqlcgen "github.com/mayur-tolexo/shoplit/internal/db/sqlc"
21+
"github.com/mayur-tolexo/shoplit/internal/exttoken"
2122
"github.com/mayur-tolexo/shoplit/internal/httpx"
2223
"github.com/mayur-tolexo/shoplit/internal/ogfetch"
2324
"github.com/mayur-tolexo/shoplit/internal/publicapi"
@@ -60,13 +61,15 @@ func run() error {
6061

6162
q := sqlcgen.New(pool)
6263

64+
sm := auth.NewSessionManager(cfg.SessionSecret).
65+
WithSecure(cfg.CookieSecure).
66+
WithBearerResolver(exttoken.Resolver(q))
67+
6368
rc, err := redis.Open(ctx, cfg.RedisURL)
6469
if err != nil {
6570
return err
6671
}
6772
defer rc.Close()
68-
69-
sm := auth.NewSessionManager(cfg.SessionSecret).WithSecure(cfg.CookieSecure)
7073
upsert := auth.NewUserUpsertFn(q)
7174
fetcher := ogfetch.New(rc)
7275
svc := carts.NewService(q)
@@ -101,6 +104,7 @@ func run() error {
101104
// Authenticated creator endpoints
102105
r.Route("/api/v1", func(r chi.Router) {
103106
r.Use(sm.RequireUser())
107+
r.Post("/extension/token", exttoken.MintHandler(q))
104108
carts.RegisterRoutes(r, svc, fetcher)
105109
})
106110

extension/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
dist/

extension/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# shoplit extension (dev)
2+
3+
## Dev load
4+
5+
1. `npm install && npm run build`
6+
2. Chrome → chrome://extensions → enable Developer mode → "Load unpacked" → select `extension/dist`.
7+
3. Copy the extension ID Chrome shows; set `NEXT_PUBLIC_EXTENSION_ID` for the web app (and rebuild the connect page) so the auto-handoff works. Without it, the copy-paste fallback is used.
8+
4. Sign in at https://shoplit.in, open https://shoplit.in/connect-extension to connect.
9+
5. Visit a product page on Nykaa/Myntra/Amazon/Flipkart/AJIO → click the toolbar icon or the "+ shoplit" button → pick a cart → Add.
10+
11+
## Connect flow
12+
13+
- Navigating to `/connect-extension` while signed in mints a Bearer token via `POST /api/v1/extension/token`.
14+
- If the extension is detected (via `externally_connectable`), the token is handed off directly using `chrome.runtime.sendMessage` → the service worker stores it in `chrome.storage.local`.
15+
- If the extension is not detected (e.g., first load before granting permission, or a version mismatch), a copy-paste fallback is shown: copy the token and paste it into the extension popup manually.
16+
17+
## Manual E2E checklist
18+
19+
Record results in the PR description. For each retailer (Nykaa, Myntra, Amazon.in, Flipkart, AJIO):
20+
21+
- [ ] Open a product page; confirm the "+ shoplit" floating button appears within 2 seconds of page load.
22+
- [ ] Click the toolbar icon; confirm the popup shows the correct title, image, and price (populated from JSON-LD or OG tags).
23+
- [ ] Select a cart from the dropdown and click "+ Add to cart"; confirm the request succeeds (no error message).
24+
- [ ] Open the cart's `/c/{slug}` page and confirm the product appears with title, image, and price.
25+
- [ ] Confirm the product's "Shop" link redirects to the original product URL on the retailer site.
26+
27+
Expected: title + image populate on at least JSON-LD retailers (Nykaa, Amazon); price where present. Where a field is missing, the inline edit lets the user fix it before adding.
28+
29+
## Build and test
30+
31+
```bash
32+
cd extension
33+
npm install
34+
npm run build # esbuild → dist/
35+
npx vitest run # retailer classification + product extraction tests
36+
```

extension/build.mjs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// extension/build.mjs
2+
import { build } from "esbuild";
3+
import { cp, mkdir, rm } from "node:fs/promises";
4+
5+
await rm("dist", { recursive: true, force: true });
6+
await mkdir("dist", { recursive: true });
7+
8+
await build({
9+
entryPoints: {
10+
"service-worker": "src/service-worker.ts",
11+
content: "src/content.ts",
12+
popup: "src/popup.ts",
13+
},
14+
outdir: "dist",
15+
bundle: true,
16+
format: "esm",
17+
target: "chrome114",
18+
logLevel: "info",
19+
});
20+
21+
await cp("manifest.json", "dist/manifest.json");
22+
await cp("src/popup.html", "dist/popup.html");
23+
await cp("icons", "dist/icons", { recursive: true }).catch(() => {});
24+
console.log("built → dist/");

extension/manifest.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"manifest_version": 3,
3+
"name": "shoplit — add to cart",
4+
"version": "0.1.0",
5+
"description": "Add any product to your shoplit cart from Amazon, Myntra, Nykaa, Flipkart, AJIO.",
6+
"action": { "default_popup": "popup.html", "default_title": "Add to shoplit" },
7+
"background": { "service_worker": "service-worker.js", "type": "module" },
8+
"permissions": ["activeTab", "scripting", "storage"],
9+
"host_permissions": [
10+
"https://shoplit.in/*",
11+
"https://*.nykaa.com/*",
12+
"https://*.myntra.com/*",
13+
"https://*.amazon.in/*",
14+
"https://*.amazon.com/*",
15+
"https://*.flipkart.com/*",
16+
"https://*.ajio.com/*"
17+
],
18+
"content_scripts": [
19+
{
20+
"matches": [
21+
"https://*.nykaa.com/*",
22+
"https://*.myntra.com/*",
23+
"https://*.amazon.in/*",
24+
"https://*.amazon.com/*",
25+
"https://*.flipkart.com/*",
26+
"https://*.ajio.com/*"
27+
],
28+
"js": ["content.js"],
29+
"run_at": "document_idle"
30+
}
31+
],
32+
"externally_connectable": { "matches": ["https://shoplit.in/*"] }
33+
}

0 commit comments

Comments
 (0)