@fluffjs/cli 0.1.14 → 0.1.15

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.d.ts CHANGED
@@ -22,7 +22,12 @@ export declare class Cli {
22
22
  private buildTarget;
23
23
  private serve;
24
24
  private serveTarget;
25
- private generateEntryPoint;
25
+ private resolveEntryPoint;
26
+ private getEsbuildEntryConfig;
27
+ private getJsBundleName;
28
+ private collectStyles;
29
+ private loadTsConfig;
30
+ private generateEntryContent;
26
31
  private findAllTsFiles;
27
32
  private findFiles;
28
33
  private matchesPatterns;
package/Cli.js CHANGED
@@ -302,49 +302,16 @@ Examples:
302
302
  if (this.noMinify) {
303
303
  bundleOptions.minify = false;
304
304
  }
305
- const entryPoint = target.entryPoint
306
- ? path.join(srcDir, target.entryPoint)
307
- : this.generateEntryPoint(srcDir, target.exclude);
308
- let inlineStyles = '';
309
- if (target.styles && target.styles.length > 0) {
310
- const styleContents = [];
311
- for (const stylePath of target.styles) {
312
- const fullPath = path.resolve(srcDir, stylePath);
313
- if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
314
- console.log(` ✓ Style: ${stylePath}`);
315
- styleContents.push(fs.readFileSync(fullPath, 'utf-8'));
316
- }
317
- else {
318
- const styleFiles = this.findFiles(srcDir, [stylePath]);
319
- if (styleFiles.length === 0) {
320
- console.warn(` ⚠ Style not found: ${fullPath}`);
321
- }
322
- for (const styleFile of styleFiles) {
323
- console.log(` ✓ Style: ${path.relative(srcDir, styleFile)}`);
324
- styleContents.push(fs.readFileSync(styleFile, 'utf-8'));
325
- }
326
- }
327
- }
328
- if (styleContents.length > 0) {
329
- inlineStyles = styleContents.join('\n');
330
- if (bundleOptions.minify) {
331
- const cssResult = await esbuild.transform(inlineStyles, {
332
- loader: 'css',
333
- minify: true
334
- });
335
- inlineStyles = cssResult.code;
336
- }
337
- console.log(' ✓ Bundled global styles');
338
- }
339
- }
305
+ const entry = this.resolveEntryPoint(target, srcDir);
306
+ const inlineStyles = await this.collectStyles(target, srcDir, bundleOptions.minify ?? true);
340
307
  console.log(' Building with esbuild...');
341
- const tsconfigRaw = target.tsConfigPath
342
- ? fs.readFileSync(path.resolve(projectRoot, target.tsConfigPath), 'utf-8')
343
- : '{}';
308
+ const tsconfigRaw = this.loadTsConfig(target, projectRoot);
344
309
  const result = await esbuild.build({
345
- entryPoints: [entryPoint],
310
+ ...this.getEsbuildEntryConfig(entry),
346
311
  bundle: true,
347
- outdir: outDir,
312
+ ...(entry.useStdin
313
+ ? { outfile: path.join(outDir, 'fluff-app.js') }
314
+ : { outdir: outDir, entryNames: '[name]' }),
348
315
  format: 'esm',
349
316
  platform: 'browser',
350
317
  target: bundleOptions.target ?? 'es2022',
@@ -413,7 +380,7 @@ Examples:
413
380
  }
414
381
  }
415
382
  if (target.assets) {
416
- await this.copyAssets(target.assets, projectRoot, srcDir, outDir);
383
+ await this.copyAssets(target.assets, projectRoot, srcDir, outDir, target.indexHtml);
417
384
  }
418
385
  console.log(`✅ Target '${target.name}' built successfully!`);
419
386
  }
@@ -503,40 +470,14 @@ Examples:
503
470
  }
504
471
  }
505
472
  }
506
- const entryPoint = target.entryPoint
507
- ? path.join(srcDir, target.entryPoint)
508
- : this.generateEntryPoint(srcDir, target.exclude);
509
- let inlineStyles = '';
510
- if (target.styles && target.styles.length > 0) {
511
- const styleContents = [];
512
- for (const stylePath of target.styles) {
513
- const fullPath = path.resolve(srcDir, stylePath);
514
- if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
515
- console.log(` ✓ Style: ${stylePath}`);
516
- styleContents.push(fs.readFileSync(fullPath, 'utf-8'));
517
- }
518
- else {
519
- const styleFiles = this.findFiles(srcDir, [stylePath]);
520
- if (styleFiles.length === 0) {
521
- console.warn(` ⚠ Style not found: ${fullPath}`);
522
- }
523
- for (const styleFile of styleFiles) {
524
- console.log(` ✓ Style: ${path.relative(srcDir, styleFile)}`);
525
- styleContents.push(fs.readFileSync(styleFile, 'utf-8'));
526
- }
527
- }
528
- }
529
- if (styleContents.length > 0) {
530
- inlineStyles = styleContents.join('\n');
531
- }
532
- }
473
+ const entry = this.resolveEntryPoint(target, srcDir);
474
+ const inlineStyles = await this.collectStyles(target, srcDir, false);
533
475
  if (target.indexHtml) {
534
476
  const indexHtmlPath = path.join(srcDir, target.indexHtml);
535
477
  if (fs.existsSync(indexHtmlPath)) {
536
478
  const indexHtml = fs.readFileSync(indexHtmlPath, 'utf-8');
537
479
  const transformed = await IndexHtmlTransformer.transform(indexHtml, {
538
- jsBundle: path.basename(entryPoint)
539
- .replace('.ts', '.js'),
480
+ jsBundle: this.getJsBundleName(entry),
540
481
  cssBundle: undefined,
541
482
  inlineStyles: inlineStyles || undefined,
542
483
  gzip: false,
@@ -547,16 +488,16 @@ Examples:
547
488
  }
548
489
  }
549
490
  if (target.assets) {
550
- this.copyAssetsForServe(target.assets, projectRoot, srcDir, outDir);
491
+ this.copyAssetsForServe(target.assets, projectRoot, srcDir, outDir, target.indexHtml);
551
492
  }
552
493
  console.log(`🚀 Starting dev server for '${target.name}'...`);
553
- const tsconfigRaw = target.tsConfigPath
554
- ? fs.readFileSync(path.resolve(projectRoot, target.tsConfigPath), 'utf-8')
555
- : '{}';
494
+ const tsconfigRaw = this.loadTsConfig(target, projectRoot);
556
495
  const ctx = await esbuild.context({
557
- entryPoints: [entryPoint],
496
+ ...this.getEsbuildEntryConfig(entry),
558
497
  bundle: true,
559
- outdir: outDir,
498
+ ...(entry.useStdin
499
+ ? { outfile: path.join(outDir, 'fluff-app.js') }
500
+ : { outdir: outDir, entryNames: '[name]' }),
560
501
  format: 'esm',
561
502
  platform: 'browser',
562
503
  target: 'es2022',
@@ -605,7 +546,72 @@ Examples:
605
546
  console.log(' Press Ctrl+C to stop\n');
606
547
  }
607
548
  }
608
- generateEntryPoint(srcDir, exclude = []) {
549
+ resolveEntryPoint(target, srcDir) {
550
+ const useStdin = !target.entryPoint;
551
+ const entryPointFile = target.entryPoint ? path.join(srcDir, target.entryPoint) : null;
552
+ const generatedEntry = useStdin ? this.generateEntryContent(srcDir, target.exclude) : null;
553
+ return { useStdin, entryPointFile, generatedEntry };
554
+ }
555
+ getEsbuildEntryConfig(entry) {
556
+ if (entry.useStdin && entry.generatedEntry) {
557
+ return {
558
+ stdin: {
559
+ contents: entry.generatedEntry.contents,
560
+ resolveDir: entry.generatedEntry.resolveDir,
561
+ loader: 'ts'
562
+ }
563
+ };
564
+ }
565
+ return { entryPoints: [entry.entryPointFile ?? ''] };
566
+ }
567
+ getJsBundleName(entry) {
568
+ if (entry.useStdin) {
569
+ return 'fluff-app.js';
570
+ }
571
+ return path.basename(entry.entryPointFile ?? '').replace('.ts', '.js');
572
+ }
573
+ async collectStyles(target, srcDir, minify) {
574
+ if (!target.styles || target.styles.length === 0) {
575
+ return '';
576
+ }
577
+ const styleContents = [];
578
+ for (const stylePath of target.styles) {
579
+ const fullPath = path.resolve(srcDir, stylePath);
580
+ if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
581
+ console.log(` ✓ Style: ${stylePath}`);
582
+ styleContents.push(fs.readFileSync(fullPath, 'utf-8'));
583
+ }
584
+ else {
585
+ const styleFiles = this.findFiles(srcDir, [stylePath]);
586
+ if (styleFiles.length === 0) {
587
+ console.warn(` ⚠ Style not found: ${fullPath}`);
588
+ }
589
+ for (const styleFile of styleFiles) {
590
+ console.log(` ✓ Style: ${path.relative(srcDir, styleFile)}`);
591
+ styleContents.push(fs.readFileSync(styleFile, 'utf-8'));
592
+ }
593
+ }
594
+ }
595
+ if (styleContents.length === 0) {
596
+ return '';
597
+ }
598
+ let inlineStyles = styleContents.join('\n');
599
+ if (minify) {
600
+ const cssResult = await esbuild.transform(inlineStyles, {
601
+ loader: 'css',
602
+ minify: true
603
+ });
604
+ inlineStyles = cssResult.code;
605
+ }
606
+ console.log(' ✓ Bundled global styles');
607
+ return inlineStyles;
608
+ }
609
+ loadTsConfig(target, projectRoot) {
610
+ return target.tsConfigPath
611
+ ? fs.readFileSync(path.resolve(projectRoot, target.tsConfigPath), 'utf-8')
612
+ : '{}';
613
+ }
614
+ generateEntryContent(srcDir, exclude = []) {
609
615
  const tsFiles = this.findAllTsFiles(srcDir, exclude);
610
616
  for (const f of tsFiles) {
611
617
  console.log(` ✓ ${path.relative(srcDir, f)}`);
@@ -617,9 +623,7 @@ Examples:
617
623
  });
618
624
  const program = t.program(importDecls);
619
625
  const entryContent = generate(program, { compact: false }).code;
620
- const entryPath = path.join(srcDir, '__generated_entry.ts');
621
- fs.writeFileSync(entryPath, entryContent);
622
- return entryPath;
626
+ return { contents: entryContent, resolveDir: srcDir };
623
627
  }
624
628
  findAllTsFiles(dir, userExclude = []) {
625
629
  const files = [];
@@ -632,7 +636,8 @@ Examples:
632
636
  walk(fullPath);
633
637
  }
634
638
  else if (entry.isFile() && entry.name.endsWith('.ts')) {
635
- const relativePath = path.relative(dir, fullPath).replace(/\\/g, '/');
639
+ const relativePath = path.relative(dir, fullPath)
640
+ .replace(/\\/g, '/');
636
641
  const isExcluded = excludePatterns.some(pattern => this.matchGlob(entry.name, pattern) || this.matchGlob(relativePath, pattern));
637
642
  if (!isExcluded) {
638
643
  files.push(fullPath);
@@ -666,7 +671,8 @@ Examples:
666
671
  matchesPatterns(filePath, patterns, baseDir) {
667
672
  for (const pattern of patterns) {
668
673
  const patternPath = path.join(baseDir, pattern);
669
- if (fs.existsSync(patternPath) && fs.statSync(patternPath).isDirectory()) {
674
+ if (fs.existsSync(patternPath) && fs.statSync(patternPath)
675
+ .isDirectory()) {
670
676
  const normalizedFile = filePath.replace(/\\/g, '/');
671
677
  const normalizedPattern = pattern.replace(/\\/g, '/');
672
678
  if (normalizedFile.startsWith(normalizedPattern + '/') || normalizedFile === normalizedPattern) {
@@ -684,11 +690,12 @@ Examples:
684
690
  const isMatch = picomatch(pattern, { dot: false });
685
691
  return isMatch(normalizedPath);
686
692
  }
687
- async copyAssets(assets, projectRoot, srcDir, outDir) {
693
+ async copyAssets(assets, projectRoot, srcDir, outDir, indexHtml) {
688
694
  const compiler = new ComponentCompiler();
689
695
  for (const asset of assets) {
690
696
  const assetPath = path.resolve(srcDir, asset);
691
- if (fs.existsSync(assetPath) && fs.statSync(assetPath).isDirectory()) {
697
+ if (fs.existsSync(assetPath) && fs.statSync(assetPath)
698
+ .isDirectory()) {
692
699
  const dirName = path.basename(assetPath);
693
700
  const targetDir = path.join(outDir, dirName);
694
701
  await this.copyDirectoryRecursive(assetPath, targetDir, compiler);
@@ -704,6 +711,8 @@ Examples:
704
711
  if (filePath.endsWith('.component.css'))
705
712
  continue;
706
713
  const relativePath = path.relative(srcDir, filePath);
714
+ if (indexHtml && relativePath === indexHtml)
715
+ continue;
707
716
  const outPath = path.join(outDir, relativePath);
708
717
  const outFileDir = path.dirname(outPath);
709
718
  if (!fs.existsSync(outFileDir)) {
@@ -723,10 +732,11 @@ Examples:
723
732
  }
724
733
  }
725
734
  }
726
- copyAssetsForServe(assets, projectRoot, srcDir, outDir) {
735
+ copyAssetsForServe(assets, projectRoot, srcDir, outDir, indexHtml) {
727
736
  for (const asset of assets) {
728
737
  const assetPath = path.resolve(srcDir, asset);
729
- if (fs.existsSync(assetPath) && fs.statSync(assetPath).isDirectory()) {
738
+ if (fs.existsSync(assetPath) && fs.statSync(assetPath)
739
+ .isDirectory()) {
730
740
  const dirName = path.basename(assetPath);
731
741
  const targetDir = path.join(outDir, dirName);
732
742
  this.copyDirectoryRecursiveSync(assetPath, targetDir);
@@ -743,6 +753,8 @@ Examples:
743
753
  if (filePath.endsWith('.ts'))
744
754
  continue;
745
755
  const relativePath = path.relative(srcDir, filePath);
756
+ if (indexHtml && relativePath === indexHtml)
757
+ continue;
746
758
  const outPath = path.join(outDir, relativePath);
747
759
  const outFileDir = path.dirname(outPath);
748
760
  if (!fs.existsSync(outFileDir)) {
@@ -3,8 +3,8 @@ import { parse } from '@babel/parser';
3
3
  import * as t from '@babel/types';
4
4
  import * as esbuild from 'esbuild';
5
5
  import * as fs from 'fs';
6
- import * as parse5 from 'parse5';
7
6
  import { minify as minifyHtml } from 'html-minifier-terser';
7
+ import * as parse5 from 'parse5';
8
8
  import * as path from 'path';
9
9
  import { SourceMapConsumer, SourceMapGenerator } from 'source-map';
10
10
  import classTransformPlugin from './babel-plugin-class-transform.js';
package/DevServer.js CHANGED
@@ -1,6 +1,6 @@
1
- import * as http from 'node:http';
2
- import * as fs from 'node:fs';
3
1
  import httpProxy from 'http-proxy';
2
+ import * as fs from 'node:fs';
3
+ import * as http from 'node:http';
4
4
  export class DevServer {
5
5
  options;
6
6
  proxy;
package/Typeguards.d.ts CHANGED
@@ -20,5 +20,11 @@ export declare class Typeguards {
20
20
  startOffset: number;
21
21
  endOffset: number;
22
22
  }>;
23
+ static hasPipeN(value: unknown): value is {
24
+ n: unknown;
25
+ };
26
+ static hasPipeA(value: unknown): value is {
27
+ a: unknown[];
28
+ };
23
29
  }
24
30
  //# sourceMappingURL=Typeguards.d.ts.map
package/Typeguards.js CHANGED
@@ -27,4 +27,10 @@ export class Typeguards {
27
27
  static isAttrsRecord(value) {
28
28
  return value !== null && typeof value === 'object';
29
29
  }
30
+ static hasPipeN(value) {
31
+ return value !== null && typeof value === 'object' && 'n' in value;
32
+ }
33
+ static hasPipeA(value) {
34
+ return value !== null && typeof value === 'object' && 'a' in value && Array.isArray(value.a);
35
+ }
30
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluffjs/cli",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",