Skip to content

🍕 fix(zip): strip source maps + verify manifest at root#5

Merged
jjpaulino merged 1 commit into
masterfrom
fix/zip-script-hardening
May 13, 2026
Merged

🍕 fix(zip): strip source maps + verify manifest at root#5
jjpaulino merged 1 commit into
masterfrom
fix/zip-script-hardening

Conversation

@jjpaulino
Copy link
Copy Markdown
Member

Summary

Fixes the Chrome Web Store upload error "No manifest found in package. Please make sure to put manifest.json at the root directory of the zip package." — and shrinks the upload from 333 KB → 101 KB (3.3× smaller) while we're at it.

Why we hit the error

Two ways to land in this state:

  1. Right-clicking dist/ in Finder / Explorer → Compress produces a zip with a dist/ wrapper, so the store sees dist/manifest.json and not manifest.json. Rejected.
  2. Even with npm run zip, the previous script shipped:
    • All source maps (*.map, ~70% of the bundle weight)
    • macOS resource forks (__MACOSX/, .DS_Store) when zipped on a macOS dev box

Source maps don't break the upload but they leak source and bloat the package; macOS metadata occasionally trips Web Store validation.

What this PR changes

scripts/zip-extension.mjs:

  • Excludes *.map, .DS_Store, __MACOSX/ by default. Pass INCLUDE_SOURCEMAPS=1 npm run zip to opt back in (handy for debugging a sideloaded build).
  • Pre-flight check: refuses to run if dist/manifest.json is missing.
  • Post-zip verification: shells out to unzip -p outzip manifest.json (with a PowerShell System.IO.Compression fallback for Windows) to assert manifest.json exists at the root. If not, exits with code 2 and a descriptive error.
  • Clear next-step output: prints the exact filename, dashboard URL, and upload steps after a successful pack — no more guessing which file to upload.

README.md:

  • "Releasing" section now warns against Finder / Explorer compression and documents the INCLUDE_SOURCEMAPS=1 env var.

Verification

Scenario Before After
npm run zip 332.8 KB, contains *.map 101.0 KB, source-map-free
INCLUDE_SOURCEMAPS=1 npm run zip n/a 332.8 KB, with maps (escape hatch)
Hand-zipped with dist/ wrapper (Finder repro) Silently produced, store rejected Refused at the source with exit code 2
manifest.json accidentally missing from dist/ Silently produced, broken zip Refused at the source with exit code 1
npm run validate
$ rm clay-slip-v*.zip && npm run zip
…
✓ wrote clay-slip-v2.0.2.zip (101.0 KB)

Next steps:
  1. Upload this file to the Chrome Web Store dashboard:
     https://chrome.google.com/webstore/devconsole
  2. Pick this extension → Package → Upload new package
  3. Choose: clay-slip-v2.0.2.zip
$ unzip -l clay-slip-v2.0.2.zip | tail -3
   297842                     23 files

Manifest at root, no source maps, no macOS junk, 23 clean files. Ready for the store.

Test plan

  • npm run zip produces a 101 KB zip with manifest.json at root and no *.map files
  • INCLUDE_SOURCEMAPS=1 npm run zip produces a 333 KB zip with maps included
  • Hand-rolled wrapper zip (zip -r bad.zip dist) is rejected by the verification guard
  • npm run validate passes (84 tests, lint, format, typecheck)
  • Once merged: cut a fresh tag, confirm the Release workflow's draft contains the slim zip
  • Manual: upload the slim zip to the Chrome Web Store dashboard and confirm acceptance

Made with Cursor

The Chrome Web Store rejects uploads where `manifest.json` isn't at the
zip root with "No manifest found in package." The most common cause is
right-clicking `dist/` in Finder/Explorer → Compress, which produces a
zip with a `dist/` wrapper. Even when our script is used, source maps
and macOS `__MACOSX/` resource forks would silently triple the upload
size and occasionally trip Web Store validation.

This hardens `scripts/zip-extension.mjs`:

- **Strips `*.map`, `.DS_Store`, and `__MACOSX/`** by default. Pass
  `INCLUDE_SOURCEMAPS=1 npm run zip` to opt back in for sideload-debug
  builds. Cuts the zip from ~333 KB → ~101 KB (3.3× smaller).
- **Verifies after zipping** that `manifest.json` is at the root by
  shelling out to `unzip -p` (with a PowerShell fallback). Refuses to
  hand off a zip that would be rejected by the store.
- **Asserts `dist/manifest.json` exists** before zipping (catches a
  half-broken build).
- **Prints explicit upload instructions** so there's no ambiguity about
  which file to upload and where.

README's "Releasing" section now warns against Finder/Explorer
compression and documents the `INCLUDE_SOURCEMAPS=1` escape hatch.

Tested locally:
  $ npm run zip
  → clay-slip-v2.0.2.zip (101.0 KB)
  → manifest.json verified at root

Negative test (zipped with a `dist/` wrapper) correctly trips the
verification guard with exit code 2.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jjpaulino jjpaulino merged commit 009ecbe into master May 13, 2026
1 check passed
@jjpaulino jjpaulino deleted the fix/zip-script-hardening branch May 13, 2026 05:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant