Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/api/endpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,47 @@ export async function finalizeParallelBuild(client, parallelId) {
headers: { 'Content-Type': 'application/json' },
});
}

// ============================================================================
// Preview Endpoints
// ============================================================================

/**
* Upload preview ZIP file for a build
* @param {Object} client - API client
* @param {string} buildId - Build ID
* @param {Buffer} zipBuffer - ZIP file contents
* @returns {Promise<Object>} Upload result with preview URL
*/
export async function uploadPreviewZip(client, buildId, zipBuffer) {
// Create form data with the ZIP file
let FormData = (await import('form-data')).default;
let formData = new FormData();
formData.append('file', zipBuffer, {
filename: 'preview.zip',
contentType: 'application/zip',
});

return client.request(`/api/sdk/builds/${buildId}/preview/upload-zip`, {
method: 'POST',
body: formData,
headers: formData.getHeaders(),
});
}

/**
* Get preview info for a build
* @param {Object} client - API client
* @param {string} buildId - Build ID
* @returns {Promise<Object>} Preview info or null if not found
*/
export async function getPreviewInfo(client, buildId) {
try {
return await client.request(`/api/sdk/builds/${buildId}/preview`);
} catch (error) {
if (error.status === 404) {
return null;
}
throw error;
}
}
2 changes: 2 additions & 0 deletions src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ export {
getBuild,
getBuilds,
getComparison,
getPreviewInfo,
getScreenshotHotspots,
getTddBaselines,
getTokenContext,
searchComparisons,
updateBuildStatus,
uploadPreviewZip,
uploadScreenshot,
} from './endpoints.js';
25 changes: 25 additions & 0 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { init } from './commands/init.js';
import { loginCommand, validateLoginOptions } from './commands/login.js';
import { logoutCommand, validateLogoutOptions } from './commands/logout.js';
import { previewCommand, validatePreviewOptions } from './commands/preview.js';
import {
projectListCommand,
projectRemoveCommand,
Expand Down Expand Up @@ -568,6 +569,30 @@ program
await finalizeCommand(parallelId, options, globalOptions);
});

program
.command('preview')
.description('Upload static files as a preview for a build')
.argument('<path>', 'Path to static files (dist/, build/, out/)')
.option('-b, --build <id>', 'Build ID to attach preview to')
.option('-p, --parallel-id <id>', 'Look up build by parallel ID')
.option('--base <path>', 'Override auto-detected base path')
.option('--open', 'Open preview URL in browser after upload')
.action(async (path, options) => {
const globalOptions = program.opts();

// Validate options
const validationErrors = validatePreviewOptions(path, options);
if (validationErrors.length > 0) {
output.error('Validation errors:');
for (let error of validationErrors) {
output.printErr(` - ${error}`);
}
process.exit(1);
}

await previewCommand(path, options, globalOptions);
});

program
.command('doctor')
.description('Run diagnostics to check your environment and configuration')
Expand Down
10 changes: 10 additions & 0 deletions src/commands/finalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '../api/index.js';
import { loadConfig as defaultLoadConfig } from '../utils/config-loader.js';
import * as defaultOutput from '../utils/output.js';
import { writeSession as defaultWriteSession } from '../utils/session.js';

/**
* Finalize command implementation
Expand All @@ -28,6 +29,7 @@ export async function finalizeCommand(
createApiClient = defaultCreateApiClient,
finalizeParallelBuild = defaultFinalizeParallelBuild,
output = defaultOutput,
writeSession = defaultWriteSession,
exit = code => process.exit(code),
} = deps;

Expand Down Expand Up @@ -69,6 +71,14 @@ export async function finalizeCommand(
let result = await finalizeParallelBuild(client, parallelId);
output.stopSpinner();

// Write session for subsequent commands (like preview)
if (result.build?.id) {
writeSession({
buildId: result.build.id,
parallelId,
});
}

if (globalOptions.json) {
output.data(result);
} else {
Expand Down
Loading