From cab026dbfbd8d956a92fb3c81ae75219cadea2b0 Mon Sep 17 00:00:00 2001 From: smoratino-apogea <> Date: Tue, 28 Apr 2026 13:32:55 +0200 Subject: [PATCH 1/2] feat: update publish command to use named File for ZIP and icon uploads --- src/cli/commands/publish.ts | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/cli/commands/publish.ts b/src/cli/commands/publish.ts index ac248fa..d31130f 100644 --- a/src/cli/commands/publish.ts +++ b/src/cli/commands/publish.ts @@ -103,9 +103,11 @@ export const publishCommand = new Command('publish') process.exit(1); } - // Read ZIP as Blob for the client + // Read ZIP as a named File for the client const zipBuffer = readFileSync(zipPath); - const zipBlob = new Blob([zipBuffer]); + const zipFile = new File([zipBuffer], 'bundle.zip', { + type: 'application/zip', + }); // Resolve icon: CLI flag > local config const iconPath = opts.icon || localConfig?.iconPath; @@ -123,7 +125,7 @@ export const publishCommand = new Command('publish') itemId = await publishComponent( client, existingId, - zipBlob, + zipFile, projectName, versionTag, cwd, @@ -132,7 +134,7 @@ export const publishCommand = new Command('publish') itemId = await publishApp( client, existingId, - zipBlob, + zipFile, projectName, versionTag, cwd, @@ -174,7 +176,7 @@ export const publishCommand = new Command('publish') async function publishApp( client: EngineServicesClient, appId: string | undefined, - zipBlob: Blob, + zipFile: File, name: string, versionTag: string, cwd: string, @@ -192,7 +194,7 @@ async function publishApp( ); const result = await client.createVersion( appId, - zipBlob, + zipFile, versionTag, {}, // extraProps required by backend for APP items ); @@ -201,7 +203,7 @@ async function publishApp( } else { console.log(`Publishing new app "${name}" (${versionTag})...`); const result = await client.createApp({ - file: zipBlob, + file: zipFile, name, versionTag, }); @@ -224,7 +226,7 @@ async function publishApp( async function publishComponent( client: EngineServicesClient, componentId: string | undefined, - zipBlob: Blob, + zipFile: File, name: string, versionTag: string, cwd: string, @@ -247,7 +249,7 @@ async function publishComponent( `Publishing new version (${versionTag}) for component ${componentId}...`, ); const result = await client.updateComponent(componentId, { - file: zipBlob, + file: zipFile, versionTag, componentProps, }); @@ -258,7 +260,7 @@ async function publishComponent( `Publishing new cloud component "${name}" (${versionTag})...`, ); const result = await client.createComponent({ - file: zipBlob, + file: zipFile, name, versionTag, componentProps, @@ -279,7 +281,12 @@ async function publishComponent( // Icon upload helper // --------------------------------------------------------------------------- -const ALLOWED_ICON_EXTENSIONS = ['.png', '.webp', '.ico']; +const ICON_MIME_TYPES: Record = { + '.png': 'image/png', + '.webp': 'image/webp', + '.ico': 'image/x-icon', +}; +const ALLOWED_ICON_EXTENSIONS = Object.keys(ICON_MIME_TYPES); const MAX_ICON_SIZE = 512 * 1024; // 512 KB async function uploadIcon( @@ -310,8 +317,10 @@ async function uploadIcon( console.log('Uploading icon...'); const iconBuffer = readFileSync(resolvedPath); - const iconBlob = new Blob([iconBuffer]); - await client.uploadItemIcon(itemId, iconBlob); + const iconFile = new File([iconBuffer], basename(resolvedPath), { + type: ICON_MIME_TYPES[ext], + }); + await client.uploadItemIcon(itemId, iconFile); console.log('Icon uploaded.'); // Save icon path to local config if provided via CLI flag From a32e019afd1b8a747d156bc12a03929475820273 Mon Sep 17 00:00:00 2001 From: smoratino-apogea <> Date: Tue, 28 Apr 2026 13:39:00 +0200 Subject: [PATCH 2/2] feat: update changelog --- .changeset/violet-moments-poke.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/violet-moments-poke.md diff --git a/.changeset/violet-moments-poke.md b/.changeset/violet-moments-poke.md new file mode 100644 index 0000000..add139b --- /dev/null +++ b/.changeset/violet-moments-poke.md @@ -0,0 +1,5 @@ +--- +'thatopen-services': minor +--- + +Send named File (with filename and mimetype) for bundle and icon uploads in the publish command.