Skip to content

Commit 25f0822

Browse files
committed
✨ Improve preview command with smart exclusions and dry-run
- Fix form-data upload issue by using native FormData/Blob for fetch compatibility - Add smart default exclusions for non-static files (node_modules, tests, configs, etc.) - Add --dry-run flag to show what would be uploaded without uploading - Add --exclude/-x flag to add custom exclusion patterns - Add --include/-i flag to override default exclusions - Show helpful error message when path argument is missing - Skip API token validation for dry-run mode
1 parent 8480393 commit 25f0822

File tree

4 files changed

+276
-40
lines changed

4 files changed

+276
-40
lines changed

src/api/endpoints.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,18 +333,15 @@ export async function finalizeParallelBuild(client, parallelId) {
333333
* @returns {Promise<Object>} Upload result with preview URL
334334
*/
335335
export async function uploadPreviewZip(client, buildId, zipBuffer) {
336-
// Create form data with the ZIP file
337-
let FormData = (await import('form-data')).default;
336+
// Use native FormData (Node 18+) with Blob for proper fetch compatibility
338337
let formData = new FormData();
339-
formData.append('file', zipBuffer, {
340-
filename: 'preview.zip',
341-
contentType: 'application/zip',
342-
});
338+
let blob = new Blob([zipBuffer], { type: 'application/zip' });
339+
formData.append('file', blob, 'preview.zip');
343340

344341
return client.request(`/api/sdk/builds/${buildId}/preview/upload-zip`, {
345342
method: 'POST',
346343
body: formData,
347-
headers: formData.getHeaders(),
344+
// Let fetch set the Content-Type with boundary automatically
348345
});
349346
}
350347

src/cli.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,14 +572,38 @@ program
572572
program
573573
.command('preview')
574574
.description('Upload static files as a preview for a build')
575-
.argument('<path>', 'Path to static files (dist/, build/, out/)')
575+
.argument('[path]', 'Path to static files (dist/, build/, out/)')
576576
.option('-b, --build <id>', 'Build ID to attach preview to')
577577
.option('-p, --parallel-id <id>', 'Look up build by parallel ID')
578578
.option('--base <path>', 'Override auto-detected base path')
579579
.option('--open', 'Open preview URL in browser after upload')
580+
.option('--dry-run', 'Show what would be uploaded without uploading')
581+
.option(
582+
'-x, --exclude <pattern>',
583+
'Exclude files/dirs (can be repeated, use trailing / for dirs)',
584+
(val, prev) => (prev ? [...prev, val] : [val])
585+
)
586+
.option(
587+
'-i, --include <pattern>',
588+
'Include files/dirs excluded by default (can be repeated)',
589+
(val, prev) => (prev ? [...prev, val] : [val])
590+
)
580591
.action(async (path, options) => {
581592
const globalOptions = program.opts();
582593

594+
// Show helpful error if path is missing
595+
if (!path) {
596+
output.error('Path to static files is required');
597+
output.blank();
598+
output.print(' Upload your build output directory:');
599+
output.blank();
600+
output.print(' vizzly preview ./dist');
601+
output.print(' vizzly preview ./build');
602+
output.print(' vizzly preview ./out');
603+
output.blank();
604+
process.exit(1);
605+
}
606+
583607
// Validate options
584608
const validationErrors = validatePreviewOptions(path, options);
585609
if (validationErrors.length > 0) {

0 commit comments

Comments
 (0)