zero-query 0.2.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * zQuery CLI
@@ -8,21 +8,22 @@
8
8
  *
9
9
  * Usage:
10
10
  * zquery build Build the zQuery library (dist/)
11
- * zquery build --watch Build & watch for library changes
12
11
  *
13
12
  * zquery bundle [entry] Bundle an app's ES modules into one file
14
13
  * zquery bundle scripts/app.js Specify entry explicitly
15
- * zquery bundle -o dist/ Custom output directory
16
- * zquery bundle --include-lib Embed zquery.min.js in the bundle
14
+ * zquery bundle -o build/ Custom output directory
15
+ * zquery bundle --html other.html Use a specific HTML file instead of auto-detected
17
16
  * zquery bundle --watch Watch & rebuild on changes
18
- * zquery bundle --html index.html Rewrite <script type="module"> to use bundle
19
17
  *
20
- * Output files use content-hashed names for cache-busting:
21
- * z-<entry>.<hash>.js / z-<entry>.<hash>.min.js
18
+ * Smart defaults (no flags needed for typical projects):
19
+ * - Entry is auto-detected from index.html's <script type="module" src="...">
20
+ * - zquery.min.js is always embedded (auto-built if not found)
21
+ * - index.html is always rewritten and assets are copied
22
+ * - Output goes to dist/ next to the detected index.html
22
23
  *
23
24
  * Examples:
24
- * cd my-zquery-app && npx zero-query bundle
25
- * npx zero-query bundle scripts/app.js -o dist/ --include-lib
25
+ * cd my-app && npx zero-query bundle # just works!
26
+ * npx zero-query bundle path/to/scripts/app.js # works from anywhere
26
27
  */
27
28
 
28
29
  const fs = require('fs');
@@ -410,38 +411,70 @@ function bundleApp() {
410
411
  process.exit(1);
411
412
  }
412
413
 
413
- const includeLib = flag('include-lib', 'L');
414
414
  const outPath = option('out', 'o', null);
415
- const htmlFile = option('html', null, null);
416
415
  const watchMode = flag('watch', 'w');
417
416
 
418
- // Derive output directory (filename is auto-generated with a content hash)
417
+ // Auto-detect index.html by walking up from the entry file, then check cwd
418
+ let htmlFile = option('html', null, null);
419
+ let htmlAbs = htmlFile ? path.resolve(projectRoot, htmlFile) : null;
420
+ if (!htmlFile) {
421
+ const htmlCandidates = [];
422
+ // Walk up from the entry file's directory to cwd looking for index.html
423
+ let entryDir = path.dirname(entry);
424
+ while (entryDir.length >= projectRoot.length) {
425
+ htmlCandidates.push(path.join(entryDir, 'index.html'));
426
+ const parent = path.dirname(entryDir);
427
+ if (parent === entryDir) break;
428
+ entryDir = parent;
429
+ }
430
+ // Also check cwd and public/
431
+ htmlCandidates.push(path.join(projectRoot, 'index.html'));
432
+ htmlCandidates.push(path.join(projectRoot, 'public/index.html'));
433
+ for (const candidate of htmlCandidates) {
434
+ if (fs.existsSync(candidate)) {
435
+ htmlAbs = candidate;
436
+ htmlFile = path.relative(projectRoot, candidate);
437
+ break;
438
+ }
439
+ }
440
+ }
441
+
442
+ // Derive output directory:
443
+ // -o flag → use that path
444
+ // else → dist/ next to the detected HTML file (or cwd/dist/ as fallback)
419
445
  const entryRel = path.relative(projectRoot, entry);
420
446
  const entryName = path.basename(entry, '.js');
421
- let distDir;
447
+ let baseDistDir;
422
448
  if (outPath) {
423
449
  const resolved = path.resolve(projectRoot, outPath);
424
- // -o accepts a directory path or a file path (directory is extracted)
425
450
  if (outPath.endsWith('/') || outPath.endsWith('\\') || !path.extname(outPath) ||
426
451
  (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory())) {
427
- distDir = resolved;
452
+ baseDistDir = resolved;
428
453
  } else {
429
- distDir = path.dirname(resolved);
454
+ baseDistDir = path.dirname(resolved);
430
455
  }
456
+ } else if (htmlAbs) {
457
+ baseDistDir = path.join(path.dirname(htmlAbs), 'dist');
431
458
  } else {
432
- distDir = path.join(projectRoot, 'dist');
459
+ baseDistDir = path.join(projectRoot, 'dist');
433
460
  }
434
461
 
462
+ // Two output sub-directories: server/ (with <base href="/">) and local/ (relative paths)
463
+ const serverDir = path.join(baseDistDir, 'server');
464
+ const localDir = path.join(baseDistDir, 'local');
465
+
435
466
  console.log(`\n zQuery App Bundler`);
436
467
  console.log(` Entry: ${entryRel}`);
437
- console.log(` Output: ${path.relative(projectRoot, distDir)}/z-${entryName}.[hash].js`);
438
- if (includeLib) console.log(` Library: embedded`);
468
+ console.log(` Output: ${path.relative(projectRoot, baseDistDir)}/server/ & local/`);
469
+ console.log(` Library: embedded`);
470
+ console.log(` HTML: ${htmlFile || 'not found (no index.html detected)'}`);
439
471
  console.log('');
440
472
 
441
473
  function doBuild() {
442
474
  const start = Date.now();
443
475
 
444
- if (!fs.existsSync(distDir)) fs.mkdirSync(distDir, { recursive: true });
476
+ if (!fs.existsSync(serverDir)) fs.mkdirSync(serverDir, { recursive: true });
477
+ if (!fs.existsSync(localDir)) fs.mkdirSync(localDir, { recursive: true });
445
478
 
446
479
  // Walk the import graph
447
480
  const files = walkImportGraph(entry);
@@ -457,26 +490,49 @@ function bundleApp() {
457
490
  return `// --- ${rel} ${'—'.repeat(Math.max(1, 60 - rel.length))}\n${code.trim()}`;
458
491
  });
459
492
 
460
- // Optionally prepend zquery.min.js
493
+ // Embed zquery.min.js — always included
461
494
  let libSection = '';
462
- if (includeLib) {
463
- // Look for the library in common locations
495
+ {
496
+ const pkgSrcDir = path.join(__dirname, 'src');
497
+ const pkgMinFile = path.join(__dirname, 'dist', 'zquery.min.js');
498
+
499
+ // Always rebuild the library from source when running from the repo/package
500
+ // so that dist/ stays current with the latest source changes.
501
+ if (fs.existsSync(pkgSrcDir) && fs.existsSync(path.join(__dirname, 'index.js'))) {
502
+ console.log(`\n Building library from source...`);
503
+ const prevCwd = process.cwd();
504
+ try {
505
+ process.chdir(__dirname);
506
+ buildLibrary();
507
+ } finally {
508
+ process.chdir(prevCwd);
509
+ }
510
+ }
511
+
512
+ // Now look for the library in common locations
513
+ const htmlDir = htmlAbs ? path.dirname(htmlAbs) : null;
464
514
  const libCandidates = [
515
+ // Prefer the freshly-built package dist
516
+ path.join(__dirname, 'dist/zquery.min.js'),
517
+ // Then check project-local locations
518
+ htmlDir && path.join(htmlDir, 'scripts/vendor/zquery.min.js'),
519
+ htmlDir && path.join(htmlDir, 'vendor/zquery.min.js'),
465
520
  path.join(projectRoot, 'scripts/vendor/zquery.min.js'),
466
521
  path.join(projectRoot, 'vendor/zquery.min.js'),
467
522
  path.join(projectRoot, 'lib/zquery.min.js'),
468
523
  path.join(projectRoot, 'dist/zquery.min.js'),
469
524
  path.join(projectRoot, 'zquery.min.js'),
470
- // If run from the zero-query repo itself
471
- path.join(__dirname, 'dist/zquery.min.js'),
472
- ];
525
+ ].filter(Boolean);
473
526
  const libPath = libCandidates.find(p => fs.existsSync(p));
527
+
474
528
  if (libPath) {
475
- libSection = `// --- zquery.min.js (library) ${'—'.repeat(34)}\n${fs.readFileSync(libPath, 'utf-8').trim()}\n\n`;
476
- console.log(`\n Embedded library from ${path.relative(projectRoot, libPath)}`);
529
+ const libBytes = fs.statSync(libPath).size;
530
+ libSection = `// --- zquery.min.js (library) ${'—'.repeat(34)}\n${fs.readFileSync(libPath, 'utf-8').trim()}\n\n`
531
+ + `// --- Build-time metadata ————————————————————————————\nif(typeof $!=="undefined"){$.meta=Object.assign($.meta||{},{libSize:${libBytes}});}\n\n`;
532
+ console.log(` Embedded library from ${path.relative(projectRoot, libPath)} (${(libBytes / 1024).toFixed(1)} KB)`);
477
533
  } else {
478
- console.warn(`\n ⚠ Could not find zquery.min.js — skipping --include-lib`);
479
- console.warn(` Build the library first: zquery build`);
534
+ console.warn(`\n ⚠ Could not find zquery.min.js anywhere`);
535
+ console.warn(` Place zquery.min.js in scripts/vendor/, vendor/, lib/, or dist/`);
480
536
  }
481
537
  }
482
538
 
@@ -503,28 +559,35 @@ function bundleApp() {
503
559
 
504
560
  // Content-hashed output filenames (z-<name>.<hash>.js)
505
561
  const contentHash = crypto.createHash('sha256').update(bundle).digest('hex').slice(0, 8);
506
- const bundleFile = path.join(distDir, `z-${entryName}.${contentHash}.js`);
507
- const minFile = path.join(distDir, `z-${entryName}.${contentHash}.min.js`);
562
+ const bundleBase = `z-${entryName}.${contentHash}.js`;
563
+ const minBase = `z-${entryName}.${contentHash}.min.js`;
508
564
 
509
- // Remove previous hashed builds
565
+ // Remove previous hashed builds from both output directories
510
566
  const escName = entryName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
511
567
  const cleanRe = new RegExp(`^z-${escName}\\.[a-f0-9]{8}\\.(?:min\\.)?js$`);
512
- if (fs.existsSync(distDir)) {
513
- for (const f of fs.readdirSync(distDir)) {
514
- if (cleanRe.test(f)) fs.unlinkSync(path.join(distDir, f));
568
+ for (const dir of [serverDir, localDir]) {
569
+ if (fs.existsSync(dir)) {
570
+ for (const f of fs.readdirSync(dir)) {
571
+ if (cleanRe.test(f)) fs.unlinkSync(path.join(dir, f));
572
+ }
515
573
  }
516
574
  }
517
575
 
576
+ // Write bundle into server/ (canonical), then copy to local/
577
+ const bundleFile = path.join(serverDir, bundleBase);
578
+ const minFile = path.join(serverDir, minBase);
518
579
  fs.writeFileSync(bundleFile, bundle, 'utf-8');
519
580
  fs.writeFileSync(minFile, minify(bundle, banner), 'utf-8');
581
+ fs.copyFileSync(bundleFile, path.join(localDir, bundleBase));
582
+ fs.copyFileSync(minFile, path.join(localDir, minBase));
520
583
 
521
- console.log(`\n ✓ ${path.relative(projectRoot, bundleFile)} (${sizeKB(fs.readFileSync(bundleFile))} KB)`);
522
- console.log(` ✓ ${path.relative(projectRoot, minFile)} (${sizeKB(fs.readFileSync(minFile))} KB)`);
584
+ console.log(`\n ✓ ${bundleBase} (${sizeKB(fs.readFileSync(bundleFile))} KB)`);
585
+ console.log(` ✓ ${minBase} (${sizeKB(fs.readFileSync(minFile))} KB)`);
523
586
 
524
- // Optionally rewrite index.html
587
+ // Rewrite index.html → two variants (server/ and local/)
525
588
  if (htmlFile) {
526
589
  const bundledFileSet = new Set(files);
527
- rewriteHtml(projectRoot, htmlFile, bundleFile, includeLib, bundledFileSet);
590
+ rewriteHtml(projectRoot, htmlFile, bundleFile, true, bundledFileSet, serverDir, localDir);
528
591
  }
529
592
 
530
593
  const elapsed = Date.now() - start;
@@ -572,18 +635,21 @@ function copyDirSync(src, dest) {
572
635
 
573
636
  /**
574
637
  * Rewrite an HTML file to replace the module <script> with the bundle.
575
- * Copies all referenced assets (CSS, JS, images) into dist/ so the
576
- * output folder is fully self-contained and deployable.
638
+ * Copies all referenced assets into both server/ and local/ dist dirs,
639
+ * then writes two index.html variants:
640
+ * server/index.html — has <base href="/"> for SPA deep-route support
641
+ * local/index.html — no <base>, relative paths for file:// access
642
+ *
643
+ * Both are fully static HTML with no dynamic loading.
577
644
  */
578
- function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFiles) {
645
+ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFiles, serverDir, localDir) {
579
646
  const htmlPath = path.resolve(projectRoot, htmlRelPath);
580
647
  if (!fs.existsSync(htmlPath)) {
581
648
  console.warn(` ⚠ HTML file not found: ${htmlRelPath}`);
582
649
  return;
583
650
  }
584
651
 
585
- const htmlDir = path.dirname(htmlPath);
586
- const distDir = path.dirname(bundleFile);
652
+ const htmlDir = path.dirname(htmlPath);
587
653
  let html = fs.readFileSync(htmlPath, 'utf-8');
588
654
 
589
655
  // Collect all asset references from the HTML (src=, href= on link/script/img)
@@ -592,37 +658,29 @@ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFi
592
658
  let m;
593
659
  while ((m = assetRe.exec(html)) !== null) {
594
660
  const ref = m[1];
595
- // Skip absolute URLs, data URIs, protocol-relative, and anchors
596
661
  if (ref.startsWith('http') || ref.startsWith('//') || ref.startsWith('data:') || ref.startsWith('#')) continue;
597
- // Skip the module entry (already bundled)
598
662
  const refAbs = path.resolve(htmlDir, ref);
599
663
  if (bundledFiles && bundledFiles.has(refAbs)) continue;
600
- // Skip zquery lib if we're embedding it
601
664
  if (includeLib && /zquery(?:\.min)?\.js$/i.test(ref)) continue;
602
665
  assets.add(ref);
603
666
  }
604
667
 
605
- // Copy each referenced asset into dist/, preserving directory structure
668
+ // Copy each referenced asset into BOTH dist dirs, preserving directory structure
606
669
  let copiedCount = 0;
607
- const copiedDirs = new Set();
608
670
  for (const asset of assets) {
609
671
  const srcFile = path.resolve(htmlDir, asset);
610
672
  if (!fs.existsSync(srcFile)) continue;
611
673
 
612
- const destFile = path.join(distDir, asset);
613
- const destDir = path.dirname(destFile);
614
- if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
615
-
616
- fs.copyFileSync(srcFile, destFile);
674
+ for (const distDir of [serverDir, localDir]) {
675
+ const destFile = path.join(distDir, asset);
676
+ const destDir = path.dirname(destFile);
677
+ if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
678
+ fs.copyFileSync(srcFile, destFile);
679
+ }
617
680
  copiedCount++;
618
-
619
- // If this is inside a directory that may contain sibling assets
620
- // (fonts referenced by CSS, etc.), track it
621
- copiedDirs.add(path.dirname(srcFile));
622
681
  }
623
682
 
624
- // Also copy any CSS-referenced assets: scan copied CSS files for url()
625
- // references and copy those too
683
+ // Also copy any CSS-referenced assets (fonts, images in url() etc.)
626
684
  for (const asset of assets) {
627
685
  const srcFile = path.resolve(htmlDir, asset);
628
686
  if (!fs.existsSync(srcFile) || !asset.endsWith('.css')) continue;
@@ -633,25 +691,27 @@ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFi
633
691
  while ((cm = urlRe.exec(cssContent)) !== null) {
634
692
  const ref = cm[1];
635
693
  if (ref.startsWith('data:') || ref.startsWith('http') || ref.startsWith('//')) continue;
636
- const cssSrcDir = path.dirname(srcFile);
637
- const assetSrc = path.resolve(cssSrcDir, ref);
638
- const cssDestDir = path.dirname(path.join(distDir, asset));
639
- const assetDest = path.resolve(cssDestDir, ref);
640
- if (fs.existsSync(assetSrc) && !fs.existsSync(assetDest)) {
641
- const dir = path.dirname(assetDest);
642
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
643
- fs.copyFileSync(assetSrc, assetDest);
644
- copiedCount++;
694
+ const cssSrcDir = path.dirname(srcFile);
695
+ const assetSrc = path.resolve(cssSrcDir, ref);
696
+ if (!fs.existsSync(assetSrc)) continue;
697
+
698
+ for (const distDir of [serverDir, localDir]) {
699
+ const cssDestDir = path.dirname(path.join(distDir, asset));
700
+ const assetDest = path.resolve(cssDestDir, ref);
701
+ if (!fs.existsSync(assetDest)) {
702
+ const dir = path.dirname(assetDest);
703
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
704
+ fs.copyFileSync(assetSrc, assetDest);
705
+ }
645
706
  }
707
+ copiedCount++;
646
708
  }
647
709
  }
648
710
 
649
- // Make the bundle path relative to the dist/ HTML
650
- const bundleRel = path.relative(distDir, bundleFile).replace(/\\/g, '/');
711
+ // Make the bundle filename relative (same name in both dirs)
712
+ const bundleRel = path.relative(serverDir, bundleFile).replace(/\\/g, '/');
651
713
 
652
- // Replace <script type="module" src="..."> with the bundle (regular script)
653
- // Use "defer" so the script runs after DOM is parsed — module scripts are
654
- // deferred by default, but regular scripts in <head> are not.
714
+ // Replace <script type="module" src="..."> with the bundle (defer)
655
715
  html = html.replace(
656
716
  /<script\s+type\s*=\s*["']module["']\s+src\s*=\s*["'][^"']+["']\s*>\s*<\/script>/gi,
657
717
  `<script defer src="${bundleRel}"></script>`
@@ -665,20 +725,23 @@ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFi
665
725
  );
666
726
  }
667
727
 
668
- // SPA deep-route fix: keep <base href="/"> so refreshing on a route like
669
- // /docs/project-structure still resolves assets from the root. However,
670
- // when opened via file:// the root is the drive letter (file:///C:/), so
671
- // inject a tiny inline script that switches the base to "./" for file://.
672
- html = html.replace(
673
- /(<base\s+href\s*=\s*["']\/["'][^>]*>)/i,
674
- '$1<script>if(location.protocol==="file:")document.querySelector("base").href="./"</script>'
675
- );
676
-
677
- // Write HTML
678
- const outHtml = path.join(distDir, path.basename(htmlRelPath));
679
- fs.writeFileSync(outHtml, html, 'utf-8');
680
- console.log(` ✓ ${path.relative(projectRoot, outHtml)} (HTML rewritten)`);
681
- console.log(` ✓ Copied ${copiedCount} asset(s) into ${path.relative(projectRoot, distDir)}/`);
728
+ // ── server/index.html ──
729
+ // Keep <base href="/"> as-is the preload scanner sees it, all resources
730
+ // resolve from root, deep-route refreshes work perfectly.
731
+ const serverHtml = html;
732
+
733
+ // ── local/index.html ──
734
+ // Remove <base href="/"> so relative paths resolve from the HTML file's
735
+ // directory — correct for file:// with zero console errors.
736
+ const localHtml = html.replace(/<base\s+href\s*=\s*["']\/["'][^>]*>\s*\n?\s*/i, '');
737
+
738
+ // Write both
739
+ const htmlName = path.basename(htmlRelPath);
740
+ fs.writeFileSync(path.join(serverDir, htmlName), serverHtml, 'utf-8');
741
+ fs.writeFileSync(path.join(localDir, htmlName), localHtml, 'utf-8');
742
+ console.log(` ✓ server/${htmlName} (with <base href="/">)`);
743
+ console.log(` ✓ local/${htmlName} (relative paths, file:// ready)`);
744
+ console.log(` ✓ Copied ${copiedCount} asset(s) into both dist dirs`);
682
745
  }
683
746
 
684
747
 
@@ -693,31 +756,54 @@ function showHelp() {
693
756
  COMMANDS
694
757
 
695
758
  build Build the zQuery library → dist/
696
- --watch, -w Watch src/ and rebuild on changes
759
+ (must be run from the project root where src/ lives)
697
760
 
698
761
  bundle [entry] Bundle app ES modules into a single file
699
- --out, -o <path> Output directory (default: dist/)
700
- --include-lib, -L Embed zquery.min.js in the bundle
701
- --html <file> Rewrite HTML file to reference the bundle
762
+ --out, -o <path> Output directory (default: dist/ next to index.html)
763
+ --html <file> Use a specific HTML file (default: auto-detected)
702
764
  --watch, -w Watch source files and rebuild on changes
703
765
 
766
+ SMART DEFAULTS
767
+
768
+ The bundler works with zero flags for typical projects:
769
+ • Entry is auto-detected from index.html <script type="module" src="...">
770
+ • zquery.min.js is always embedded (auto-built from source if not found)
771
+ • index.html is rewritten for both server and local (file://) use
772
+ • Output goes to dist/server/ and dist/local/ next to the detected index.html
773
+
704
774
  OUTPUT
705
775
 
706
- Bundle filenames are content-hashed for cache-busting:
707
- z-<entry>.<hash>.js readable bundle
708
- z-<entry>.<hash>.min.js minified bundle
776
+ The bundler produces two self-contained sub-directories:
777
+
778
+ dist/server/ deploy to your web server
779
+ index.html has <base href="/"> for SPA deep routes
780
+ z-<entry>.<hash>.js readable bundle
781
+ z-<entry>.<hash>.min.js minified bundle
782
+
783
+ dist/local/ open from disk (file://)
784
+ index.html relative paths, no <base> tag
785
+ z-<entry>.<hash>.js same bundle
786
+
709
787
  Previous hashed builds are automatically cleaned on each rebuild.
710
788
 
789
+ DEVELOPMENT
790
+
791
+ npm run serve start a local dev server (zero-http, SPA routing)
792
+ npm run dev watch mode — auto-rebuild bundle on source changes
793
+
711
794
  EXAMPLES
712
795
 
713
- # Build the library
796
+ # Build the library only
714
797
  zquery build
715
798
 
716
- # Bundle an app (auto-detects entry from index.html)
799
+ # Bundle an app auto-detects everything
717
800
  cd my-app && zquery bundle
718
801
 
719
- # Bundle with all options
720
- zquery bundle scripts/app.js -o dist/ -L --html index.html
802
+ # Point to an entry from a parent directory
803
+ zquery bundle path/to/scripts/app.js
804
+
805
+ # Custom output directory
806
+ zquery bundle -o build/
721
807
 
722
808
  # Watch mode
723
809
  zquery bundle --watch
@@ -739,20 +825,6 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
739
825
  } else if (command === 'build') {
740
826
  console.log('\n zQuery Library Build\n');
741
827
  buildLibrary();
742
- if (flag('watch', 'w')) {
743
- console.log(' Watching src/ for changes...\n');
744
- const srcDir = path.join(process.cwd(), 'src');
745
- let debounceTimer;
746
- const rebuild = () => {
747
- clearTimeout(debounceTimer);
748
- debounceTimer = setTimeout(() => {
749
- console.log(' Rebuilding...');
750
- try { buildLibrary(); } catch (e) { console.error(` ✗ ${e.message}`); }
751
- }, 200);
752
- };
753
- fs.watch(srcDir, { recursive: true }, rebuild);
754
- fs.watch(path.join(process.cwd(), 'index.js'), rebuild);
755
- }
756
828
  } else if (command === 'bundle') {
757
829
  bundleApp();
758
830
  } else {
Binary file