xpine 0.0.48 → 0.0.49

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/README.md CHANGED
@@ -426,4 +426,30 @@ setupEnv also supports AWS secrets manager. Simply add SECRETS_NAME=your_aws_sec
426
426
 
427
427
  1. Add script to src/public/scripts/pages/your_script.ts
428
428
  2. Import script into page HTML (e.g. `<script src="/scripts/pages/your_script.ts">`)
429
- 3. To unload event listeners, use `window.addEventListener('spa-update-page-url', () => { remove event listeners here})` in the code
429
+ 3. To unload event listeners, use `window.addEventListener('spa-update-page-url', () => { remove event listeners here})` in the code
430
+
431
+ ### Separate client side bundles
432
+
433
+ You can create separate client side bundles in xpine.config.mjs like this:
434
+
435
+ ```
436
+ export default {
437
+ bundles: [
438
+ {
439
+ id: 'site',
440
+ excludePaths: [
441
+ // Excludes SecretPageData
442
+ '/**/pages/secret/**/*.{js,ts,tsx,jsx}',
443
+ '/**/pages/secret/*.{js,ts,tsx,jsx}',
444
+ ],
445
+ },
446
+ {
447
+ id: 'secret-page',
448
+ includePaths: [
449
+ // Only uses Alpine data coming from paths in this directory
450
+ '/**/pages/secret/**/*.{js,ts,tsx,jsx}',
451
+ ]
452
+ }
453
+ ]
454
+ }
455
+ ```
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import chokidar from "chokidar";
9
9
  import path6 from "path";
10
10
  import fs7 from "fs-extra";
11
11
  import { build } from "esbuild";
12
+ import micromatch from "micromatch";
12
13
 
13
14
  // src/build/typescript-builder.ts
14
15
  import ts from "typescript";
@@ -780,8 +781,27 @@ async function buildApp(args) {
780
781
  if (removePreviousBuild) fs7.removeSync(config.distDir);
781
782
  const srcDirFiles = globSync3(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
782
783
  const { componentData, dataFiles } = await buildAppFiles(srcDirFiles, isDev2);
784
+ const clientSideBundles = [];
785
+ if (config?.bundles?.length) {
786
+ for (const bundle of config.bundles) {
787
+ const matchingComponentData = componentData?.filter((item) => {
788
+ return !micromatch([item.path], bundle?.excludePaths || [])?.length;
789
+ })?.filter((item) => {
790
+ if (!bundle?.includePaths?.length) return true;
791
+ return micromatch([item.path], bundle?.includePaths || [])?.length;
792
+ });
793
+ const matchingDataFiles = dataFiles?.filter((item) => {
794
+ return !micromatch([item.path], bundle?.excludePaths || [])?.length;
795
+ })?.filter((item) => {
796
+ if (!bundle?.includePaths?.length) return true;
797
+ return micromatch([item.path], bundle?.includePaths || [])?.length;
798
+ });
799
+ const alpineDataFile2 = await buildAlpineDataFile(matchingComponentData, matchingDataFiles, bundle.id);
800
+ await buildClientSideFiles([alpineDataFile2], isDev2, `./${bundle.id}.ts`, bundle.id);
801
+ }
802
+ }
783
803
  const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
784
- await buildClientSideFiles([alpineDataFile], isDev2);
804
+ await buildClientSideFiles([alpineDataFile, ...clientSideBundles], isDev2);
785
805
  fs7.removeSync(config.distTempFolder);
786
806
  await buildCSS(disableTailwind);
787
807
  await buildPublicFolderSymlinks();
@@ -825,8 +845,8 @@ async function buildAppFiles(files, isDev2) {
825
845
  dataFiles
826
846
  };
827
847
  }
828
- async function buildClientSideFiles(alpineDataFiles = [], isDev2) {
829
- const tempFilePath = path6.join(config.distTempFolder, "./app.ts");
848
+ async function buildClientSideFiles(alpineDataFiles = [], isDev2, tempClientSidePath, id) {
849
+ const tempFilePath = path6.join(config.distTempFolder, tempClientSidePath || "./app.ts");
830
850
  fs7.ensureFileSync(tempFilePath);
831
851
  const pagesScriptsGlob = config.publicDir + "/scripts/pages/**/*.{js,ts}";
832
852
  const clientFiles = globSync3(
@@ -853,7 +873,7 @@ async function buildClientSideFiles(alpineDataFiles = [], isDev2) {
853
873
  minify: !isDev2,
854
874
  sourcemap: isDev2 ? "inline" : false
855
875
  });
856
- await logSize(config.distPublicDir, "client");
876
+ await logSize(config.distPublicDir, id ? `client bundle: ${id}.js` : "client bundle: app.js");
857
877
  }
858
878
  function writeDevServerClientSideCode(tempFilePath) {
859
879
  const devServerPath = path6.join(xpineDistDir, "./src/static/dev-server.js");
@@ -865,7 +885,7 @@ function writeSpaClientSideCode(tempFilePath) {
865
885
  const content = fs7.readFileSync(spaPath, "utf-8");
866
886
  fs7.appendFileSync(tempFilePath, "\n" + content);
867
887
  }
868
- async function buildAlpineDataFile(componentData, dataFiles) {
888
+ async function buildAlpineDataFile(componentData, dataFiles, bundleID) {
869
889
  const output = {
870
890
  imports: [
871
891
  "import Alpine from 'alpinejs';"
@@ -909,9 +929,16 @@ async function buildAlpineDataFile(componentData, dataFiles) {
909
929
  output.code.push(`Alpine.data('${dataFunction.name}', ${dataFunction.name});`);
910
930
  }
911
931
  const result = output.imports.join("\n") + "\n" + output.code.join("\n") + "\n" + output.end.join("\n");
912
- fs7.ensureFileSync(config.alpineDataPath);
913
- fs7.writeFileSync(config.alpineDataPath, result);
914
- return config.alpineDataPath;
932
+ if (bundleID) {
933
+ const bundlePath = path6.join(config.distTempFolder, `./alpine-data-${bundleID}.ts`);
934
+ fs7.ensureFileSync(bundlePath);
935
+ fs7.writeFileSync(bundlePath, result);
936
+ return bundlePath;
937
+ } else {
938
+ fs7.ensureFileSync(config.alpineDataPath);
939
+ fs7.writeFileSync(config.alpineDataPath, result);
940
+ return config.alpineDataPath;
941
+ }
915
942
  }
916
943
  async function buildPublicFolderSymlinks() {
917
944
  const files = globSync3(config.publicDir + "/**/*.*", {
@@ -6,7 +6,7 @@ type BuildAppArgs = {
6
6
  };
7
7
  export declare function buildApp(args: BuildAppArgs): Promise<void>;
8
8
  export declare function buildPublicFolderSymlinks(): Promise<void>;
9
- export declare function logSize(pathName: string, type: 'app' | 'client' | 'css', validExtensions?: string[]): Promise<void>;
9
+ export declare function logSize(pathName: string, type: string, validExtensions?: string[]): Promise<void>;
10
10
  export declare function buildFilesWithConfigs(componentData: ComponentData[]): Promise<void>;
11
11
  export declare function buildStaticFiles(config: ConfigFile, component: ComponentData, componentImport: any, builtComponentPath: string): Promise<void>;
12
12
  export declare function getComponentDynamicPaths(componentPath: string): string[];
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/scripts/build.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,UAAU,EAA2B,aAAa,EAAE,MAAM,aAAa,CAAC;AAajF,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAA;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,iBAsBhD;AAiJD,wBAAsB,yBAAyB,kBAgB9C;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,EAAE,eAAe,WAAkB,iBAahH;AAED,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,aAAa,EAAE,iBAezE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,iBAyEpI;AAED,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAQxE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAA;AAGD,wBAAsB,eAAe,CAAC,aAAa,EAAE,aAAa,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,iBAoDpF"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/scripts/build.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,UAAU,EAA2B,aAAa,EAAE,MAAM,aAAa,CAAC;AAajF,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAA;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,iBA+ChD;AAwJD,wBAAsB,yBAAyB,kBAgB9C;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,WAAkB,iBAa9F;AAED,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,aAAa,EAAE,iBAezE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,iBAyEpI;AAED,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAQxE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAA;AAGD,wBAAsB,eAAe,CAAC,aAAa,EAAE,aAAa,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,iBAoDpF"}
@@ -4,6 +4,7 @@
4
4
  import path5 from "path";
5
5
  import fs7 from "fs-extra";
6
6
  import { build } from "esbuild";
7
+ import micromatch from "micromatch";
7
8
 
8
9
  // src/build/typescript-builder.ts
9
10
  import ts from "typescript";
@@ -573,8 +574,27 @@ async function buildApp(args) {
573
574
  if (removePreviousBuild2) fs7.removeSync(config.distDir);
574
575
  const srcDirFiles = globSync3(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
575
576
  const { componentData, dataFiles } = await buildAppFiles(srcDirFiles, isDev3);
577
+ const clientSideBundles = [];
578
+ if (config?.bundles?.length) {
579
+ for (const bundle of config.bundles) {
580
+ const matchingComponentData = componentData?.filter((item) => {
581
+ return !micromatch([item.path], bundle?.excludePaths || [])?.length;
582
+ })?.filter((item) => {
583
+ if (!bundle?.includePaths?.length) return true;
584
+ return micromatch([item.path], bundle?.includePaths || [])?.length;
585
+ });
586
+ const matchingDataFiles = dataFiles?.filter((item) => {
587
+ return !micromatch([item.path], bundle?.excludePaths || [])?.length;
588
+ })?.filter((item) => {
589
+ if (!bundle?.includePaths?.length) return true;
590
+ return micromatch([item.path], bundle?.includePaths || [])?.length;
591
+ });
592
+ const alpineDataFile2 = await buildAlpineDataFile(matchingComponentData, matchingDataFiles, bundle.id);
593
+ await buildClientSideFiles([alpineDataFile2], isDev3, `./${bundle.id}.ts`, bundle.id);
594
+ }
595
+ }
576
596
  const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
577
- await buildClientSideFiles([alpineDataFile], isDev3);
597
+ await buildClientSideFiles([alpineDataFile, ...clientSideBundles], isDev3);
578
598
  fs7.removeSync(config.distTempFolder);
579
599
  await buildCSS(disableTailwind2);
580
600
  await buildPublicFolderSymlinks();
@@ -618,8 +638,8 @@ async function buildAppFiles(files, isDev3) {
618
638
  dataFiles
619
639
  };
620
640
  }
621
- async function buildClientSideFiles(alpineDataFiles = [], isDev3) {
622
- const tempFilePath = path5.join(config.distTempFolder, "./app.ts");
641
+ async function buildClientSideFiles(alpineDataFiles = [], isDev3, tempClientSidePath, id) {
642
+ const tempFilePath = path5.join(config.distTempFolder, tempClientSidePath || "./app.ts");
623
643
  fs7.ensureFileSync(tempFilePath);
624
644
  const pagesScriptsGlob = config.publicDir + "/scripts/pages/**/*.{js,ts}";
625
645
  const clientFiles = globSync3(
@@ -646,7 +666,7 @@ async function buildClientSideFiles(alpineDataFiles = [], isDev3) {
646
666
  minify: !isDev3,
647
667
  sourcemap: isDev3 ? "inline" : false
648
668
  });
649
- await logSize(config.distPublicDir, "client");
669
+ await logSize(config.distPublicDir, id ? `client bundle: ${id}.js` : "client bundle: app.js");
650
670
  }
651
671
  function writeDevServerClientSideCode(tempFilePath) {
652
672
  const devServerPath = path5.join(xpineDistDir, "./src/static/dev-server.js");
@@ -658,7 +678,7 @@ function writeSpaClientSideCode(tempFilePath) {
658
678
  const content = fs7.readFileSync(spaPath, "utf-8");
659
679
  fs7.appendFileSync(tempFilePath, "\n" + content);
660
680
  }
661
- async function buildAlpineDataFile(componentData, dataFiles) {
681
+ async function buildAlpineDataFile(componentData, dataFiles, bundleID) {
662
682
  const output = {
663
683
  imports: [
664
684
  "import Alpine from 'alpinejs';"
@@ -702,9 +722,16 @@ async function buildAlpineDataFile(componentData, dataFiles) {
702
722
  output.code.push(`Alpine.data('${dataFunction.name}', ${dataFunction.name});`);
703
723
  }
704
724
  const result = output.imports.join("\n") + "\n" + output.code.join("\n") + "\n" + output.end.join("\n");
705
- fs7.ensureFileSync(config.alpineDataPath);
706
- fs7.writeFileSync(config.alpineDataPath, result);
707
- return config.alpineDataPath;
725
+ if (bundleID) {
726
+ const bundlePath = path5.join(config.distTempFolder, `./alpine-data-${bundleID}.ts`);
727
+ fs7.ensureFileSync(bundlePath);
728
+ fs7.writeFileSync(bundlePath, result);
729
+ return bundlePath;
730
+ } else {
731
+ fs7.ensureFileSync(config.alpineDataPath);
732
+ fs7.writeFileSync(config.alpineDataPath, result);
733
+ return config.alpineDataPath;
734
+ }
708
735
  }
709
736
  async function buildPublicFolderSymlinks() {
710
737
  const files = globSync3(config.publicDir + "/**/*.*", {
@@ -11,6 +11,7 @@ import chokidar from "chokidar";
11
11
  import path5 from "path";
12
12
  import fs7 from "fs-extra";
13
13
  import { build } from "esbuild";
14
+ import micromatch from "micromatch";
14
15
 
15
16
  // src/build/typescript-builder.ts
16
17
  import ts from "typescript";
@@ -580,8 +581,27 @@ async function buildApp(args) {
580
581
  if (removePreviousBuild) fs7.removeSync(config.distDir);
581
582
  const srcDirFiles = globSync3(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
582
583
  const { componentData, dataFiles } = await buildAppFiles(srcDirFiles, isDev2);
584
+ const clientSideBundles = [];
585
+ if (config?.bundles?.length) {
586
+ for (const bundle of config.bundles) {
587
+ const matchingComponentData = componentData?.filter((item) => {
588
+ return !micromatch([item.path], bundle?.excludePaths || [])?.length;
589
+ })?.filter((item) => {
590
+ if (!bundle?.includePaths?.length) return true;
591
+ return micromatch([item.path], bundle?.includePaths || [])?.length;
592
+ });
593
+ const matchingDataFiles = dataFiles?.filter((item) => {
594
+ return !micromatch([item.path], bundle?.excludePaths || [])?.length;
595
+ })?.filter((item) => {
596
+ if (!bundle?.includePaths?.length) return true;
597
+ return micromatch([item.path], bundle?.includePaths || [])?.length;
598
+ });
599
+ const alpineDataFile2 = await buildAlpineDataFile(matchingComponentData, matchingDataFiles, bundle.id);
600
+ await buildClientSideFiles([alpineDataFile2], isDev2, `./${bundle.id}.ts`, bundle.id);
601
+ }
602
+ }
583
603
  const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
584
- await buildClientSideFiles([alpineDataFile], isDev2);
604
+ await buildClientSideFiles([alpineDataFile, ...clientSideBundles], isDev2);
585
605
  fs7.removeSync(config.distTempFolder);
586
606
  await buildCSS(disableTailwind);
587
607
  await buildPublicFolderSymlinks();
@@ -625,8 +645,8 @@ async function buildAppFiles(files, isDev2) {
625
645
  dataFiles
626
646
  };
627
647
  }
628
- async function buildClientSideFiles(alpineDataFiles = [], isDev2) {
629
- const tempFilePath = path5.join(config.distTempFolder, "./app.ts");
648
+ async function buildClientSideFiles(alpineDataFiles = [], isDev2, tempClientSidePath, id) {
649
+ const tempFilePath = path5.join(config.distTempFolder, tempClientSidePath || "./app.ts");
630
650
  fs7.ensureFileSync(tempFilePath);
631
651
  const pagesScriptsGlob = config.publicDir + "/scripts/pages/**/*.{js,ts}";
632
652
  const clientFiles = globSync3(
@@ -653,7 +673,7 @@ async function buildClientSideFiles(alpineDataFiles = [], isDev2) {
653
673
  minify: !isDev2,
654
674
  sourcemap: isDev2 ? "inline" : false
655
675
  });
656
- await logSize(config.distPublicDir, "client");
676
+ await logSize(config.distPublicDir, id ? `client bundle: ${id}.js` : "client bundle: app.js");
657
677
  }
658
678
  function writeDevServerClientSideCode(tempFilePath) {
659
679
  const devServerPath = path5.join(xpineDistDir, "./src/static/dev-server.js");
@@ -665,7 +685,7 @@ function writeSpaClientSideCode(tempFilePath) {
665
685
  const content = fs7.readFileSync(spaPath, "utf-8");
666
686
  fs7.appendFileSync(tempFilePath, "\n" + content);
667
687
  }
668
- async function buildAlpineDataFile(componentData, dataFiles) {
688
+ async function buildAlpineDataFile(componentData, dataFiles, bundleID) {
669
689
  const output = {
670
690
  imports: [
671
691
  "import Alpine from 'alpinejs';"
@@ -709,9 +729,16 @@ async function buildAlpineDataFile(componentData, dataFiles) {
709
729
  output.code.push(`Alpine.data('${dataFunction.name}', ${dataFunction.name});`);
710
730
  }
711
731
  const result = output.imports.join("\n") + "\n" + output.code.join("\n") + "\n" + output.end.join("\n");
712
- fs7.ensureFileSync(config.alpineDataPath);
713
- fs7.writeFileSync(config.alpineDataPath, result);
714
- return config.alpineDataPath;
732
+ if (bundleID) {
733
+ const bundlePath = path5.join(config.distTempFolder, `./alpine-data-${bundleID}.ts`);
734
+ fs7.ensureFileSync(bundlePath);
735
+ fs7.writeFileSync(bundlePath, result);
736
+ return bundlePath;
737
+ } else {
738
+ fs7.ensureFileSync(config.alpineDataPath);
739
+ fs7.writeFileSync(config.alpineDataPath, result);
740
+ return config.alpineDataPath;
741
+ }
715
742
  }
716
743
  async function buildPublicFolderSymlinks() {
717
744
  const files = globSync3(config.publicDir + "/**/*.*", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xpine",
3
- "version": "0.0.48",
3
+ "version": "0.0.49",
4
4
  "main": "dist/index.js",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-secrets-manager": "^3.758.0",
@@ -14,6 +14,7 @@
14
14
  "fs-extra": "^11.3.0",
15
15
  "glob": "^11.0.1",
16
16
  "jsonwebtoken": "^9.0.2",
17
+ "micromatch": "^4.0.8",
17
18
  "postcss": "^8.5.3",
18
19
  "request-ip": "^3.3.0",
19
20
  "shelljs": "^0.9.2",
@@ -48,6 +49,7 @@
48
49
  "@eslint/js": "^9.24.0",
49
50
  "@tailwindcss/oxide-darwin-arm64": "^4.1.3",
50
51
  "@types/express": "^5.0.0",
52
+ "@types/micromatch": "^4.0.9",
51
53
  "@types/node": "^22.13.5",
52
54
  "@types/request-ip": "^0.0.41",
53
55
  "@types/shelljs": "^0.8.15",