@pyreon/compiler 0.5.0 → 0.5.2

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.
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"df2f33b4-1","name":"jsx.ts"},{"uid":"df2f33b4-3","name":"react-intercept.ts"},{"uid":"df2f33b4-5","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"df2f33b4-1":{"renderedLength":24622,"gzipLength":6908,"brotliLength":0,"metaUid":"df2f33b4-0"},"df2f33b4-3":{"renderedLength":27615,"gzipLength":6898,"brotliLength":0,"metaUid":"df2f33b4-2"},"df2f33b4-5":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"df2f33b4-4"}},"nodeMetas":{"df2f33b4-0":{"id":"/src/jsx.ts","moduleParts":{"index.js":"df2f33b4-1"},"imported":[{"uid":"df2f33b4-6"}],"importedBy":[{"uid":"df2f33b4-4"}]},"df2f33b4-2":{"id":"/src/react-intercept.ts","moduleParts":{"index.js":"df2f33b4-3"},"imported":[{"uid":"df2f33b4-6"}],"importedBy":[{"uid":"df2f33b4-4"}]},"df2f33b4-4":{"id":"/src/index.ts","moduleParts":{"index.js":"df2f33b4-5"},"imported":[{"uid":"df2f33b4-0"},{"uid":"df2f33b4-2"}],"importedBy":[],"isEntry":true},"df2f33b4-6":{"id":"typescript","moduleParts":{},"imported":[],"importedBy":[{"uid":"df2f33b4-0"},{"uid":"df2f33b4-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"a8a3634b-1","name":"jsx.ts"},{"uid":"a8a3634b-3","name":"project-scanner.ts"},{"uid":"a8a3634b-5","name":"react-intercept.ts"},{"uid":"a8a3634b-7","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"a8a3634b-1":{"renderedLength":24622,"gzipLength":6908,"brotliLength":0,"metaUid":"a8a3634b-0"},"a8a3634b-3":{"renderedLength":4762,"gzipLength":1730,"brotliLength":0,"metaUid":"a8a3634b-2"},"a8a3634b-5":{"renderedLength":27615,"gzipLength":6898,"brotliLength":0,"metaUid":"a8a3634b-4"},"a8a3634b-7":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"a8a3634b-6"}},"nodeMetas":{"a8a3634b-0":{"id":"/src/jsx.ts","moduleParts":{"index.js":"a8a3634b-1"},"imported":[{"uid":"a8a3634b-8"}],"importedBy":[{"uid":"a8a3634b-6"}]},"a8a3634b-2":{"id":"/src/project-scanner.ts","moduleParts":{"index.js":"a8a3634b-3"},"imported":[{"uid":"a8a3634b-9"},{"uid":"a8a3634b-10"}],"importedBy":[{"uid":"a8a3634b-6"}]},"a8a3634b-4":{"id":"/src/react-intercept.ts","moduleParts":{"index.js":"a8a3634b-5"},"imported":[{"uid":"a8a3634b-8"}],"importedBy":[{"uid":"a8a3634b-6"}]},"a8a3634b-6":{"id":"/src/index.ts","moduleParts":{"index.js":"a8a3634b-7"},"imported":[{"uid":"a8a3634b-0"},{"uid":"a8a3634b-2"},{"uid":"a8a3634b-4"}],"importedBy":[],"isEntry":true},"a8a3634b-8":{"id":"typescript","moduleParts":{},"imported":[],"importedBy":[{"uid":"a8a3634b-0"},{"uid":"a8a3634b-4"}]},"a8a3634b-9":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"a8a3634b-2"}]},"a8a3634b-10":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"a8a3634b-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
package/lib/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import ts from "typescript";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
2
4
 
3
5
  //#region src/jsx.ts
4
6
  /**
@@ -633,6 +635,159 @@ function containsCall(node) {
633
635
  return ts.forEachChild(node, containsCall) ?? false;
634
636
  }
635
637
 
638
+ //#endregion
639
+ //#region src/project-scanner.ts
640
+ /**
641
+ * Project scanner — extracts route, component, and island information from source files.
642
+ */
643
+ function generateContext(cwd) {
644
+ const files = collectSourceFiles(cwd);
645
+ return {
646
+ framework: "pyreon",
647
+ version: readVersion(cwd),
648
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
649
+ routes: extractRoutes(files, cwd),
650
+ components: extractComponents(files, cwd),
651
+ islands: extractIslands(files, cwd)
652
+ };
653
+ }
654
+ function collectSourceFiles(cwd) {
655
+ const results = [];
656
+ const extensions = new Set([
657
+ ".tsx",
658
+ ".jsx",
659
+ ".ts",
660
+ ".js"
661
+ ]);
662
+ const ignoreDirs = new Set([
663
+ "node_modules",
664
+ "dist",
665
+ "lib",
666
+ ".pyreon",
667
+ ".git",
668
+ "build"
669
+ ]);
670
+ function walk(dir) {
671
+ let entries;
672
+ try {
673
+ entries = fs.readdirSync(dir, { withFileTypes: true });
674
+ } catch {
675
+ return;
676
+ }
677
+ for (const entry of entries) {
678
+ if (entry.name.startsWith(".") && entry.isDirectory()) continue;
679
+ if (ignoreDirs.has(entry.name) && entry.isDirectory()) continue;
680
+ const fullPath = path.join(dir, entry.name);
681
+ if (entry.isDirectory()) walk(fullPath);
682
+ else if (entry.isFile() && extensions.has(path.extname(entry.name))) results.push(fullPath);
683
+ }
684
+ }
685
+ walk(cwd);
686
+ return results;
687
+ }
688
+ function extractRoutes(files, _cwd) {
689
+ const routes = [];
690
+ for (const file of files) {
691
+ let code;
692
+ try {
693
+ code = fs.readFileSync(file, "utf-8");
694
+ } catch {
695
+ continue;
696
+ }
697
+ const routeArrayRe = /(?:createRouter\s*\(\s*\[|(?:const|let)\s+routes\s*(?::\s*RouteRecord\[\])?\s*=\s*\[)([\s\S]*?)\]/g;
698
+ let match;
699
+ for (match = routeArrayRe.exec(code); match; match = routeArrayRe.exec(code)) {
700
+ const block = match[1] ?? "";
701
+ const routeObjRe = /path\s*:\s*["']([^"']+)["']/g;
702
+ let routeMatch;
703
+ for (routeMatch = routeObjRe.exec(block); routeMatch; routeMatch = routeObjRe.exec(block)) {
704
+ const routePath = routeMatch[1] ?? "";
705
+ const surroundingStart = Math.max(0, routeMatch.index - 50);
706
+ const surroundingEnd = Math.min(block.length, routeMatch.index + 200);
707
+ const surrounding = block.slice(surroundingStart, surroundingEnd);
708
+ routes.push({
709
+ path: routePath,
710
+ name: surrounding.match(/name\s*:\s*["']([^"']+)["']/)?.[1],
711
+ hasLoader: /loader\s*:/.test(surrounding),
712
+ hasGuard: /beforeEnter\s*:|beforeLeave\s*:/.test(surrounding),
713
+ params: extractParams(routePath)
714
+ });
715
+ }
716
+ }
717
+ }
718
+ return routes;
719
+ }
720
+ function extractComponents(files, cwd) {
721
+ const components = [];
722
+ for (const file of files) {
723
+ let code;
724
+ try {
725
+ code = fs.readFileSync(file, "utf-8");
726
+ } catch {
727
+ continue;
728
+ }
729
+ const componentRe = /(?:export\s+)?(?:const|function)\s+([A-Z]\w*)\s*(?::\s*ComponentFn<[^>]+>\s*)?=?\s*\(?(?:\s*\{?\s*([^)]*?)\s*\}?\s*)?\)?\s*(?:=>|{)/g;
730
+ let match;
731
+ for (match = componentRe.exec(code); match; match = componentRe.exec(code)) {
732
+ const name = match[1] ?? "Unknown";
733
+ const props = (match[2] ?? "").split(/[,;]/).map((p) => p.trim().replace(/[{}]/g, "").trim().split(":")[0]?.split("=")[0]?.trim() ?? "").filter((p) => p && p !== "props");
734
+ const bodyStart = match.index + match[0].length;
735
+ const body = code.slice(bodyStart, Math.min(code.length, bodyStart + 2e3));
736
+ const signalNames = [];
737
+ const signalRe = /(?:const|let)\s+(\w+)\s*=\s*signal\s*[<(]/g;
738
+ let sigMatch;
739
+ for (sigMatch = signalRe.exec(body); sigMatch; sigMatch = signalRe.exec(body)) if (sigMatch[1]) signalNames.push(sigMatch[1]);
740
+ components.push({
741
+ name,
742
+ file: path.relative(cwd, file),
743
+ hasSignals: signalNames.length > 0,
744
+ signalNames,
745
+ props
746
+ });
747
+ }
748
+ }
749
+ return components;
750
+ }
751
+ function extractIslands(files, cwd) {
752
+ const islands = [];
753
+ for (const file of files) {
754
+ let code;
755
+ try {
756
+ code = fs.readFileSync(file, "utf-8");
757
+ } catch {
758
+ continue;
759
+ }
760
+ const islandRe = /island\s*\(\s*\(\)\s*=>\s*import\(.+?\)\s*,\s*\{[^}]*name\s*:\s*["']([^"']+)["'][^}]*?(?:hydrate\s*:\s*["']([^"']+)["'])?[^}]*\}/g;
761
+ let match;
762
+ for (match = islandRe.exec(code); match; match = islandRe.exec(code)) if (match[1]) islands.push({
763
+ name: match[1],
764
+ file: path.relative(cwd, file),
765
+ hydrate: match[2] ?? "load"
766
+ });
767
+ }
768
+ return islands;
769
+ }
770
+ function extractParams(routePath) {
771
+ const params = [];
772
+ const paramRe = /:(\w+)\??/g;
773
+ let match;
774
+ for (match = paramRe.exec(routePath); match; match = paramRe.exec(routePath)) if (match[1]) params.push(match[1]);
775
+ return params;
776
+ }
777
+ function readVersion(cwd) {
778
+ try {
779
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, "package.json"), "utf-8"));
780
+ const deps = {
781
+ ...pkg.dependencies,
782
+ ...pkg.devDependencies
783
+ };
784
+ for (const [name, ver] of Object.entries(deps)) if (name.startsWith("@pyreon/") && typeof ver === "string") return ver.replace(/^[\^~]/, "");
785
+ return pkg.version || "unknown";
786
+ } catch {
787
+ return "unknown";
788
+ }
789
+ }
790
+
636
791
  //#endregion
637
792
  //#region src/react-intercept.ts
638
793
  /**
@@ -1307,5 +1462,5 @@ function diagnoseError(error) {
1307
1462
  }
1308
1463
 
1309
1464
  //#endregion
1310
- export { detectReactPatterns, diagnoseError, hasReactPatterns, migrateReactCode, transformJSX };
1465
+ export { detectReactPatterns, diagnoseError, generateContext, hasReactPatterns, migrateReactCode, transformJSX };
1311
1466
  //# sourceMappingURL=index.js.map