Repository: mediar-ai/screenpipe
File: screenpipe-js/cli/src/commands/pipe/publish.ts (TypeScript)

Code before:
              console.error(colors.dim(`${symbols.arrow} stack trace: ${error.stack}`));
            }
            if (axios.isAxiosError(error)) {
              console.error(colors.error(`${symbols.error} upload response: ${JSON.stringify(error.response?.data || {})}`));
              console.error(colors.error(`${symbols.error} upload status: ${error.response?.status || 'unknown'}`));
              console.error(colors.error(`${symbols.error} upload request config: ${JSON.stringify({
                url: error.config?.url?.substring(0, 100) + '...',
                method: error.config?.method,
                timeout: error.config?.timeout,
                headers: error.config?.headers
              })}`));
            }
            throw error;
          } else {
            // If we've seen 100% progress, we can ignore the socket close error
            // Use a warning style instead of error
            console.log(colors.dim(`${symbols.info} upload completed but connection closed: ${error instanceof Error ? error.message : 'unknown'}`));
            console.log(colors.dim(`${symbols.arrow} socket was closed after upload completed, continuing with finalization...`));
          }
        }
        
        // Notify server that upload is complete
        logger.log(colors.dim(`${symbols.arrow} finalizing upload...`));
        console.log(colors.dim(`${symbols.arrow} sending finalize request to: ${API_BASE_URL}/api/plugins/publish/finalize`));
        
        const finalizeResponse = await axios.post(
          `${API_BASE_URL}/api/plugins/publish/finalize`,
          {
            name: opts.name,
            version: packageJson.version,
            fileHash,
            storagePath: path,
            description,
            fileSize,
          },
          {
            headers: {
              Authorization: `Bearer ${apiKey}`,
              "Content-Type": "application/json",
            },
            timeout: 30000, // 30 second timeout
          }
        );

        console.log(colors.dim(`${symbols.arrow} finalize response status: ${finalizeResponse.status}`));
        console.log(colors.dim(`${symbols.arrow} finalize response data: ${JSON.stringify(finalizeResponse.data)}`));

        // Success messages
        logger.success(`\n${symbols.success} successfully published plugin!`);

        console.log(

Review comment (bug):
@m13v this is really hard to read / debug - check early return pattern:

https://medium.com/swlh/return-early-pattern-3d18a41bba8

Code after:
                
                // Update packageJson in memory
                packageJson.version = newVersion;
                
                // Retry the request with new version
                console.log(colors.dim(`${symbols.arrow} retrying with new version: ${newVersion}`));
                urlResponse = await axios.post(`${API_BASE_URL}/api/plugins/publish`, {
                  name: opts.name,
                  version: newVersion,
                  fileSize,
                  fileHash,
                  description,
                }, {
                  headers: {
                    Authorization: `Bearer ${apiKey}`,
                    "Content-Type": "application/json",
                  },
                  timeout: 30000,
                });
              } else {
                // User chose not to bump version
                throw new Error(`Publishing canceled. Please update the version manually in package.json.`);
              }
            } else {
              // Handle other errors
              if (typeof errorData === 'string') {
                throw new Error(errorData);
              } else if (errorData.error) {
                if (Array.isArray(errorData.error)) {
                  const issues = errorData.error.map((issue: any) => 
                    `${issue.path.join('.')}: ${issue.message}`
                  ).join(', ');
                  throw new Error(`validation failed: ${issues}`);
                } else {
                  throw new Error(`server error: ${JSON.stringify(errorData.error)}`);
                }
              } else {
                throw new Error(`server responded with error: ${JSON.stringify(errorData)}`);
              }
            }
          } else {
            throw error; // Re-throw if not an axios error
          }
        }

        console.log(colors.dim(`${symbols.arrow} url response status: ${urlResponse.status}`));
        
        const { uploadUrl, path } = urlResponse.data;
        console.log(colors.dim(`${symbols.arrow} received upload URL: ${uploadUrl.substring(0, 50)}...`));
        console.log(colors.dim(`${symbols.arrow} storage path: ${path}`));
        console.log(colors.dim(`${symbols.arrow} file size: ${fileSize} bytes`));