@pylonsync/functions 0.3.262 → 0.3.264

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonsync/functions",
3
- "version": "0.3.262",
3
+ "version": "0.3.264",
4
4
  "description": "TypeScript function runtime for pylon — defines server-side queries, mutations, and actions.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -38,6 +38,16 @@ type Send = (msg: Record<string, unknown>) => void;
38
38
  interface BundleClientMessage {
39
39
  type: "bundle_client";
40
40
  call_id: string;
41
+ /**
42
+ * Project-relative directory holding the route tree
43
+ * (`<app_dir>/**​/page.tsx`). Defaults to `"app"` when the host
44
+ * doesn't send it (older hosts, or the default single-`app/`
45
+ * layout). The full-stack app that namespaces its frontend under a
46
+ * subdir — e.g. `web/app` via `discoverAppRoutes({appDir:"web/app"})`
47
+ * — sends the same dir here so the client bundler and the SSR
48
+ * manifest agree on where the routes live.
49
+ */
50
+ app_dir?: string;
41
51
  }
42
52
 
43
53
  interface DiscoveredRoute {
@@ -87,19 +97,22 @@ declare const Bun: {
87
97
  };
88
98
 
89
99
  /**
90
- * Synchronously walk `app/` under cwd. Returns one entry per
91
- * discovered page, each carrying its layout chain (root leaf).
92
- * Mirrors the discovery logic in @pylonsync/sdk's
93
- * `discoverAppRoutes` exactly same sort order, same group-strip,
94
- * so the in-browser map keys line up with the manifest's component
95
- * field.
100
+ * Synchronously walk the route dir (`<appDirRel>` under cwd, e.g.
101
+ * `app` or `web/app`) and return one entry per discovered page, each
102
+ * carrying its layout chain (root → leaf). `appDirRel` MUST match the
103
+ * `appDir` the manifest was built with (`discoverAppRoutes({appDir})`)
104
+ * so the component paths `path.relative(cwd, file)` — line up with
105
+ * the manifest's `component` field byte-for-byte. Mirrors the
106
+ * discovery logic in @pylonsync/sdk's `discoverAppRoutes` exactly:
107
+ * same sort order, same group-strip.
96
108
  */
97
109
  function discoverRoutes(
98
110
  fs: any,
99
111
  path: any,
100
112
  cwd: string,
113
+ appDirRel: string,
101
114
  ): DiscoveredRoute[] {
102
- const appDir = path.join(cwd, "app");
115
+ const appDir = path.join(cwd, appDirRel);
103
116
  if (!fs.existsSync(appDir) || !fs.statSync(appDir).isDirectory()) {
104
117
  return [];
105
118
  }
@@ -684,11 +697,13 @@ let _inflightBuild: Promise<BuildOutput> | null = null;
684
697
  * Used from `handleBundleClient` (protocol RPC path from Rust) AND
685
698
  * from `getManifest` (in-process SSR path).
686
699
  */
687
- export async function buildClientBundle(): Promise<BuildOutput> {
700
+ export async function buildClientBundle(
701
+ appDirRel: string = "app",
702
+ ): Promise<BuildOutput> {
688
703
  if (_inflightBuild) return _inflightBuild;
689
704
  _inflightBuild = (async () => {
690
705
  try {
691
- return await _doBuild();
706
+ return await _doBuild(appDirRel);
692
707
  } finally {
693
708
  _inflightBuild = null;
694
709
  }
@@ -696,7 +711,7 @@ export async function buildClientBundle(): Promise<BuildOutput> {
696
711
  return _inflightBuild;
697
712
  }
698
713
 
699
- async function _doBuild(): Promise<BuildOutput> {
714
+ async function _doBuild(appDirRel: string): Promise<BuildOutput> {
700
715
  // node:* are available in Bun, but `globalThis.require` is
701
716
  // not defined in ESM. Use dynamic import; Bun fast-paths these.
702
717
  const fsMod: any = await import("node:fs");
@@ -704,7 +719,7 @@ async function _doBuild(): Promise<BuildOutput> {
704
719
  const fs = fsMod.default ?? fsMod;
705
720
  const path = pathMod.default ?? pathMod;
706
721
  const cwd = process.cwd();
707
- return _doBuildInner(fs, path, cwd);
722
+ return _doBuildInner(fs, path, cwd, appDirRel);
708
723
  }
709
724
 
710
725
  /**
@@ -719,8 +734,9 @@ async function buildTailwind(
719
734
  path: any,
720
735
  cwd: string,
721
736
  outdir: string,
737
+ appDirRel: string,
722
738
  ): Promise<string | null> {
723
- const globalsPath = path.join(cwd, "app", "globals.css");
739
+ const globalsPath = path.join(cwd, appDirRel, "globals.css");
724
740
  if (!fs.existsSync(globalsPath)) return null;
725
741
  // Resolve @tailwindcss/cli. The package only exports
726
742
  // `./package.json` in its `exports` map (it's a binary, not a
@@ -778,10 +794,17 @@ async function buildTailwind(
778
794
  return stylesName;
779
795
  }
780
796
 
781
- async function _doBuildInner(fs: any, path: any, cwd: string): Promise<BuildOutput> {
782
- const routes = discoverRoutes(fs, path, cwd);
797
+ async function _doBuildInner(
798
+ fs: any,
799
+ path: any,
800
+ cwd: string,
801
+ appDirRel: string,
802
+ ): Promise<BuildOutput> {
803
+ const routes = discoverRoutes(fs, path, cwd, appDirRel);
783
804
  if (routes.length === 0) {
784
- throw new Error("no SSR routes discovered under app/ — nothing to bundle");
805
+ throw new Error(
806
+ `no SSR routes discovered under ${appDirRel}/ — nothing to bundle`,
807
+ );
785
808
  }
786
809
 
787
810
  const stageDir = path.join(cwd, ".pylon");
@@ -976,7 +999,7 @@ async function _doBuildInner(fs: any, path: any, cwd: string): Promise<BuildOutp
976
999
  // `app/globals.css`. Adds the stylesheet to every route's css
977
1000
  // array so SSR head injection emits `<link rel="stylesheet">`.
978
1001
  try {
979
- const styles = await buildTailwind(fs, path, cwd, outdir);
1002
+ const styles = await buildTailwind(fs, path, cwd, outdir, appDirRel);
980
1003
  if (styles) {
981
1004
  for (const r of Object.values(manifest.routes)) {
982
1005
  r.css = [styles];
@@ -1054,7 +1077,9 @@ export async function handleBundleClient(
1054
1077
  send: Send,
1055
1078
  ): Promise<void> {
1056
1079
  try {
1057
- const { manifestPath, outdir } = await buildClientBundle();
1080
+ const appDirRel =
1081
+ msg.app_dir && msg.app_dir.length > 0 ? msg.app_dir : "app";
1082
+ const { manifestPath, outdir } = await buildClientBundle(appDirRel);
1058
1083
  send({
1059
1084
  type: "bundle_client_result",
1060
1085
  call_id: msg.call_id,