Skip to content

Commit c71cec3

Browse files
authored
✨ Improve preview command with smart exclusions and dry-run (#186)
## Summary - Fix form-data upload by using native `FormData`/`Blob` for fetch compatibility (the `form-data` npm package doesn't stream correctly with Node's native fetch) - Add smart default exclusions for non-static files: `node_modules`, `tests/`, `__tests__/`, `coverage/`, `*.config.js`, `package.json`, `*.md`, etc. - Add `--dry-run` flag to preview what would be uploaded without actually uploading - Add `--exclude/-x` flag to add custom exclusion patterns (repeatable, use trailing `/` for directories) - Add `--include/-i` flag to override default exclusions (e.g., `--include package.json`) - Show helpful error message with examples when path argument is missing - Skip API token validation for dry-run mode ## Test plan - [ ] Run `vizzly preview ./dist --dry-run` to verify file listing works - [ ] Run `vizzly preview ./dist --dry-run --verbose` to see exclusion lists - [ ] Run `vizzly preview ./dist --dry-run --exclude "*.css"` to test custom exclusions - [ ] Run `vizzly preview ./dist --dry-run --include package.json` to test including excluded files - [ ] Run `vizzly preview` (no path) to verify helpful error message - [ ] Run actual upload to verify form-data fix works
1 parent 8480393 commit c71cec3

File tree

5 files changed

+520
-45
lines changed

5 files changed

+520
-45
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 (repeatable, e.g. -x "*.log" -x "temp/")',
584+
(val, prev) => (prev ? [...prev, val] : [val])
585+
)
586+
.option(
587+
'-i, --include <pattern>',
588+
'Override default exclusions (repeatable, e.g. -i package.json -i tests/)',
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)