Skip to content

feat: recognize .msix / .msixbundle assets and 'msix' package format#46

Open
dopry wants to merge 4 commits into
nextfrom
claude/pecans-pr26-rebase-x9ih6r
Open

feat: recognize .msix / .msixbundle assets and 'msix' package format#46
dopry wants to merge 4 commits into
nextfrom
claude/pecans-pr26-rebase-x9ih6r

Conversation

@dopry

@dopry dopry commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Summary

Supersedes #26 (thanks @jjeff for the original contribution — authorship is credited via Co-Authored-By on the commit). That PR was written against the pre-refactor codebase and can't be rebased mechanically: next has since replaced versions.ts / resolveForVersion.ts with the unified ReleaseService pipeline on the discrete {os, arch, pkg} model (#41#45), and the PR's head lives on a fork branch this session can't push to. This PR reimplements the same feature idiomatically on the new architecture, preserving the external contract #26 established.

Pecans can now act as the update server for an Electron 41+ app packaged as MSIX: the /update/:platform/:version endpoint already emits the Squirrel.Mac-shaped {url, name, notes, pub_date} JSON that Electron's MSIX autoUpdater consumes — Pecans just needs to recognize .msix / .msixbundle assets and route to them when the client asks for the msix filetype.

Changes

  • Detection utilities (unchanged from feat: recognize .msix / .msixbundle assets and 'msix' package format #26): SUPPORTED_FILE_EXTENSIONS gains .msix / .msixbundle; PACKAGE_FORMATS gains msix; filenameToOperatingSystem maps both extensions to windows; filenameToArchitecture treats .msixbundle as universal (multi-arch by definition) while single-arch .msix derives arch from the filename suffix (_x64, _arm64, _x86); getDownloadExtensionsByOs("windows", "msix") returns [".msixbundle", ".msix"], preferring the bundle.
  • Ingestion — where this diverges from feat: recognize .msix / .msixbundle assets and 'msix' package format #26, which excluded msix from composite platform ids: on the discrete model, msix is a first-class package format, so assets ingest as windows_msix_64 / windows_msix_32 / windows_msix_universal (new PLATFORMS entries), exactly like linux_deb_64. This is what makes them reach parsePlatform/assetMatchesPlatform cleanly. arm64 .msix assets drop at ingestion like any other arm64 windows asset.
  • Resolution (assetMatchesPlatform): a universal msix asset satisfies any windows arch only when msix is explicitly requested (pkg: "msix"); default windows flows (pkg: "default") never widen to msix, so a .msixbundle-only release counts toward msix availability but never toward default availability. (feat: recognize .msix / .msixbundle assets and 'msix' package format #26's ingestion-order fix made bundle availability unconditional — a bundle-only release would 200 on a default update request and then 404 on the download; the discrete model lets us return an honest 204 instead.)
  • HTTP edge: new filetypeToPackageFormat maps ?filetype=msix|msixbundle to pkg: "msix" on the update and composite download routes. Other filetypes (deb, rpm, zip…) deliberately imply no pkg, preserving their existing platform-default semantics. The discrete route gets msix for free: /dl/windows/64?pkg=msix and /dl/windows/universal?pkg=msix.
  • Docs: MSIX section added to docs/update-windows.md.

Downstream compatibility

  • Default windows downloads/updates still resolve [".exe"] unless msix is explicitly requested — pinned by a regression test with .exe + .msix + .msixbundle published side by side.
  • The Squirrel.Windows RELEASES / .nupkg path is untouched.
  • The PackageFormat / SupportedFileExtension / Platform unions widen, which only affects TypeScript consumers doing exhaustive switches — semver-minor.

Test plan

  • All of feat: recognize .msix / .msixbundle assets and 'msix' package format #26's unit tests ported to the current test layout (detection utilities, platform table, normalizeRelease ingestion seam, service-level resolution semantics)
  • New test/integration/msix.spec.ts covers the feature end-to-end through the HTTP surface: Squirrel.Mac-shaped 200/204s for ?filetype=msix|msixbundle, feed-url → bundle download resolution, bundle-only releases satisfying arch-specific clients, default flows still serving the .exe, and the /dl + /dl/:filename routes
  • 767 tests pass (up from 719 on next), tsc --noEmit clean, eslint clean

Notes

Server-side half of MSIX support for spaceagetv/missioncontrol (Visibox). References: Electron 41 release notes, electron/electron#49230.

🤖 Generated with Claude Code

https://claude.ai/code/session_019F5tixJXBm2R1FAjAfH1se


Generated by Claude Code

Reimplementation of #26 on the unified ReleaseService resolution
pipeline (msix as a first-class package format on the discrete
{os, arch, pkg} model):

- SUPPORTED_FILE_EXTENSIONS gains .msix / .msixbundle;
  getDownloadExtensionsByOs("windows", "msix") returns
  [".msixbundle", ".msix"], preferring the multi-arch bundle.
- PACKAGE_FORMATS gains "msix"; filenameToPackageFormat detects both
  extensions; new filetypeToPackageFormat maps ?filetype=msix|msixbundle
  to the msix pkg at the HTTP edge (other filetypes keep their
  platform-default semantics).
- filenameToOperatingSystem maps .msix / .msixbundle to windows;
  filenameToArchitecture treats .msixbundle as universal (multi-arch by
  definition), single-arch .msix derives arch from the filename suffix.
- New composite platform ids windows_msix{,_32,_64,_universal} so msix
  assets survive ingestion; arm64 .msix drops like any arm64 windows
  asset.
- assetMatchesPlatform: a universal msix asset satisfies any windows
  arch when msix is explicitly requested; default windows flows
  (pkg "default") never widen to msix, so Squirrel clients keep
  resolving the .exe when msix assets are published alongside it.
- /update/:platform/:version?filetype=msix serves the existing
  Squirrel.Mac-shaped JSON that Electron 41+'s MSIX autoUpdater
  consumes; /download/...?filetype=msix and /dl/windows/:arch?pkg=msix
  route to the assets. The Squirrel.Windows RELEASES/.nupkg path is
  untouched.

Co-Authored-By: Jeff Robbins <321284+jjeff@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019F5tixJXBm2R1FAjAfH1se
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019F5tixJXBm2R1FAjAfH1se

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class MSIX support to Pecans’ discrete {os, arch, pkg} resolution pipeline so Electron 41+ MSIX autoUpdater clients can request updates via ?filetype=msix|msixbundle and resolve to .msix / .msixbundle assets without affecting default Windows (Squirrel/.exe) behavior.

Changes:

  • Extend detection + platform modeling to recognize .msix / .msixbundle, introduce pkg: "msix", and ingest MSIX assets as windows_msix_* platforms.
  • Update resolution semantics so universal .msixbundle can satisfy arch-specific Windows requests only when pkg: "msix" is requested, while default Windows flows remain .exe.
  • Add end-to-end integration coverage and documentation for MSIX update/download routes.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/unit/SupportedFileExtension.spec.ts Adds MSIX/MSIXBUNDLE extension coverage and Windows msix download-extension expectations.
test/unit/service.spec.ts Adds parsePlatform, matching, and resolution tests for msix (including universal bundle widening under pkg: "msix").
test/unit/platforms.spec.ts Verifies filename→platform resolution for .msix/.msixbundle including arm64 drop behavior.
test/unit/PackageFormat.spec.ts Expands PackageFormat to include msix and tests filetypeToPackageFormat.
test/unit/OperatingSystem.spec.ts Adds OS detection expectations for .msix/.msixbundle as Windows.
test/unit/github.spec.ts Ensures GitHub backend normalization retains msix assets alongside exe assets.
test/unit/Architecture.spec.ts Adds .msixbundleuniversal and .msix suffix arch detection tests.
test/integration/msix.spec.ts New integration suite covering update/download/dl behavior for MSIX end-to-end.
src/utils/SupportedFileExtension.ts Adds supported extensions and Windows pkg=msix download-extension preference ordering.
src/utils/platforms.ts Adds windows_msix* platform IDs and allows filenameToPlatform to encode msix as a pkg segment.
src/utils/PackageFormat.ts Adds msix package format detection + filetypeToPackageFormat mapping for HTTP filetype.
src/utils/OperatingSystem.ts Recognizes .msix/.msixbundle as Windows.
src/utils/Architecture.ts Treats .msixbundle as universal by definition.
src/service.ts Allows universal msix assets to satisfy arch-specific Windows filters when pkg: "msix".
src/http/updates.ts Applies msix pkg implication based on ?filetype=... for the Squirrel.Mac-shaped update feed.
src/http/downloads.ts Applies msix pkg implication at the legacy /download/* HTTP edge when ?filetype=msix*.
docs/update-windows.md Documents Electron 41+ MSIX update usage and how it interacts with default Windows behavior.

Comment thread src/http/updates.ts
filetypeToPackageFormat accepts ?filetype=MSIX case-insensitively, but
the handler embedded the caller's casing into the generated download
url, which the download route's case-sensitive filetype validation then
rejects with a 400. Lowercase the filetype before both the pkg mapping
and the feed url.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019F5tixJXBm2R1FAjAfH1se

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Comment thread src/http/downloads.ts
Comment thread src/utils/PackageFormat.ts
The filetype->pkg implication belongs to platform-based resolution; an
explicit :filename already identifies the asset and its package format,
so a stray ?filetype=msix on an .exe filename request must not narrow
release resolution (previously a 404 when no msix assets exist). Also
reword the filetypeToPackageFormat doc comment: internal windows_msix*
composite ids exist for ingestion, they're just not part of the legacy
request vocabulary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019F5tixJXBm2R1FAjAfH1se

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

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.

3 participants