feat: update publish command to use named File for ZIP and icon uploads#12
Merged
Conversation
ABujalance
approved these changes
Apr 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Send named
Filefor bundle and icon uploadsSummary
Replace
new Blob([buffer])withnew File([buffer], filename, { type })in thepublishcommand. The CLI was sending unnamed, untyped multipart entries — which the platform now rejects (bundle), or has been silently rejecting since the icon endpoint shipped (icon).What changed
In
src/cli/commands/publish.ts:new Blob([zipBuffer])→new File([zipBuffer], 'bundle.zip', { type: 'application/zip' }). Renamed the localzipBlobvariable and thepublishApp/publishComponentparameter tozipFile: File.new Blob([iconBuffer])→new File([iconBuffer], basename(resolvedPath), { type: ICON_MIME_TYPES[ext] }). Added anICON_MIME_TYPESmap and derivedALLOWED_ICON_EXTENSIONSfrom its keys (single source of truth).No changes to public API, client surface, or tests.
Why it didn't fail before
Two independent backend validations are involved, both added recently:
Bundle —
allowedExtensionFilter(platform commit135f5d2 feat(uploads): add extension whitelist and fix S3 ContentType). This is part of thefeat/free-tier-limitsPR currently in flight on the platform repo. Before this filter, multer accepted any multipart entry regardless of filename or extension. Node's FormData defaults the filename of an unnamedBlobto"blob"(no extension), so the new filter rejects every CLI publish with a 400.Icon —
ALLOWED_ICON_MIMETYPES(platform commit8439550 feat: add optional icon support for items, March 1 2026). The icon endpoint validatesfile.mimetype ∈ {image/png, image/webp, image/x-icon, image/vnd.microsoft.icon}. ABlobconstructed withouttypeserializes asapplication/octet-streamover multipart, which is not in the allowlist. The icon CLI feature was added shortly after (b7949c0 feat: add icon support for items (#6)) but never sent a valid mimetype — so it has been broken since it shipped. The bug went unnoticed because the feature is new and likely unused in production.Risk and side effects
The backend uses
originalnameandmimetypein three places. None are regressions:item.service.ts:118): now derives"zip"instead of"". This is the path the new filter validates.item.service.ts:119): only triggers when nonameis supplied. The CLI always passesprojectName, so this is unreachable frompublish.s3-multer.ts,iconMimeTypefield): cosmetic improvement —"bundle.zip"over"blob","image/png"over"application/octet-stream".64 published versions of
thatopen-services(0.0.1 → 0.14.0) all carry the oldBlobcode. None of them work against a backend with the extension filter. After this fix, all future versions will.Test plan
yarn build— passes (verified locally).thatopen publishagainst a backend withallowedExtensionFilterenabled — bundle uploads succeed.thatopen publish --icon ./icon.png— icon uploads succeed and the item'siconMimeTypeisimage/png..webpand.icoextensions.appId/componentIdin.thatopen) —createVersion/updateComponentsucceed.