UNPKG

@getcronit/pylon

Version:

![Pylon cover](https://github.com/user-attachments/assets/c28e49b2-5672-4849-826e-8b2eab0360cc)

2,560 lines 91.3 kB
import "./chunk-R6NNLVZJ.js";

// src/plugins/use-pages/build/index.ts
import chokidar from "chokidar";
import esbuild from "esbuild";
import fs6 from "fs/promises";
import path4 from "path";

// src/plugins/use-pages/build/app-utils.ts
import fs from "fs";
import path from "path";
var PAGES_DIR = "./pages";
function formatSegment(segment) {
  let sanitized = segment;
  if (sanitized.startsWith("[...") && sanitized.endsWith("]")) {
    const param = sanitized.slice(4, -1);
    sanitized = "CatchAll" + param.charAt(0).toUpperCase() + param.slice(1);
  } else if (sanitized.startsWith("[") && sanitized.endsWith("]")) {
    sanitized = sanitized.slice(1, -1);
  }
  return sanitized.charAt(0).toUpperCase() + sanitized.slice(1);
}
function getLayoutComponentName(filePath) {
  const segments = filePath.replace(PAGES_DIR, "").replace(/\\/g, "/").replace(/layout\.tsx$/, "").split("/").filter(Boolean);
  return segments.map(formatSegment).join("") + "Layout";
}
function getPageComponentName(filePath) {
  const segments = filePath.replace(PAGES_DIR, "").replace(/\\/g, "/").replace(/page\.tsx$/, "").split("/").filter(Boolean);
  return segments.map(formatSegment).join("") + "Page";
}
function convertToDynamicRoute(segment) {
  if (segment.startsWith("[...") && segment.endsWith("]")) return "*";
  if (segment.startsWith("[") && segment.endsWith("]"))
    return `:${segment.slice(1, -1)}`;
  return segment;
}
function processLayoutItem(relativePath, importPath, route, context) {
  const layoutComponentName = getLayoutComponentName(relativePath);
  context.imports.push(`import ${layoutComponentName} from ${importPath};`);
  const componentName = layoutComponentName === "Layout" ? `RootLayout` : `${layoutComponentName}`;
  const catchAllParam = relativePath.match(/\[\.\.\.(.+)\]/)?.[1];
  const paramMatches = [...relativePath.matchAll(/\[(.+?)\]/g)].map(
    (m) => m[1].replace("...", "")
  );
  route.id = componentName;
  route.Component = `withRouteData((props) => <${componentName} children={<Outlet />} {...props} />, "${componentName}", ${catchAllParam ? `"${catchAllParam}"` : "undefined"})`;
  route.shouldRevalidate = `({ currentParams, nextParams, formData, defaultShouldRevalidate }) => {
    // Revalidate if a form was submitted (standard behavior)
    if (formData) return true;

    // List of params this layout segment depends on
    const relevantKeys = ${JSON.stringify(paramMatches)};
    
    // Check if any relevant URL parameter changed
    const hasParamChanged = relevantKeys.some(key => 
      JSON.stringify(currentParams[key]) !== JSON.stringify(nextParams[key])
    );

    // If it's the RootLayout, we might only want to revalidate on hard refreshes 
    // or specific global triggers. Otherwise, follow param changes.
    return hasParamChanged || (relevantKeys.length === 0 && defaultShouldRevalidate);
  }`;
  if (route.path === "/") {
    route.errorElement = "<ErrorElement standalone={true} />";
  }
  route.HydrateFallback = "HydrateFallback";
}
function processPageItem(relativePath, importPath, route) {
  const catchAllParam = relativePath.match(/\[\.\.\.(.+)\]/)?.[1];
  const pageComponentName = getPageComponentName(relativePath);
  route.children.push({
    id: pageComponentName,
    path: void 0,
    index: true,
    errorElement: "<ErrorElement standalone={false} />",
    lazy: `async () => {const i = await import(${importPath}).catch(() => {window.location.reload()}); return {Component: withRouteData(i.default, "${pageComponentName}", ${catchAllParam ? `"${catchAllParam}"` : "undefined"})}}`,
    HydrateFallback: "HydrateFallback"
  });
}
function optimizeRouteStructure(route, hasLayout) {
  if (!hasLayout && route.children?.length === 1 && route.children[0].path === "*") {
    const child = route.children[0];
    const currentPath = route.path === "/" ? "" : route.path;
    Object.assign(route, child);
    route.path = currentPath ? `${currentPath}/*` : "*";
    delete route.children;
  }
  if (route.path === "*" && !hasLayout && route.children?.length === 1) {
    const child = route.children[0];
    const currentPath = route.path;
    Object.assign(route, child);
    route.path = currentPath;
    delete route.index;
    delete route.children;
  }
  if (route.path === "*" && hasLayout && route.children) {
    const pageChild = route.children.find((child) => child.index);
    if (pageChild) {
      delete pageChild.index;
      pageChild.path = "*";
    }
  }
}
function scanDirectory(directory, context, basePath = "") {
  const items = fs.readdirSync(directory, { withFileTypes: true });
  const route = { path: basePath || "/", children: [] };
  let hasLayout = false;
  let pageFound = false;
  for (const item of items) {
    const itemPath = path.join(directory, item.name);
    const relativePath = path.join(basePath, item.name).replace(/\\/g, "/");
    const importPath = `"./${path.join("..", PAGES_DIR, relativePath).replace(/\.tsx$/, "")}"`;
    if (item.isDirectory()) {
      const childRoute = scanDirectory(itemPath, context, relativePath);
      if (childRoute) {
        route.children.push(childRoute);
      }
    } else if (item.name === "layout.tsx") {
      processLayoutItem(relativePath, importPath, route, context);
      hasLayout = true;
    } else if (item.name === "page.tsx") {
      processPageItem(relativePath, importPath, route);
      pageFound = true;
    }
  }
  if (route.path) {
    const segments = route.path.split("/").map((segment) => convertToDynamicRoute(segment)).filter(Boolean);
    const fullPath = segments.length > 0 ? `/${segments.join("/")}` : "/";
    route.path = segments[segments.length - 1] || "/";
    if (hasLayout || pageFound) {
      context.routeSlugs.push(fullPath);
    }
  }
  if (hasLayout) {
    const childNotFoundRoute = {
      id: `${route.id}/NotFound`,
      path: "*",
      element: "<NotFoundPage standalone={false} />",
      loader: '() => { console.log("EXECUTED LOADER 404"); return new Response("Not Found", { status: 404 }) }'
    };
    if (!route.children) {
      route.children = [];
    }
    route.children.push(childNotFoundRoute);
  }
  optimizeRouteStructure(route, hasLayout);
  if (hasLayout || route.lazy || route.children && route.children.length > 0) {
    return route;
  }
  return null;
}
function serialize(obj, parentKey) {
  if (Array.isArray(obj)) {
    return `[${obj.map(serialize).join(", ")}]`;
  } else if (obj && typeof obj === "object") {
    const entries = Object.entries(obj).map(
      ([key, value]) => `${JSON.stringify(key)}: ${serialize(value, key)}`
    );
    return `{${entries.join(", ")}}`;
  } else if (typeof obj === "string") {
    if (parentKey === "lazy" || parentKey === "loader" || parentKey === "shouldRevalidate" || parentKey === "Component" || parentKey === "element" || parentKey === "errorElement" || parentKey === "HydrateFallback") {
      return obj;
    }
    return JSON.stringify(obj);
  } else {
    return String(obj);
  }
}
function generateRouteFileContent(context, rootRoute, notFoundRoute) {
  return `${context.imports.join("\n")}

import {useMemo, Suspense} from 'react'
import {__PYLON_ROUTER_INTERNALS_DO_NOT_USE, __PYLON_INTERNALS_DO_NOT_USE, GlobalErrorPage, StatusPage} from '@getcronit/pylon/pages'
const Outlet = __PYLON_ROUTER_INTERNALS_DO_NOT_USE.Outlet

const ErrorElement: React.FC<{standalone: boolean}> = ({standalone}) => {
  // Destructure for cleaner code
  const { useRouteError, isRouteErrorResponse, Navigate } = __PYLON_ROUTER_INTERNALS_DO_NOT_USE;
  
  const error = useRouteError();
  console.error(error);
  
  let message = 'An unexpected error occurred.';

  // 1. Handle raw Response redirects (e.g., thrown directly during client render)
  if (
    error instanceof Response && 
    error.status >= 300 && 
    error.status < 400 && 
    error.headers.get('Location')
  ) {
    return <Navigate to={error.headers.get('Location')!} replace />;
  }

  // 2. Use the official router check for handled data errors (404, 401, etc.)
  // We check \`error.internal\` as a fallback just in case the server formatting is slightly off
  const isRouteError = isRouteErrorResponse(error)

  if (isRouteError) {
    try {
      const errorData = (error as any).data;
      const rawMessage = typeof errorData === 'string' ? errorData : errorData?.message;
      
      if (rawMessage) {
        try {
          const parsed = JSON.parse(rawMessage);
          message = parsed.message || rawMessage;
        } catch (e) {
          message = rawMessage;
        }
      }
    } catch (e) {}

    // Only render the StatusPage for non-500 HTTP errors
    if ((error as any).status !== 500) {
      return (
        <StatusPage
          code={(error as any).status}
          message={message}
          error={error}
          standalone={standalone}
        />
      );
    }
  }

  // 3. Fallback for standard code crashes (e.g., TypeError) and explicit 500s
  const displayError = error instanceof Error 
    ? error 
    : new Error(
        message || 
        (error && typeof error === 'object' && ((error as any).message || (error as any).statusText)) || 
        'A critical error occurred'
      );
      
  return <GlobalErrorPage error={displayError as any} standalone={standalone} />;
}

const HydrateFallback = () => {
  return <div>Loading...</div>
}

// Replaced pageClientCache with central cache in DataClientProvider

function withRouteData(Component: React.ComponentType<any>, id?: string, catchAllParam?: string) {
  return function WithRouteDataWrapper(props: any) {
    const dataClient = __PYLON_INTERNALS_DO_NOT_USE.useDataClient()
    const pagesContext = dataClient.pagesContext

    const location = __PYLON_ROUTER_INTERNALS_DO_NOT_USE.useLocation()
    const [searchParams] = __PYLON_ROUTER_INTERNALS_DO_NOT_USE.useSearchParams()
    const searchParamsObject = useMemo(() => Object.fromEntries(searchParams.entries()), [searchParams])

    const reactRouterParams = __PYLON_ROUTER_INTERNALS_DO_NOT_USE.useParams()

    const params = useMemo(() => {
      const params: Record<string, string | string[] | undefined> = reactRouterParams

      if (catchAllParam && reactRouterParams['*']) {
        params[catchAllParam] = reactRouterParams['*']?.split('/')
      }

      return params
    }, [reactRouterParams, catchAllParam])

    const pageProps = useMemo(() => {
      return {
        path: location.pathname,
        params,
        searchParams: searchParamsObject,
        context: pagesContext,
      }
    }, [location.pathname, params, searchParamsObject, pagesContext])

    return (
      <__PYLON_INTERNALS_DO_NOT_USE.RouteDataProvider props={pageProps} name={id}>
        <Component {...(props as any)} {...pageProps} children={<Outlet />} />
      </__PYLON_INTERNALS_DO_NOT_USE.RouteDataProvider>
    )
  };
}





const RootLayout = (props: { children: React.ReactNode; [key: string]: any }) => {
  const manifest = (globalThis as any).__PYLON_MANIFEST__;

  return (
    <Layout {...props}>
      <meta charSet="utf-8" />
      {manifest?.['index.css'] && <link rel="stylesheet" href={manifest['index.css']} precedence="high" />}
      {manifest?.['app.css'] && <link rel="stylesheet" href={manifest['app.css']} precedence="high" />}
      {props.children}
    </Layout>
  )
}

const NotFoundPage: React.FC<{standalone: boolean}> = ({standalone = false}) => {
  return <StatusPage code={404} message="The page you are looking for does not exist." standalone={standalone} />
}

const routes = ${serialize([rootRoute, notFoundRoute].filter(Boolean))}

export default routes

`;
}
function makeAppFiles() {
  const context = { imports: [], routeSlugs: [] };
  const rootRoute = scanDirectory(PAGES_DIR, context);
  const notFoundRoute = {
    id: "NotFound",
    path: "*",
    element: "<NotFoundPage standalone={true} />",
    loader: '() => { return new Response("Not Found", { status: 404 }) }'
  };
  const routes = generateRouteFileContent(context, rootRoute, notFoundRoute);
  const slugs = `export default ${JSON.stringify(context.routeSlugs, null, 2)}`;
  return {
    routes,
    slugs
  };
}

// src/plugins/use-pages/build/plugins/external-esm-plugin.ts
import escapeStringRegexp from "escape-string-regexp";
var NAME = "esm-externals";
var NAMESPACE = NAME;
function makeFilter(externals) {
  return new RegExp(
    "^(" + externals.map(escapeStringRegexp).join("|") + ")(\\/.*)?$"
    // TODO support for query strings?
  );
}
var esmExternalsPlugin = (externals) => {
  return {
    name: NAME,
    setup(build2) {
      const filter = makeFilter(externals);
      build2.onResolve({ filter: /.*/, namespace: NAMESPACE }, (args) => {
        return {
          path: args.path,
          external: true
        };
      });
      build2.onResolve({ filter }, (args) => {
        return {
          path: args.path,
          namespace: NAMESPACE
        };
      });
      build2.onLoad({ filter: /.*/, namespace: NAMESPACE }, (args) => {
        return {
          contents: `export * as default from ${JSON.stringify(
            args.path
          )}; export * from ${JSON.stringify(args.path)};`
        };
      });
    }
  };
};

// src/plugins/use-pages/build/plugins/image-plugin.ts
import { createHash } from "crypto";
import path2 from "path";
import fs2 from "fs/promises";
var imagePlugin = {
  name: "image-plugin",
  setup(build2) {
    const outdir = build2.initialOptions.outdir;
    const publicPath = build2.initialOptions.publicPath;
    if (!outdir || !publicPath) {
      throw new Error("outdir and publicPath must be set in esbuild options");
    }
    build2.onResolve({ filter: /\.(png|jpe?g)$/ }, async (args) => {
      const filePath = path2.resolve(args.resolveDir, args.path);
      const fileName = path2.basename(filePath);
      const extname = path2.extname(filePath);
      const hash = createHash("md5").update(filePath + await fs2.readFile(filePath)).digest("hex").slice(0, 8);
      const newFilename = `${fileName}-${hash}${extname}`;
      const newFilePath = path2.join(outdir, "media", newFilename);
      await fs2.mkdir(path2.dirname(newFilePath), { recursive: true });
      await fs2.copyFile(filePath, newFilePath);
      return {
        path: newFilePath,
        namespace: "image"
      };
    });
    build2.onLoad({ filter: /\.png$|\.jpg$/ }, async (args) => {
      const sharp = (await import("sharp")).default;
      const image = sharp(args.path);
      const metadata = await image.metadata();
      const url = `${publicPath}/media/${path2.basename(args.path)}`;
      const output = image.resize({
        width: Math.min(metadata.width ?? 16, 16),
        height: Math.min(metadata.height ?? 16, 16),
        fit: "inside"
      }).toFormat("webp", {
        quality: 30,
        alphaQuality: 20,
        smartSubsample: true
      });
      const { data, info } = await output.toBuffer({ resolveWithObject: true });
      const dataURIBase64 = `data:image/${info.format};base64,${data.toString(
        "base64"
      )}`;
      return {
        contents: JSON.stringify({
          url,
          width: metadata.width,
          height: metadata.height,
          blurDataURL: dataURIBase64
        }),
        loader: "json"
      };
    });
  }
};

// src/plugins/use-pages/build/plugins/inject-app-hydration.ts
import fs3 from "fs/promises";
import path3 from "path";
var injectAppHydrationPlugin = (version) => ({
  name: "inject-hydration",
  setup(build2) {
    build2.onLoad({ filter: /.*/, namespace: "file" }, async (args) => {
      if (args.path === path3.resolve(process.cwd(), ".pylon", "app.tsx")) {
        let contents = await fs3.readFile(args.path, "utf-8");
        const clientPath = path3.resolve(process.cwd(), ".pylon/client");
        const pathToClient = path3.relative(path3.dirname(args.path), clientPath);
        contents += `
          import {hydrateRoot} from 'react-dom/client'
          import * as client from './${pathToClient}'
          import { __PYLON_ROUTER_INTERNALS_DO_NOT_USE, __PYLON_INTERNALS_DO_NOT_USE, DevOverlay, onCaughtErrorProd, onRecoverableErrorProd, onUncaughtErrorProd } from '@getcronit/pylon/pages';
          import React, {startTransition} from 'react'
          import * as Sentry from '@sentry/react'

          // @ts-ignore
          window.__PYLON_VERSION__ = "${version}"

          async function hydrate() {
            // Determine if any of the initial routes are lazy
            const lazyMatches = __PYLON_ROUTER_INTERNALS_DO_NOT_USE.matchRoutes(routes, window.location)?.filter(
              (m) => m.route.lazy
            );

            // Load the lazy matches and update the routes before creating your router
            // so we can hydrate the SSR-rendered content synchronously
            if (lazyMatches && lazyMatches?.length > 0) {
              await Promise.all(
                lazyMatches.map(async (m) => {
                  const routeModule = await m.route.lazy!();
                  Object.assign(m.route, { ...routeModule, lazy: undefined });
                })
              );
            }

            const payload = (window as any).__pylonStaticData
            if (payload?.cache) {
              const coreClient = (client as any).client || client
              if (coreClient && coreClient.cache) {
                console.log('Hydrating cache with payload', payload.cache, coreClient)
                coreClient.hydrateCache({cacheSnapshot: payload.cache, shouldRefetch: false})
              }
            }

            // @ts-ignore
            const router = __PYLON_ROUTER_INTERNALS_DO_NOT_USE.createBrowserRouter(routes)

            // @ts-ignore
            window.__PYLON_NAVIGATE__ = router.navigate

            startTransition(() => {
              hydrateRoot(
                document,
                  <__PYLON_INTERNALS_DO_NOT_USE.DataClientProvider client={client}>
                    <__PYLON_ROUTER_INTERNALS_DO_NOT_USE.RouterProvider router={router} />
                  </__PYLON_INTERNALS_DO_NOT_USE.DataClientProvider>
              , {
                // Callback called when an error is thrown and not caught by an ErrorBoundary.
                onUncaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
                  console.warn('Uncaught error', error, errorInfo.componentStack);
                }),
                // Callback called when React catches an error in an ErrorBoundary.
                onCaughtError: Sentry.reactErrorHandler(),
                // Callback called when React automatically recovers from errors.
                onRecoverableError: Sentry.reactErrorHandler(),
              })
            })
         }

         hydrate()


          `;
        return {
          loader: "tsx",
          contents
        };
      }
    });
  }
});

// src/plugins/use-pages/build/plugins/postcss-plugin.ts
import fs4 from "fs/promises";
import loadConfig from "postcss-load-config";
import postcss from "postcss";
var postcssPlugin = {
  name: "postcss-plugin",
  setup(build2) {
    build2.onLoad({ filter: /.css$/, namespace: "file" }, async (args) => {
      const { plugins, options } = await loadConfig();
      const css = await fs4.readFile(args.path, "utf-8");
      const result = await postcss(plugins).process(css, {
        ...options,
        from: args.path
      }).then((result2) => result2);
      return {
        contents: result.css,
        loader: "css"
      };
    });
  }
};

// src/plugins/use-pages/build/plugins/use-data-static-analyzer/index.ts
import * as fs5 from "fs";
import { Node as Node2, SyntaxKind as SyntaxKind2 } from "ts-morph";

// src/plugins/use-pages/build/plugins/use-data-static-analyzer/analyze.ts
import {
  Node,
  Project,
  SyntaxKind,
  ts
} from "ts-morph";
function pathKey(p) {
  let key = "";
  for (let i = 0; i < p.length; i++) {
    if (i > 0) key += ".";
    key += p[i].name;
    if (p[i].args !== void 0) key += "(" + p[i].args + ")";
  }
  return key;
}
var JS_ARRAY_ONLY_METHODS = /* @__PURE__ */ new Set([
  "push",
  "pop",
  "shift",
  "unshift",
  "splice",
  "join",
  "flat",
  "flatMap",
  "reverse",
  "sort",
  "toReversed",
  "toSorted",
  "toSpliced"
]);
var JS_SHARED_METHODS = /* @__PURE__ */ new Set(["slice", "concat", "indexOf", "includes"]);
var JS_ARRAY_METHODS = /* @__PURE__ */ new Set([
  ...JS_ARRAY_ONLY_METHODS,
  ...JS_SHARED_METHODS
]);
var JS_INTERNALS = /* @__PURE__ */ new Set([
  ...JS_ARRAY_METHODS,
  "length",
  "toString",
  "toLocaleString",
  "toLocaleDateString",
  "toLocaleTimeString",
  "toJSON",
  "valueOf",
  "hasOwnProperty",
  "trim",
  "trimStart",
  "trimEnd",
  "toLowerCase",
  "toUpperCase",
  "split",
  "substring",
  "substr",
  "replace",
  "replaceAll",
  "match",
  "matchAll",
  "startsWith",
  "endsWith",
  "charAt",
  "charCodeAt",
  "codePointAt",
  "repeat",
  "padStart",
  "padEnd",
  "toFixed",
  "toPrecision",
  "toExponential",
  "bind",
  "call",
  "apply"
]);
var ITERATOR_METHODS = /* @__PURE__ */ new Set([
  "map",
  "filter",
  "forEach",
  "reduce",
  "some",
  "every",
  "find",
  "findIndex",
  "reverse",
  "sort",
  "slice",
  "concat",
  "flat",
  "flatMap",
  "toReversed",
  "toSorted",
  "toSpliced"
]);
function coreAnalyze(sourceFile, options) {
  const result = {};
  let _checker = void 0;
  const getChecker = () => {
    if (!_checker) _checker = sourceFile.getProject().getTypeChecker();
    return _checker;
  };
  const symbolCache = /* @__PURE__ */ new WeakMap();
  function getSymbol(node) {
    let sym = symbolCache.get(node);
    if (sym !== void 0) return sym;
    sym = node.getSymbol?.() || getChecker().getSymbolAtLocation(node);
    symbolCache.set(node, sym ?? null);
    return sym ?? void 0;
  }
  const typeCache = /* @__PURE__ */ new WeakMap();
  function getNodeType(node) {
    let t = typeCache.get(node);
    if (t !== void 0) return t;
    t = node.getType();
    typeCache.set(node, t);
    return t;
  }
  let importedIdentifiers;
  const getImportedIdentifiers = () => {
    if (importedIdentifiers) return importedIdentifiers;
    importedIdentifiers = /* @__PURE__ */ new Set();
    sourceFile.getImportDeclarations().forEach((imp) => {
      const namedBindings = imp.getImportClause()?.getNamedBindings();
      if (namedBindings && Node.isNamedImports(namedBindings)) {
        namedBindings.getElements().forEach((el) => {
          importedIdentifiers.add(el.getAliasNode()?.getText() || el.getName());
        });
      }
      const namespaceImport = imp.getImportClause()?.getNamespaceImport();
      if (namespaceImport) {
        importedIdentifiers.add(namespaceImport.getText());
      }
    });
    return importedIdentifiers;
  };
  const WELL_KNOWN_GLOBALS = /* @__PURE__ */ new Set([
    "console",
    "Math",
    "JSON",
    "Array",
    "Object",
    "Promise",
    "Error",
    "Map",
    "Set",
    "Number",
    "String",
    "Boolean",
    "Date",
    "RegExp",
    "Intl",
    "Uint8Array",
    "Buffer",
    "React",
    "document",
    "window"
  ]);
  function needsTypeChecker(node) {
    if (!Node.isIdentifier(node)) return true;
    const name = node.getText();
    if (WELL_KNOWN_GLOBALS.has(name)) return false;
    if (functionRegistry.has(name)) return false;
    const paths = resolveBinding(name);
    if (paths.length === 0) return true;
    return false;
  }
  const trackedNames = /* @__PURE__ */ new Set();
  if (options.rootObjectName) {
    trackedNames.add(options.rootObjectName);
  }
  function textMentionsTracked(node) {
    if (trackedNames.size === 0) return true;
    let found = false;
    const walkNative = (n) => {
      if (found) return;
      if (ts.isIdentifier(n) && trackedNames.has(n.text)) {
        found = true;
        return;
      }
      ts.forEachChild(n, walkNative);
    };
    walkNative(node.compilerNode);
    return found;
  }
  function mergePathAndArgs(tree, path5, isList = false) {
    if (path5.length === 0) return;
    if (path5.some((p) => p.name === "__decl")) return;
    let current = tree;
    for (let i = 0; i < path5.length; i++) {
      const step = path5[i];
      const key = step.name;
      if (key === "__element") continue;
      const args = step.args;
      const isLast = i === path5.length - 1;
      const segmentIsList = (!!step.__isList || isLast && isList) && !step.__isVirtual;
      if (current[key] === true && !isLast) {
        current[key] = {};
      }
      let node = current[key];
      if (node === void 0 || node === true) {
        if (args !== void 0) {
          node = { __args: args };
          current[key] = node;
        } else {
          if (isLast && !segmentIsList) {
            current[key] = true;
            node = true;
          } else {
            node = {};
            current[key] = node;
          }
        }
      }
      if (node === true) {
        if (isLast && !segmentIsList && args === void 0) return;
        node = {};
        current[key] = node;
      }
      if (Array.isArray(node)) {
        let branch = node.find((n) => n.__args === args);
        if (!branch) {
          branch = args !== void 0 ? { __args: args } : {};
          node.push(branch);
        }
        node = branch;
      } else if (args !== void 0 && node.__args !== void 0 && node.__args !== args) {
        const oldNode = node;
        const newNode = { __args: args };
        current[key] = [oldNode, newNode];
        node = newNode;
      } else if (args === void 0 && node.__args !== void 0) {
        const oldNode = node;
        const newNode = {};
        current[key] = [oldNode, newNode];
        node = newNode;
      } else if (args !== void 0 && node.__args === void 0) {
        node.__args = args;
      }
      if (segmentIsList) {
        if (typeof node === "object" && node !== null && !Array.isArray(node)) {
          node.__isList = true;
        } else if (node === true) {
          current[key] = { __isList: true };
          node = current[key];
        }
      }
      if (!isLast) {
        current = node;
      }
    }
  }
  function stringifyArgument(node) {
    if (Node.isObjectLiteralExpression(node)) {
      const props = node.getProperties().map((prop) => {
        if (Node.isPropertyAssignment(prop)) {
          const keyNode = prop.getNameNode();
          const key = Node.isComputedPropertyName(keyNode) ? `[${stringifyArgument(keyNode.getExpression())}]` : prop.getName();
          const value = stringifyArgument(prop.getInitializer());
          return `${key}: ${value}`;
        }
        if (Node.isShorthandPropertyAssignment(prop)) {
          const name = prop.getName();
          const value = stringifyArgument(prop.getNameNode());
          if (value === name) return name;
          return `${name}: ${value}`;
        }
        if (Node.isSpreadAssignment(prop)) {
          return `...${stringifyArgument(prop.getExpression())}`;
        }
        return prop.getText();
      });
      if (props.length === 0) return "{}";
      return `{ ${props.join(", ")} }`;
    }
    if (Node.isArrayLiteralExpression(node)) {
      return `[${node.getElements().map(stringifyArgument).join(", ")}]`;
    }
    if (Node.isIdentifier(node)) {
      const name = node.getText();
      const binding = resolveBindingInfo(name);
      if (binding && binding.paths.length > 0) {
        const path5 = binding.paths[0];
        const first = path5[0];
        if (first?.sourceName) {
          if (first.name.startsWith("__target_")) return name;
          if (path5.some((p) => p.isElement)) return name;
          let result2 = first.sourceName;
          for (let i = 1; i < path5.length; i++) {
            const seg = path5[i];
            if (seg.name.startsWith("__")) continue;
            result2 += "." + seg.name;
            if (seg.args !== void 0) result2 += "(" + seg.args + ")";
          }
          return result2;
        }
        if (first?.name.startsWith("__literal_")) {
          return first.name.replace("__literal_", "");
        }
      }
      return name;
    }
    const kind = node.getKind();
    if (kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NumericLiteral || kind === SyntaxKind.TrueKeyword || kind === SyntaxKind.FalseKeyword || kind === SyntaxKind.NullKeyword || kind === SyntaxKind.NoSubstitutionTemplateLiteral) {
      return node.getText();
    }
    if (Node.isConditionalExpression(node)) {
      const condition = stringifyArgument(node.getCondition());
      const whenTrue = stringifyArgument(node.getWhenTrue());
      const whenFalse = stringifyArgument(node.getWhenFalse());
      if (condition === "true" || condition.startsWith('"') && condition !== '""' || !isNaN(Number(condition)) && Number(condition) !== 0) {
        return whenTrue;
      }
      if (condition === "false" || condition === "null" || condition === "undefined" || condition === "0" || condition === '""') {
        return whenFalse;
      }
      return `${condition} ? ${whenTrue} : ${whenFalse}`;
    }
    return node.getText();
  }
  let scopes = [{ bindings: /* @__PURE__ */ new Map() }];
  function currentScope() {
    return scopes[scopes.length - 1];
  }
  let branchDepth = 0;
  const exportedFunctionReturns = /* @__PURE__ */ new Map();
  function setBinding(identifier, paths, isDeclaration = false, isParam = false) {
    let finalPaths = paths;
    if (isDeclaration) {
      if (options.rootObjectName && identifier === options.rootObjectName && !finalPaths.some((p) => p.length > 0 && p[0].sourceName)) {
        currentScope().bindings.set(identifier, { paths: [[]], isParam });
        trackedNames.add(identifier);
        return;
      }
      finalPaths = paths.map((p) => {
        if (p.length > 0) {
          if (!p[0].sourceName) {
            return [{ ...p[0], sourceName: identifier }, ...p.slice(1)];
          }
        }
        return p;
      });
    }
    if (!isDeclaration) {
      for (let i = scopes.length - 1; i >= 0; i--) {
        const existingBinding = scopes[i].bindings.get(identifier);
        if (existingBinding) {
          if (branchDepth > 0) {
            const existing = existingBinding.paths;
            const combined = [...existing];
            const seen = new Set(combined.map(pathKey));
            for (const p of finalPaths) {
              const pk = pathKey(p);
              if (!seen.has(pk)) {
                seen.add(pk);
                combined.push(p);
              }
            }
            scopes[i].bindings.set(identifier, {
              paths: combined,
              isParam: existingBinding.isParam
            });
          } else {
            scopes[i].bindings.set(identifier, { paths: finalPaths, isParam });
          }
          return;
        }
      }
    }
    currentScope().bindings.set(identifier, { paths: finalPaths, isParam });
    if (finalPaths.length > 0) trackedNames.add(identifier);
  }
  function hasBinding(identifier) {
    for (let i = scopes.length - 1; i >= 0; i--) {
      if (scopes[i].bindings.has(identifier)) return true;
    }
    if (options.rootObjectName && identifier === options.rootObjectName)
      return true;
    return false;
  }
  function resolveBinding(identifier) {
    for (let i = scopes.length - 1; i >= 0; i--) {
      const b = scopes[i].bindings.get(identifier);
      if (b) return b.paths;
    }
    return [];
  }
  function resolveBindingInfo(identifier) {
    for (let i = scopes.length - 1; i >= 0; i--) {
      const b = scopes[i].bindings.get(identifier);
      if (b) return b;
    }
    return void 0;
  }
  let lastReturnedPaths = [];
  function markAsList(paths) {
    paths.forEach((path5) => {
      mergePathAndArgs(result, path5, true);
      if (path5.length > 0) {
        const lastSegment = path5[path5.length - 1];
        if (!lastSegment.__isVirtual) {
          lastSegment.__isList = true;
        }
      }
    });
  }
  function bindParam(paramNameNode, paths, isDeclaration = false) {
    if (Node.isIdentifier(paramNameNode)) {
      setBinding(paramNameNode.getText(), paths, isDeclaration, true);
    } else if (Node.isObjectBindingPattern(paramNameNode) || Node.isArrayBindingPattern(paramNameNode)) {
      handleDestructuring(paramNameNode, paths, isDeclaration);
    }
  }
  function executeFunctionBody(body, bindParams, isolate = false) {
    if (!body) return [];
    const oldScopes = scopes;
    if (isolate) {
      scopes = [oldScopes[0], { bindings: /* @__PURE__ */ new Map() }];
    } else {
      scopes.push({ bindings: /* @__PURE__ */ new Map() });
    }
    if (bindParams) bindParams();
    let paths = [];
    if (Node.isBlock(body)) {
      const prevReturned = lastReturnedPaths;
      lastReturnedPaths = [];
      body.getStatements().forEach(analyzeStatement);
      paths = lastReturnedPaths;
      lastReturnedPaths = prevReturned;
    } else {
      paths = evaluateExpression(body);
    }
    if (isolate) {
      scopes = oldScopes;
    } else {
      scopes.pop();
    }
    return paths;
  }
  function bindIteratorParam(params, basePaths, methodName) {
    const paramIndex = methodName === "reduce" ? 1 : 0;
    if (params.length > paramIndex) {
      const elementPaths = basePaths.map((p) => [
        ...p,
        { name: "__element", isElement: true }
      ]);
      bindParam(params[paramIndex].getNameNode(), elementPaths);
    }
  }
  function withRecursionGuard(decl, fn) {
    const count = visitedDecls.get(decl) || 0;
    if (count >= MAX_RECURSION_PER_DECL || currentDepth >= MAX_DEPTH) {
      return void 0;
    }
    visitedDecls.set(decl, count + 1);
    currentDepth++;
    const sourceFile2 = decl.getSourceFile();
    if (options.onFileAccess) options.onFileAccess(sourceFile2);
    try {
      return fn();
    } finally {
      currentDepth--;
      const newCount = (visitedDecls.get(decl) || 1) - 1;
      if (newCount <= 0) visitedDecls.delete(decl);
      else visitedDecls.set(decl, newCount);
    }
  }
  const functionRegistry = /* @__PURE__ */ new Map();
  function handleDestructuring(pattern, paths, isDeclaration = false) {
    if (Node.isObjectBindingPattern(pattern)) {
      for (const element of pattern.getElements()) {
        let propName = "";
        const propertyNameNode = element.getPropertyNameNode();
        const nameNode = element.getNameNode();
        if (element.getDotDotDotToken()) {
          if (Node.isIdentifier(nameNode)) {
            setBinding(nameNode.getText(), paths, isDeclaration);
          }
          continue;
        }
        if (propertyNameNode) {
          propName = propertyNameNode.getText();
        } else if (Node.isIdentifier(nameNode)) {
          propName = nameNode.getText();
        }
        if (propName) {
          if (propName.startsWith("$") && propName !== "$on") continue;
          const propPrefix = `__prop_${propName}`;
          const matches = paths.filter((p) => p[0]?.name === propPrefix);
          let nextPaths;
          if (matches.length > 0) {
            nextPaths = matches.map((p) => p.slice(1));
          } else {
            nextPaths = paths.map((p) => [...p, { name: propName }]);
          }
          nextPaths.forEach((p) => mergePathAndArgs(result, p));
          if (Node.isIdentifier(nameNode)) {
            setBinding(nameNode.getText(), nextPaths, isDeclaration);
          } else if (Node.isObjectBindingPattern(nameNode) || Node.isArrayBindingPattern(nameNode)) {
            handleDestructuring(nameNode, nextPaths, isDeclaration);
          }
        }
      }
    } else if (Node.isArrayBindingPattern(pattern)) {
      const elements = pattern.getElements();
      for (let i = 0; i < elements.length; i++) {
        const element = elements[i];
        if (!Node.isOmittedExpression(element)) {
          const nameNode = element.getNameNode();
          const indexPrefix = `__index_${i}`;
          const elementPaths = paths.filter((p) => p[0]?.name === indexPrefix).map((p) => p.slice(1));
          const finalPaths = elementPaths.length > 0 ? elementPaths : paths;
          if (Node.isIdentifier(nameNode)) {
            setBinding(nameNode.getText(), finalPaths, isDeclaration);
          } else if (Node.isObjectBindingPattern(nameNode) || Node.isArrayBindingPattern(nameNode)) {
            handleDestructuring(nameNode, finalPaths, isDeclaration);
          }
        }
      }
    }
  }
  const visitedDecls = /* @__PURE__ */ new Map();
  let currentDepth = 0;
  const MAX_DEPTH = 10;
  const MAX_RECURSION_PER_DECL = 2;
  function resolveFunctionDefinition(symbol, onFileAccess) {
    if (!symbol) return void 0;
    let currentSym = symbol;
    const visitedSyms = /* @__PURE__ */ new Set();
    while (currentSym && !visitedSyms.has(currentSym)) {
      visitedSyms.add(currentSym);
      const prevSym = currentSym;
      const decls = currentSym.getDeclarations();
      if (onFileAccess && decls) {
        decls.forEach((d) => onFileAccess(d.getSourceFile()));
      }
      let decl = decls?.find(
        (d) => Node.isFunctionDeclaration(d) || Node.isArrowFunction(d) || Node.isFunctionExpression(d) || Node.isMethodDeclaration(d)
      );
      if (!decl) {
        const varDecl = decls?.find(
          (d) => Node.isVariableDeclaration(d) || Node.isPropertyAssignment(d)
        );
        if (varDecl && (Node.isVariableDeclaration(varDecl) || Node.isPropertyAssignment(varDecl))) {
          let initializer = varDecl.getInitializer();
          while (initializer) {
            if (Node.isAsExpression(initializer) || Node.isParenthesizedExpression(initializer)) {
              initializer = initializer.getExpression();
              continue;
            }
            if (Node.isCallExpression(initializer)) {
              const args = initializer.getArguments();
              let foundSubDecl = false;
              for (const arg of args) {
                const argSym = getSymbol(arg);
                let subDecl;
                if (argSym) {
                  subDecl = resolveFunctionDefinition(argSym, onFileAccess);
                }
                if (subDecl) {
                  initializer = subDecl;
                  foundSubDecl = true;
                  break;
                } else if (Node.isArrowFunction(arg) || Node.isFunctionExpression(arg)) {
                  initializer = arg;
                  foundSubDecl = true;
                  break;
                }
              }
              if (foundSubDecl) continue;
            }
            if (Node.isIdentifier(initializer)) {
              const sym = getSymbol(initializer);
              if (sym && !visitedSyms.has(sym)) {
                currentSym = sym;
                break;
              }
            }
            break;
          }
          if (initializer && !Node.isIdentifier(initializer)) {
            if (Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer)) {
              decl = initializer;
            }
          }
          if (decl) return decl;
          if (currentSym !== prevSym) continue;
        }
      }
      if (decl) return decl;
      try {
        const aliased = currentSym.getAliasedSymbol();
        if (aliased && aliased !== currentSym) {
          currentSym = aliased;
          continue;
        }
      } catch (e) {
      }
      break;
    }
    return void 0;
  }
  function executeIfFunction(paths, argsPaths, isolate = false) {
    let allRetPaths = [];
    let found = false;
    for (const p of paths) {
      for (const segment of p) {
        if (segment.name === "__decl" && segment.decl) {
          const fnDef = segment.decl;
          const retPaths = withRecursionGuard(fnDef, () => {
            return executeFunctionBody(
              fnDef.getBody(),
              () => {
                fnDef.getParameters().forEach((param, i) => {
                  if (i < argsPaths.length) {
                    bindParam(param.getNameNode(), argsPaths[i], true);
                  }
                });
              },
              isolate
            );
          });
          if (retPaths !== void 0) {
            allRetPaths.push(...retPaths);
            found = true;
          }
        }
      }
    }
    return found ? allRetPaths : void 0;
  }
  function evaluateExpression(originalNode) {
    if (!originalNode) return [];
    let node = originalNode;
    let k = node.getKind();
    while (k === SyntaxKind.ParenthesizedExpression || k === SyntaxKind.AsExpression || k === SyntaxKind.TypeAssertionExpression || k === SyntaxKind.NonNullExpression) {
      node = node.getExpression();
      k = node.getKind();
    }
    if (options.targetNodes) {
      const idx = options.targetNodes.indexOf(node);
      if (idx !== -1) {
        return [[{ name: `__target_${idx}` }]];
      }
    }
    const kind = node.getKind();
    if (kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NumericLiteral || kind === SyntaxKind.TrueKeyword || kind === SyntaxKind.FalseKeyword || kind === SyntaxKind.NullKeyword || kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.Identifier && node.getText() === "undefined") {
      return [[{ name: `__literal_${node.getText()}` }]];
    }
    if (Node.isIdentifier(node)) {
      const name = node.getText();
      if (hasBinding(name)) {
        return resolveBinding(name);
      }
      if (needsTypeChecker(node)) {
        const sym = getSymbol(node);
        const decl = resolveFunctionDefinition(sym, options.onFileAccess);
        if (decl) {
          return [[{ name: "__decl", decl }]];
        }
      }
      return [];
    }
    if (Node.isPropertyAccessExpression(node)) {
      const basePaths = evaluateExpression(node.getExpression());
      const name = node.getName();
      const propPrefix = `__prop_${name}`;
      const matchingPaths = basePaths.filter((p) => p[0]?.name === propPrefix);
      if (matchingPaths.length > 0) {
        return matchingPaths.map((p) => p.slice(1));
      }
      if (JS_INTERNALS.has(name) || name.startsWith("$") && name !== "$on") {
        if (JS_ARRAY_METHODS.has(name)) markAsList(basePaths);
        return name === "bind" ? basePaths : [];
      }
      const parent = node.getParent();
      const isCallExpr = parent && parent.getKind() === SyntaxKind.CallExpression && parent.getExpression() === node;
      const newPaths = [];
      for (const path5 of basePaths) {
        const nextPath = [...path5, { name }];
        if (!isCallExpr) {
          mergePathAndArgs(result, nextPath);
        }
        newPaths.push(nextPath);
      }
      return newPaths;
    }
    if (Node.isObjectLiteralExpression(node)) {
      const paths = [];
      node.getProperties().forEach((prop) => {
        if (Node.isPropertyAssignment(prop)) {
          const nameNode = prop.getNameNode();
          let name = "";
          if (Node.isComputedPropertyName(nameNode)) {
            const expr = nameNode.getExpression();
            if (Node.isStringLiteral(expr)) {
              name = expr.getLiteralText();
            }
          } else {
            name = prop.getName();
          }
          if (!name) return;
          const init = prop.getInitializer();
          if (init) {
            if (Node.isArrowFunction(init) || Node.isFunctionExpression(init)) {
              functionRegistry.set(name, init);
            }
            const initPaths = evaluateExpression(init);
            if (initPaths.length === 0) {
              paths.push([{ name: `__prop_${name}` }]);
            } else {
              for (const ip of initPaths) {
                paths.push([{ name: `__prop_${name}` }, ...ip]);
              }
            }
          }
        } else if (Node.isShorthandPropertyAssignment(prop)) {
          const name = prop.getName();
          const initPaths = resolveBinding(name);
          if (initPaths.length === 0) {
            paths.push([{ name: `__prop_${name}` }]);
          } else {
            for (const ip of initPaths) {
              paths.push([{ name: `__prop_${name}` }, ...ip]);
            }
          }
        } else if (Node.isMethodDeclaration(prop)) {
          const name = prop.getName();
          functionRegistry.set(name, prop);
          paths.push([{ name: `__prop_${name}` }]);
        } else if (Node.isSpreadAssignment(prop)) {
          const spreadPaths = evaluateExpression(prop.getExpression());
          paths.push(...spreadPaths);
        }
      });
      return paths;
    }
    if (Node.isArrayLiteralExpression(node)) {
      const paths = [];
      node.getElements().forEach((el) => {
        if (Node.isSpreadElement(el)) {
          paths.push(...evaluateExpression(el.getExpression()));
        } else {
          paths.push(...evaluateExpression(el));
        }
      });
      return paths;
    }
    if (Node.isSpreadElement(node)) {
      return evaluateExpression(node.getExpression());
    }
    if (Node.isElementAccessExpression(node)) {
      const basePaths = evaluateExpression(node.getExpression());
      const argExpr = node.getArgumentExpression();
      if (argExpr) {
        if (Node.isStringLiteral(argExpr) || Node.isNoSubstitutionTemplateLiteral(argExpr)) {
          const propName = argExpr.getLiteralText();
          if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(propName)) {
            const newPaths = [];
            for (const path5 of basePaths) {
              const nextPath = [...path5, { name: propName }];
              mergePathAndArgs(result, nextPath);
              newPaths.push(nextPath);
            }
            return newPaths;
          }
        }
        const baseType = getNodeType(node.getExpression());
        const argType = getNodeType(argExpr);
        if (baseType.isArray() || baseType.isTuple() || argType.isNumber() || argType.isNumberLiteral() || Node.isNumericLiteral(argExpr)) {
          markAsList(basePaths);
        }
      }
      if (argExpr) evaluateExpression(argExpr);
      return basePaths;
    }
    if (Node.isCallExpression(node)) {
      const args = node.getArguments();
      let argsString;
      const getArgsString = () => {
        if (argsString === void 0) {
          argsString = args.length > 0 ? args.map((arg) => stringifyArgument(arg)).join(", ") : "";
        }
        return argsString;
      };
      const expr = node.getExpression();
      const hookName = Node.isIdentifier(expr) ? expr.getText() : Node.isPropertyAccessExpression(expr) ? expr.getName() : "";
      if (hookName === "useMemo") {
        const firstArg = args[0];
        if (firstArg) {
          const paths = evaluateExpression(firstArg);
          const retPaths = executeIfFunction(paths, []);
          return retPaths !== void 0 ? retPaths : paths;
        }
      }
      if (hookName === "useCallback") {
        const firstArg = args[0];
        if (firstArg) {
          return evaluateExpression(firstArg);
        }
      }
      if (hookName === "useState") {
        const firstArg = args[0];
        const initPaths = firstArg ? evaluateExpression(firstArg) : [];
        const statePaths = initPaths.length > 0 ? initPaths.map((p) => [
          { name: "__index_0" },
          { name: "__state" },
          ...p
        ]) : [[{ name: "__index_0" }, { name: "__state" }]];
        return [...statePaths, [{ name: "__index_1" }]];
      }
      if (Node.isPropertyAccessExpression(expr)) {
        const methodName = expr.getName();
        const baseExpr = expr.getExpression();
        const basePaths = evaluateExpression(baseExpr);
        if (ITERATOR_METHODS.has(methodName)) {
          let baseType;
          if (needsTypeChecker(baseExpr)) {
            baseType = getNodeType(baseExpr);
          }
          if (!JS_SHARED_METHODS.has(methodName) || baseType && !(baseType.isString() || baseType.isStringLiteral())) {
            markAsList(basePaths);
          }
          let callbackPaths = [];
          node.getArguments().forEach((originalArg) => {
            let arg = originalArg;
            while (Node.isParenthesizedExpression(arg)) {
              arg = arg.getExpression();
            }
            if (Node.isArrowFunction(arg) || Node.isFunctionExpression(arg)) {
              callbackPaths = executeFunctionBody(arg.getBody(), () => {
                bindIteratorParam(arg.getParameters(), basePaths, methodName);
              });
            } else if (Node.isIdentifier(arg)) {
              const fnName = arg.getText();
              let fnDef = functionRegistry.get(fnName);
              if (!fnDef) {
                const paths = resolveBinding(fnName);
                for (const p of paths) {
                  for (const s of p) {
                    if (s.name === "__decl" && s.decl) {
                      fnDef = s.decl;
                      break;
                    }
                  }
                  if (fnDef) break;
                }
              }
              if (!fnDef) {
                let symbol;
                if (needsTypeChecker(arg)) {
                  symbol = getSymbol(arg) || getNodeType(arg).getSymbol();
                }
                fnDef = resolveFunctionDefinition(symbol, options.onFileAccess);
              }
              if (fnDef) {
                const result2 = withRecursionGuard(fnDef, () => {
                  return executeFunctionBody(fnDef.getBody(), () => {
                    bindIteratorParam(
                      fnDef.getParameters(),
                      basePaths,
                      methodName
                    );
                  });
                });
                if (result2) callbackPaths = result2;
              }
            } else {
              evaluateExpression(arg);
            }
          });
          return methodName === "map" && callbackPaths.length > 0 ? callbackPaths.map(
            (p) => p.map(
              (s, idx) => idx === p.length - 1 && (s.name === "__element" || s.name.startsWith("__index_") || !p.some((s2) => s2.name.startsWith("__prop_"))) ? { ...s, __isVirtual: true } : s
            )
          ) : basePaths;
        }
        if (JS_INTERNALS.has(methodName) || methodName.startsWith("$")) {
          if (JS_ARRAY_ONLY_METHODS.has(methodName)) {
            markAsList(basePaths);
          } else if (JS_SHARED_METHODS.has(methodName)) {
            if (needsTypeChecker(baseExpr)) {
              const baseType = getNodeType(baseExpr);
              if (!(baseType.isString() || baseType.isStringLiteral())) {
                markAsList(basePaths);
              }
            }
          }
          if (methodName === "push" || methodName === "unshift" || methodName === "splice") {
            node.getArguments().forEach((arg, i) => {
              if (methodName === "splice" && i < 2) {
                evaluateExpression(arg);
                return;
              }
              const argPaths = evaluateExpression(arg);
              basePaths.push(...argPaths);
            });
          } else {
            node.getArguments().forEach((arg) => evaluateExpression(arg) || []);
          }
          return methodName === "bind" ? basePaths : [];
        }
        let methodFnDef = functionRegistry.get(methodName);
        if (!methodFnDef) {
          if (needsTypeChecker(expr)) {
            const methodSymbol = getSymbol(expr);
            methodFnDef = resolveFunctionDefinition(
              methodSymbol,
              options.onFileAccess
            );
          }
        }
        if (!methodFnDef) {
          const nameNode = expr.getNameNode();
          if (nameNode && needsTypeChecker(nameNode)) {
            const nameSym = getSymbol(nameNode);
            if (nameSym) {
              methodFnDef = resolveFunctionDefinition(
                nameSym,
                options.onFileAccess
              );
            }
          }
        }
        const methodArgsPaths = node.getArguments().map((arg) => evaluateExpression(arg));
        const callPaths = evaluateExpression(expr);
        const retPaths = executeIfFunction(callPaths, methodArgsPaths);
        if (retPaths !== void 0) return retPaths;
        const newPaths = [];
        for (const path5 of basePaths) {
          const nextPath = [...path5, { name: methodName, args: getArgsString() }];
          mergePathAndArgs(result, nextPath);
          newPaths.push(nextPath);
        }
        return newPaths;
      }
      let basePathsForCall = [];
      if (Node.isIdentifier(expr)) {
        const fnName = expr.getText();
        let fnDef = functionRegistry.get(fnName);
        if (!fnDef) {
          if (needsTypeChecker(expr)) {
            const symbol = getSymbol(expr) || getNodeType(expr).getSymbol();
            fnDef = resolveFunctionDefinition(symbol, options.onFileAccess);
          }
        }
        const argsPaths = node.getArguments().map((arg) => evaluateExpression(arg));
        const callPaths = evaluateExpression(expr);
        const retPaths = executeIfFunction(callPaths, argsPaths);
        if (retPaths !== void 0) return retPaths;
        if (fnDef) {
          const retPaths2 = withRecursionGuard(fnDef, () => {
            return executeFunctionBody(fnDef.getBody(), () => {
              fnDef.getParameters().forEach((param, i) => {
                if (i < argsPaths.length) {
                  bindParam(param.getNameNode(), argsPaths[i], true);
                }
              });
            });
          });
          if (retPaths2) return retPaths2;
        }
        basePathsForCall = resolveBinding(fnName);
      } else {
        basePathsForCall = evaluateExpression(expr);
      }
      if (basePathsForCall.length > 0) {
        const newPaths = [];
        for (const path5 of basePathsForCall) {
          if (path5.length > 0) {
            const last = path5[path5.length - 1];
            const nextPath = [
              ...path5.slice(0, -1),
              { ...last, args: getArgsString() }
            ];
            mergePathAndArgs(result, nextPath);
            newPaths.push(nextPath);
          }
        }
        if (newPaths.length > 0) return newPaths;
      }
      return [];
    }
    if (Node.isJsxOpeningElement(node) || Node.isJsxSelfClosingElement(node)) {
      const tagNameNode = node.getTagNameNode();
      const tagNameString = tagNameNode.getText();
      let decl;
      if (!/^[a-z]/.test(tagNameString)) {
        if (Node.isIdentifier(tagNameNode)) {
          decl = functionRegistry.get(tagNameString);
          if (!decl) {
            const paths = resolveBinding(tagNameString);
            for (const p of paths) {
              for (const s of p) {
                if (s.name === "__decl" && s.decl) {
                  decl = s.decl;
                  break;
                }
              }
              if (decl) break;
            }
          }
        }
        if (!decl) {
          let symbol;
          if (needsTypeChecker(tagNameNode)) {
            symbol = getSymbol(tagNameNode) || getNodeType(tagNameNode).getSymbol();
          }
          decl = resolveFunctionDefinition(symbol, options.onFileAccess);
        }
      }
      const attributes = node.getAttributes();
      const propsPaths = /* @__PURE__ */ new Map();
      attributes.forEach((attr) => {
        if (Node.isJsxAttribute(attr)) {
          const name = attr.getNameNode().getText();
          const initializer = attr.getInitializer();
          if (initializer) {
            const valPaths = Node.isJsxExpression(initializer) ? evaluateExpression(initializer.getExpression()) : evaluateExpression(initializer);
            propsPaths.set(name, valPaths);
            executeIfFunction(valPaths, []);
          }
        } else if (Node.isJsxSpreadAttribute(attr)) {
          const expr = attr.getExpression();
          const spreadPaths = evaluateExpression(expr);
          for (const path5 of spreadPaths) {
            if (path5[0]?.name.startsWith("__prop_")) {
              const propName = path5[0].name.replace("__prop_", "");
              const existing = propsPaths.get(propName) || [];
              propsPaths.set(propName, [...existing, path5.slice(1)]);
            }
          }
        }
      });
      if (decl) {
        withRecursionGuard(decl, () => {
          return executeFunctionBody(
            decl.getBody(),
            () => {
              const params = decl.getParameters();
              if (params.length > 0) {
                const propsParam = params[0].getNameNode();
                if (Node.isObjectBindingPattern(propsParam)) {
                  for (const element of propsParam.getElements()) {
                    const name = element.getPropertyNameNode()?.getText() || element.getName();
                    const paths = propsPaths.get(name) || [];
                    bindParam(element.getNameNode(), paths, true);
                  }
                } else {
                  const allPaths = [];
                  propsPaths.forEach((paths, name) => {
                    paths.forEach((p) => {
                      allPaths.push([{ name: `__prop_${name}` }, ...p]);
                    });
                  });
                  bindParam(propsParam, allPaths, true);
                }
              }
            },
            true
          );
        });
      }
      return [];
    }
    if (Node.isConditionalExpression(node)) {
      evaluateExpression(node.getCondition());
      branchDepth++;
      const truePaths = evaluateExpression(node.getWhenTrue());
      const falsePaths = evaluateExpression(node.getWhenFalse());
      branchDepth--;
      return [...truePaths, ...falsePaths];
    }
    if (Node.isBinaryExpression(node) && node.getOperatorToken().getKind() === SyntaxKind.EqualsToken) {
      const right = node.getRight();
      const left = node.getLeft();
      const paths = evaluateExpression(right);
      if (Node.isIdentifier(left)) {
        setBinding(left.getText(), paths);
      } else {
        evaluateExpression(left);
      }
      return paths;
    }
    if (Node.isArrowFunction(node) || Node.isFunctionExpression(node)) {
      const resultPaths = executeFunctionBody(node.getBody());
      return [[{ name: "__decl", decl: node }], ...resultPaths];
    }
    if (Node.isBinaryExpression(node)) {
      const left = evaluateExpression(node.getLeft());
      const right = evaluateExpression(node.getRight());
      return [...left, ...right];
    }
    node.forEachChild((child) => {
      evaluateExpression(child);
    });
    return [];
  }
  function analyzeStatement(stmt) {
    if (Node.isVariableStatement(stmt)) {
      for (const decl of stmt.getDeclarations()) {
        const initializer = decl.getInitializer();
        const paths = initializer ? evaluateExpression(initializer) : [];
        const nameNode = decl.getNameNode();
        const name = nameNode.getText();
        if (initializer && (Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer))) {
          functionRegistry.set(name, initializer);
          const containsTarget = !options.targetNodes || options.targetNodes.some(
            (target) => initializer.getStart() <= target.getStart() && initializer.getEnd() >= target.getEnd()
          );
          if (containsTarget) {
            executeFunctionBody(initializer.getBody());
          }
        }
        bindParam(nameNode, paths, true);
      }
    } else if (Node.isExpressionStatement(stmt)) {
      evaluateExpression(stmt.getExpression());
    } else if (Node.isIfStatement(stmt)) {
      evaluateExpression(stmt.getExpression());
      branchDepth++;
      analyzeStatement(stmt.getThenStatement());
      const elseStmt = stmt.getElseStatement();
      if (elseStmt) analyzeStatement(elseStmt);
      branchDepth--;
    } else if (Node.isSwitchStatement(stmt)) {
      evaluateExpression(stmt.getExpression());
      branchDepth++;
      stmt.getClauses().forEach((clause) => {
        clause.getStatements().forEach(analyzeStatement);
      });
      branchDepth--;
    } else if (Node.isForStatement(stmt)) {
      const initializer = stmt.getInitializer();
      if (initializer && Node.isVariableDeclarationList(initializer)) {
        scopes.push({ bindings: /* @__PURE__ */ new Map() });
        for (const decl of initializer.getDeclarations()) {
          const init = decl.getInitializer();
          if (init) {
            const paths = evaluateExpression(init);
            bindParam(decl.getNameNode(), paths);
          }
        }
      }
      const condition = stmt.getCondition();
      if (condition) evaluateExpression(condition);
      const incrementor = stmt.getIncrementor();
      if (incrementor) evaluateExpression(incrementor);
      analyzeStatement(stmt.getStatement());
      if (initializer && Node.isVariableDeclarationList(initializer)) {
        scopes.pop();
      }
    } else if (Node.isForOfStatement(stmt)) {
      scopes.push({ bindings: /* @__PURE__ */ new Map() });
      const paths = evaluateExpression(stmt.getExpression());
      markAsList(paths);
      const initializer = stmt.getInitializer();
      if (Node.isVariableDeclarationList(initializer)) {
        for (const decl of initializer.getDeclarations()) {
          bindParam(decl.getNameNode(), paths);
        }
      }
      analyzeStatement(stmt.getStatement());
      scopes.pop();
    } else if (Node.isBlock(stmt)) {
      const stmts = stmt.getStatements();
      if (stmts.length > 5 && !textMentionsTracked(stmt)) return;
      scopes.push({ bindings: /* @__PURE__ */ new Map() });
      stmts.forEach(analyzeStatement);
      scopes.pop();
    } else if (Node.isReturnStatement(stmt)) {
      const expr = stmt.getExpression();
      if (expr) {
        lastReturnedPaths = evaluateExpression(expr);
        if (lastReturnedPaths.length > 0) {
          let parent = stmt.getParent();
          while (parent && !Node.isFunctionDeclaration(parent) && !Node.isArrowFunction(parent) && !Node.isFunctionExpression(parent)) {
            parent = parent.getParent();
          }
          if (parent && (Node.isFunctionDeclaration(parent) || Node.isArrowFunction(parent) || Node.isFunctionExpression(parent))) {
            const existing = exportedFunctionReturns.get(parent) || [];
            exportedFunctionReturns.set(parent, [
              ...existing,
              ...lastReturnedPaths
            ]);
          }
        }
      }
    } else if (Node.isFunctionDeclaration(stmt)) {
      const name = stmt.getName();
      if (name) functionRegistry.set(name, stmt);
      const containsTarget = !options.targetNodes || options.targetNodes.some(
        (target) => stmt.getStart() <= target.getStart() && stmt.getEnd() >= target.getEnd()
      );
      if (containsTarget) {
        scopes.push({ bindings: /* @__PURE__ */ new Map() });
        executeFunctionBody(stmt.getBody());
        scopes.pop();
      }
    } else {
      stmt.forEachChild(analyzeStatement);
    }
  }
  const walkOuter = (node) => {
    if (Node.isFunctionDeclaration(node)) {
      const name = node.getName();
      if (name) functionRegistry.set(name, node);
      const params = node.getParameters();
      if (params.length > 0 && options.rootObjectName) {
        const paramNameNode = params[0].getNameNode();
        if (Node.isObjectBindingPattern(paramNameNode)) {
          for (const el of paramNameNode.getElements()) {
            const propName = el.getPropertyNameNode()?.getText() || el.getName();
            if (propName === options.rootObjectName) {
              scopes.push({ bindings: /* @__PURE__ */ new Map() });
              bindParam(el.getNameNode(), [[]]);
              const body = node.getBody();
              if (body && Node.isBlock(body)) {
                body.getStatements().forEach(analyzeStatement);
              }
              scopes.pop();
            }
          }
        }
      }
    }
    if (Node.isFunctionDeclaration(node) && !options.targetNodes) {
      const body = node.getBody();
      if (body && !textMentionsTracked(body)) return;
    }
    if (Node.isStatement(node)) {
      analyzeStatement(node);
    } else {
      node.forEachChild(walkOuter);
    }
  };
  walkOuter(sourceFile);
  return { result, exportedFunctionReturns };
}
var _sharedProject;
function clearAnalyzeCache() {
  _sharedProject = void 0;
  projectImporterGraphCache = /* @__PURE__ */ new WeakMap();
}
var projectImporterGraphCache = /* @__PURE__ */ new WeakMap();
function extractQueries(filePath, project, options = {}) {
  const accessedFiles = /* @__PURE__ */ new Set();
  accessedFiles.add(filePath);
  const { pylonPackage = "@getcronit/pylon/pages", hookName = "useData" } = options;
  const sourceFile = project.getSourceFileOrThrow(filePath);
  if (!options.skipDependencyResolution) {
    project.resolveSourceFileDependencies();
  }
  const targetNodes = findUseQueries(sourceFile, pylonPackage, hookName);
  if (targetNodes.length === 0) {
    return { queries: [], dependencies: Array.from(accessedFiles) };
  }
  const { result, exportedFunctionReturns } = coreAnalyze(sourceFile, {
    targetNodes,
    onFileAccess: (sf) => accessedFiles.add(sf.getFilePath())
  });
  const processedCallSites = /* @__PURE__ */ new Set();
  const functionQueue = Array.from(
    exportedFunctionReturns.entries()
  );
  const processedFunctions = /* @__PURE__ */ new Set();
  let directImporterGraph = projectImporterGraphCache.get(project);
  function buildImporterGraph() {
    if (directImporterGraph) return;
    directImporterGraph = /* @__PURE__ */ new Map();
    function addToGraph(importedPath, importer) {
      let set = directImporterGraph.get(importedPath);
      if (!set) {
        set = /* @__PURE__ */ new Set();
        directImporterGraph.set(importedPath, set);
      }
      set.add(importer);
    }
    project.getSourceFiles().forEach((sf) => {
      const text = sf.compilerNode.text;
      if (!text.includes("import") && !text.includes("export")) return;
      sf.getImportDeclarations().forEach((imp) => {
        const moduleSF = imp.getModuleSpecifierSourceFile();
        if (moduleSF) addToGraph(moduleSF.getFilePath(), sf);
      });
      sf.getExportDeclarations().forEach((exp) => {
        const moduleSF = exp.getModuleSpecifierSourceFile();
        if (moduleSF) addToGraph(moduleSF.getFilePath(), sf);
      });
    });
    projectImporterGraphCache.set(project, directImporterGraph);
  }
  function getTransitiveImporters(sfPath, visited = /* @__PURE__ */ new Set()) {
    const result2 = /* @__PURE__ */ new Set();
    const direct = directImporterGraph?.get(sfPath);
    if (!direct) return result2;
    visited.add(sfPath);
    for (const importer of direct) {
      result2.add(importer);
      const impPath = importer.getFilePath();
      if (!visited.has(impPath)) {
        const sub = getTransitiveImporters(impPath, visited);
        sub.forEach((s) => result2.add(s));
      }
    }
    return result2;
  }
  function findCallSitesInFile(sf, fnName) {
    if (!sf.compilerNode.text.includes(fnName)) return [];
    return sf.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => {
      const expr = call.getExpression();
      const name = Node.isIdentifier(expr) ? expr.getText() : Node.isPropertyAccessExpression(expr) ? expr.getName() : "";
      return name === fnName;
    });
  }
  const referencesCache = /* @__PURE__ */ new Map();
  function getCachedReferences(fn) {
    let refs = referencesCache.get(fn);
    if (refs !== void 0) return refs;
    refs = fn.findReferences?.() || [];
    referencesCache.set(fn, refs);
    return refs;
  }
  const analysisCache = /* @__PURE__ */ new Map();
  function getCachedAnalysis(sf, targets) {
    const cacheKey = sf.getFilePath() + ":" + targets.map((t) => t.getStart() + "-" + t.getEnd()).join(",");
    let cached = analysisCache.get(cacheKey);
    if (cached) return cached;
    cached = coreAnalyze(sf, {
      targetNodes: targets,
      onFileAccess: (s) => accessedFiles.add(s.getFilePath())
    });
    analysisCache.set(cacheKey, cached);
    return cached;
  }
  while (functionQueue.length > 0) {
    const [fn, paths] = functionQueue.shift();
    if (processedFunctions.has(fn)) continue;
    processedFunctions.add(fn);
    const targetPaths = paths.filter(
      (p) => p.some((step) => step.name.startsWith("__target_"))
    );
    if (targetPaths.length === 0) continue;
    buildImporterGraph();
    const callNodes = [];
    if (Node.isFunctionDeclaration(fn) || Node.isArrowFunction(fn) || Node.isFunctionExpression(fn)) {
      const name = fn.getName?.();
      const sf = fn.getSourceFile();
      const sfPath = sf.getFilePath();
      if (name) {
        callNodes.push(...findCallSitesInFile(sf, name));
      }
      const importers = getTransitiveImporters(sfPath);
      if (importers.size > 0 && name) {
        for (const importer of importers) {
          callNodes.push(...findCallSitesInFile(importer, name));
        }
      }
    }
    if (callNodes.length === 0) {
      const references = getCachedReferences(fn);
      for (const refSymbol of references) {
        for (const match of refSymbol.getReferences()) {
          callNodes.push(match.getNode());
        }
      }
    }
    for (const node of callNodes) {
      if (processedCallSites.has(node)) continue;
      processedCallSites.add(node);
      let call = node;
      while (call && !Node.isCallExpression(call)) {
        call = call.getParent();
      }
      if (call && Node.isCallExpression(call)) {
        accessedFiles.add(call.getSourceFile().getFilePath());
        const callerAnalysis = getCachedAnalysis(call.getSourceFile(), [call]);
        for (const [
          newFn,
          newPaths
        ] of callerAnalysis.exportedFunctionReturns.entries()) {
          functionQueue.push([newFn, newPaths]);
        }
        const externalSelectors = callerAnalysis.result["__target_0"] || {};
        const shadowedProperties = /* @__PURE__ */ new Set();
        for (const p of paths) {
          if (p[0]?.name.startsWith("__prop_")) {
            shadowedProperties.add(p[0].name.replace(/^__prop_/, ""));
          }
        }
        for (const tp of targetPaths) {
          const targetIdx = tp.findIndex(
            (step) => step.name.startsWith("__target_")
          );
          if (targetIdx === -1) continue;
          const prefixes = tp.slice(0, targetIdx);
          const suffixes = tp.slice(targetIdx + 1);
          let currentExt = externalSelectors;
          let skip = false;
          for (const pref of prefixes) {
            const cleanName = pref.name.replace(/^__prop_/, "");
            if (currentExt && typeof currentExt === "object" && cleanName in currentExt) {
              currentExt = currentExt[cleanName];
            } else {
              skip = true;
              break;
            }
          }
          if (skip || !currentExt) continue;
          if (suffixes.length > 0 && typeof currentExt === "object") {
            currentExt = { ...currentExt };
            delete currentExt.__args;
          }
          if (prefixes.length === 0 && typeof currentExt === "object") {
            const filtered = { ...currentExt };
            for (const shadow of shadowedProperties) {
              delete filtered[shadow];
            }
            currentExt = filtered;
          }
          const targetKey = tp[targetIdx].name;
          const subPath = tp.slice(targetIdx + 1);
          let currentLevel = result[targetKey] || (result[targetKey] = {});
          let parent = result;
          let lastKey = targetKey;
          for (let i = 0; i < subPath.length; i++) {
            const step = subPath[i];
            if (step.name === "__element" || step.name === "__decl" || step.name.startsWith("__prop_")) {
              continue;
            }
            const isLast = i === subPath.length - 1;
            if (currentLevel[step.name] === true && !isLast) {
              currentLevel[step.name] = {};
            }
            parent = currentLevel;
            lastKey = step.name;
            if (isLast) {
              if (currentExt === true) {
                if (!currentLevel[step.name] || currentLevel[step.name] === true) {
                  currentLevel[step.name] = true;
                }
              } else if (typeof currentExt === "object" && Object.keys(currentExt).length > 0) {
                if (!currentLevel[step.name] || currentLevel[step.name] === true) {
                  currentLevel[step.name] = {};
                }
                deepMerge(currentLevel[step.name], currentExt);
              } else {
                if (currentLevel[step.name] === void 0) {
                  currentLevel[step.name] = true;
                }
              }
              break;
            }
            currentLevel = currentLevel[step.name] || (currentLevel[step.name] = {});
          }
          continue;
        }
      }
    }
  }
  return {
    queries: targetNodes.map((node, idx) => ({
      start: node.getStart(),
      end: node.getEnd(),
      selectors: result[`__target_${idx}`] || {},
      node
    })),
    dependencies: Array.from(accessedFiles)
  };
}
function deepMerge(target, source) {
  if (!source || typeof source !== "object") return;
  for (const key in source) {
    if (key === "__element" || key.startsWith("__prop_") || key === "__decl") {
      continue;
    }
    if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
      if (!target[key] || typeof target[key] !== "object") {
        target[key] = {};
      }
      deepMerge(target[key], source[key]);
    } else {
      if (source[key] === true && typeof target[key] === "object") {
        continue;
      }
      target[key] = source[key];
    }
  }
}
function findUseQueries(sourceFile, pylonPackage, hookName) {
  if (!sourceFile.compilerNode.text.includes(hookName)) return [];
  const useQueryAliases = /* @__PURE__ */ new Set();
  const targetNodes = [];
  const visit = (node) => {
    if (Node.isImportDeclaration(node)) {
      const moduleSpecifier = node.getModuleSpecifierValue();
      if (moduleSpecifier === pylonPackage) {
        const importClause = node.getImportClause();
        if (importClause) {
          const namedBindings = importClause.getNamedBindings();
          if (namedBindings && Node.isNamedImports(namedBindings)) {
            for (const el of namedBindings.getElements()) {
              const originalName = el.getNameNode().getText();
              const aliasNode = el.getAliasNode();
              const localName = aliasNode ? aliasNode.getText() : originalName;
              if (originalName === hookName) {
                useQueryAliases.add(localName);
              }
            }
          }
        }
      }
    } else if (Node.isCallExpression(node)) {
      const expression = node.getExpression();
      if (Node.isIdentifier(expression) && useQueryAliases.has(expression.getText())) {
        targetNodes.push(node);
      }
    }
    node.forEachChild(visit);
  };
  visit(sourceFile);
  return targetNodes;
}

// src/plugins/use-pages/build/plugins/use-data-static-analyzer/manager.ts
import * as crypto from "crypto";
import { Project as Project2 } from "ts-morph";
var StaticAnalysisManager = class {
  project;
  cache = /* @__PURE__ */ new Map();
  sessionResults = /* @__PURE__ */ new Map();
  lastSessionReset = 0;
  constructor(options) {
    this.project = new Project2({
      tsConfigFilePath: options.tsConfigFilePath,
      skipAddingFilesFromTsConfig: true,
      compilerOptions: {
        allowJs: true,
        jsx: 4,
        // ReactJSX
        moduleResolution: 2,
        // Node
        esModuleInterop: true,
        target: 9
        // ESNext
      }
    });
  }
  /**
   * Resets the session cache if enough time has passed since the last reset.
   * This allows client and server builds starting together to share results.
   */
  resetSession() {
    const now = Date.now();
    if (now - this.lastSessionReset > 500) {
      this.sessionResults.clear();
      this.lastSessionReset = now;
    }
  }
  getProject() {
    return this.project;
  }
  getCachedResult(path5, content) {
    const hash = this.computeHash(content);
    const sessionResult = this.sessionResults.get(path5);
    if (sessionResult && sessionResult.hash === hash) {
      return sessionResult;
    }
    const cached = this.cache.get(path5);
    if (cached && cached.hash === hash) {
      return cached;
    }
    return null;
  }
  setCache(path5, result) {
    this.cache.set(path5, result);
    this.sessionResults.set(path5, result);
  }
  updateSourceFile(path5, content) {
    const existing = this.project.getSourceFile(path5);
    if (existing) {
      if (existing.getFullText() !== content) {
        existing.replaceWithText(content);
      }
      return existing;
    }
    return this.project.createSourceFile(path5, content, { overwrite: true });
  }
  computeHash(content) {
    return crypto.createHash("md5").update(content).digest("hex");
  }
};

// src/plugins/use-pages/build/plugins/use-data-static-analyzer/selectors-to-prepare.ts
function generatePrepare(selectors) {
  let depth = 0;
  let varCount = 0;
  function compileNode(node, accessPath) {
    const lines = [];
    for (const [key, value] of Object.entries(node)) {
      if (key === "__args" || key === "__isList") continue;
      const isIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
      const base = isIdentifier ? `${accessPath}?.${key}` : `${accessPath}?.[${JSON.stringify(key)}]`;
      if (value === true) {
        lines.push(`${base};`);
        continue;
      }
      const branches = Array.isArray(value) ? value : [value];
      for (const branch of branches) {
        let nodeAccess = base;
        if (typeof branch === "object" && branch !== null) {
          if (branch.__args !== void 0) {
            nodeAccess += `?.(${branch.__args})`;
          }
          if (branch.__isList) {
            depth++;
            const iter = `i${depth}`;
            const sub = compileNode(branch, iter);
            if (sub.length === 0) {
              lines.push(`${nodeAccess};`);
            } else {
              lines.push(`${nodeAccess}?.map(${iter} => { ${sub.join(" ")} });`);
            }
            depth--;
            continue;
          }
          const childKeys = Object.keys(branch).filter(
            (k) => k !== "__args" && k !== "__isList"
          );
          if (childKeys.length > 1 || childKeys.length > 0 && branch.__args !== void 0) {
            const varName = `v${++varCount}`;
            lines.push(`const ${varName} = ${nodeAccess};`);
            lines.push(...compileNode(branch, varName));
            continue;
          } else if (childKeys.length > 0) {
            lines.push(...compileNode(branch, nodeAccess));
            continue;
          }
        }
        lines.push(`${nodeAccess};`);
      }
    }
    return lines;
  }
  const internals = compileNode(selectors, "query");
  if (internals.length === 0) return `({ query }) => {}`;
  return `({ query }) => { ${internals.join(" ")} }`;
}

// src/plugins/use-pages/build/plugins/use-data-static-analyzer/index.ts
function useDataStaticAnalyzer(options = {}) {
  const {
    filter = /\.(ts|tsx)$/,
    pylonPackage = "@getcronit/pylon/pages",
    hookName = "useData",
    debug = false
  } = options;
  return {
    name: "pylon-use-data-static-analyzer",
    async setup(build2) {
      const manager = options.manager || new StaticAnalysisManager({
        tsConfigFilePath: build2.initialOptions.tsconfig
      });
      const project = manager.getProject();
      build2.onStart(() => {
        manager.resetSession();
        clearAnalyzeCache();
      });
      const entries = build2.initialOptions.entryPoints;
      if (entries) {
        const entryPaths = [];
        if (Array.isArray(entries)) {
          for (const entry of entries) {
            entryPaths.push(
              typeof entry === "string" ? entry : entry.in
            );
          }
        } else if (entries && typeof entries === "object") {
          for (const key in entries) {
            entryPaths.push(entries[key]);
          }
        }
        if (entryPaths.length > 0) {
          project.addSourceFilesAtPaths(entryPaths);
          project.resolveSourceFileDependencies();
        }
      }
      build2.onLoad({ filter }, async (args) => {
        const contents = await fs5.promises.readFile(args.path, "utf8");
        const cached = manager.getCachedResult(args.path, contents);
        if (cached) {
          return {
            contents: cached.contents,
            loader: args.path.endsWith(".tsx") ? "tsx" : "ts",
            watchFiles: cached.dependencies
          };
        }
        if (!contents.includes(pylonPackage) || !contents.includes(hookName) && !contents.includes("from")) {
          manager.setCache(args.path, {
            contents,
            dependencies: [args.path],
            hash: manager.computeHash(contents)
          });
          return null;
        }
        manager.updateSourceFile(args.path, contents);
        if (debug) {
          console.log(`[Pylon] Analyzing ${args.path}`);
        }
        try {
          const { queries, dependencies } = extractQueries(args.path, project, {
            pylonPackage,
            hookName,
            skipDependencyResolution: true
          });
          let outputContents = contents;
          if (queries.length > 0) {
            const sortedQueries = [...queries].sort((a, b) => b.start - a.start);
            for (const query of sortedQueries) {
              const node = query.node;
              const args2 = node.getArguments();
              const prepareFn = generatePrepare(query.selectors);
              if (args2.length === 0) {
                const closeParen = node.getLastChildByKind(
                  SyntaxKind2.CloseParenToken
                );
                const pos = closeParen ? closeParen.getStart() : node.getEnd() - 1;
                outputContents = outputContents.slice(0, pos) + `{
  prepare: ${prepareFn}
}` + outputContents.slice(pos);
              } else {
                const firstArg = args2[0];
                if (Node2.isObjectLiteralExpression(firstArg)) {
                  const startPos = firstArg.getStart() + 1;
                  const text = firstArg.getText();
                  const isEmpty = text.replace(/\s/g, "") === "{}";
                  const injection = isEmpty ? `
  prepare: ${prepareFn}
` : `
  prepare: ${prepareFn},`;
                  outputContents = outputContents.slice(0, startPos) + injection + outputContents.slice(startPos);
                } else {
                  const startPos = firstArg.getStart();
                  const endPos = firstArg.getEnd();
                  const existingText = outputContents.slice(startPos, endPos);
                  outputContents = outputContents.slice(0, startPos) + `{
  ...${existingText},
  prepare: ${prepareFn}
}` + outputContents.slice(endPos);
                }
              }
            }
            if (debug) {
              console.log(
                `[Pylon] Effectively injected selectors into ${queries.length} calls in ${args.path}`
              );
            }
          }
          manager.setCache(args.path, {
            contents: outputContents,
            dependencies,
            hash: manager.computeHash(contents)
          });
          const loader = args.path.endsWith(".tsx") ? "tsx" : "ts";
          return {
            contents: outputContents,
            loader,
            watchFiles: dependencies
          };
        } catch (err) {
          console.error(`[Pylon] Error analyzing ${args.path}:`, err);
          return null;
        }
      });
    }
  };
}

// src/plugins/use-pages/build/index.ts
var DIST_STATIC_DIR = path4.join(process.cwd(), ".pylon/__pylon/static");
var DIST_PAGES_DIR = path4.join(process.cwd(), ".pylon/__pylon/pages");
async function updateFileIfChanged(filePath, newContent) {
  await fs6.mkdir(path4.dirname(filePath), { recursive: true });
  try {
    const currentContent = await fs6.readFile(filePath);
    if (currentContent.equals(newContent)) {
      return false;
    }
  } catch (err) {
    if (err.code !== "ENOENT") throw err;
  }
  await fs6.writeFile(filePath, newContent);
  return true;
}
var build = async ({ onBuild }) => {
  const version = Math.random().toString(36).substring(7);
  const buildAppFile = async () => {
    const appFiles = makeAppFiles();
    await updateFileIfChanged(
      path4.resolve(process.cwd(), ".pylon", "app.tsx"),
      Buffer.from(appFiles.routes)
    );
  };
  const copyPublicDir = async () => {
    const publicDir = path4.resolve(process.cwd(), "public");
    const pylonPublicDir = path4.resolve(
      process.cwd(),
      ".pylon",
      "__pylon",
      "public"
    );
    try {
      await fs6.access(publicDir);
      await fs6.mkdir(pylonPublicDir, { recursive: true });
      await fs6.cp(publicDir, pylonPublicDir, { recursive: true, force: true });
    } catch (err) {
      if (err.code !== "ENOENT") throw err;
    }
  };
  const pylonCssPath = path4.join(
    process.cwd(),
    "node_modules",
    "@getcronit/pylon/dist/pages/index.css"
  );
  const buildAppFilePlugin = {
    name: "build-app-file",
    setup(build2) {
      build2.onStart(async () => {
        await buildAppFile();
      });
    }
  };
  const writeOnEndPlugin = {
    name: "write-on-end",
    setup(build2) {
      build2.initialOptions.metafile = true;
      build2.initialOptions.write = false;
      build2.onEnd(async (result) => {
        const manifest = {};
        for (const [key, value] of Object.entries(
          result.metafile?.outputs || {}
        )) {
          if (value.entryPoint === ".pylon/app.tsx") {
            manifest["app.js"] = key;
            if (value.cssBundle) {
              manifest["app.css"] = value.cssBundle;
            }
          } else if (value.entryPoint?.endsWith("pylon/dist/pages/index.css")) {
            manifest["index.css"] = key;
          } else if (value.entryPoint?.endsWith("pages/sitemap.ts")) {
            manifest["sitemap.js"] = key;
          }
        }
        if (build2.initialOptions.publicPath) {
          const publicPath = build2.initialOptions.publicPath;
          for (const [key, value] of Object.entries(manifest)) {
            const index = value.indexOf(publicPath);
            if (index !== -1) {
              manifest[key] = value.slice(index);
            }
          }
        }
        manifest["version"] = version;
        await updateFileIfChanged(
          path4.join(build2.initialOptions.outdir, "manifest.json"),
          Buffer.from(JSON.stringify(manifest, null, 2))
        );
        await Promise.all(
          result.outputFiles.map(async (file) => {
            await fs6.mkdir(path4.dirname(file.path), { recursive: true });
            await updateFileIfChanged(file.path, file.contents);
          })
        );
        if (result.errors.length === 0) {
          onBuild();
        }
      });
    }
  };
  const nodePaths = [
    path4.join(process.cwd(), "node_modules"),
    path4.join(process.cwd(), "node_modules", "@getcronit/pylon/node_modules")
  ];
  let pagesWatcher = null;
  const timePlugin = (name) => ({
    name: "rebuild-log",
    setup({ onStart, onEnd }) {
      var t;
      onStart(() => {
        t = Date.now();
      });
      onEnd(() => {
        console.log(`Pages [${name}] Rebuild took ${Date.now() - t}ms`);
      });
    }
  });
  const sitemapExists = await fs6.access(path4.join(process.cwd(), "pages/sitemap.ts")).then(() => true).catch(() => false);
  const tsConfigPath = path4.join(process.cwd(), "tsconfig.json");
  const tsConfigExists = await fs6.access(tsConfigPath).then(() => true).catch(() => false);
  const analysisManager = new StaticAnalysisManager({
    tsConfigFilePath: tsConfigExists ? tsConfigPath : void 0
  });
  const clientCtx = await esbuild.context({
    sourcemap: "linked",
    write: false,
    metafile: true,
    nodePaths,
    absWorkingDir: process.cwd(),
    plugins: [
      buildAppFilePlugin,
      injectAppHydrationPlugin(version),
      useDataStaticAnalyzer({ debug: true, manager: analysisManager }),
      imagePlugin,
      postcssPlugin,
      writeOnEndPlugin,
      timePlugin("client")
    ],
    publicPath: "/__pylon/static",
    assetNames: "assets/[name]-[hash]",
    chunkNames: "chunks/[name]-[hash]",
    entryNames: "./[name]-[hash]",
    format: "esm",
    platform: "browser",
    entryPoints: [".pylon/app.tsx", pylonCssPath],
    outdir: DIST_STATIC_DIR,
    bundle: true,
    splitting: true,
    minify: false,
    loader: {
      // Map file extensions to the file loader
      ".svg": "file",
      ".woff": "file",
      ".woff2": "file",
      ".ttf": "file",
      ".otf": "file"
    },
    define: {
      "process.env.NODE_ENV": JSON.stringify(
        process.env.NODE_ENV || "development"
      )
    },
    mainFields: ["browser", "module", "main"]
  });
  const serverCtx = await esbuild.context({
    sourcemap: "inline",
    write: false,
    metafile: true,
    absWorkingDir: process.cwd(),
    nodePaths,
    plugins: [
      buildAppFilePlugin,
      useDataStaticAnalyzer({ debug: true, manager: analysisManager }),
      imagePlugin,
      postcssPlugin,
      writeOnEndPlugin,
      timePlugin("server"),
      esmExternalsPlugin([
        "@getcronit/pylon",
        "react",
        "react-dom",
        "gqty",
        "@gqty/react"
      ])
    ],
    publicPath: "/__pylon/static",
    assetNames: "assets/[name]-[hash]",
    chunkNames: "chunks/[name]-[hash]",
    entryNames: "./[name]-[hash]",
    format: "esm",
    platform: "node",
    entryPoints: [
      ".pylon/app.tsx",
      pylonCssPath,
      ...sitemapExists ? ["./pages/sitemap.ts"] : []
    ],
    outdir: DIST_PAGES_DIR,
    bundle: true,
    splitting: false,
    external: ["@getcronit/pylon", "react", "react-dom", "gqty", "@gqty/react"],
    minify: true,
    loader: {
      // Map file extensions to the file loader
      ".svg": "file",
      ".woff": "file",
      ".woff2": "file",
      ".ttf": "file",
      ".otf": "file"
    },
    define: {
      "process.env.NODE_ENV": JSON.stringify(
        process.env.NODE_ENV || "development"
      )
    },
    mainFields: ["module", "main"]
  });
  return {
    watch: async () => {
      await buildAppFile();
      await copyPublicDir();
      pagesWatcher = chokidar.watch("pages", { ignoreInitial: true });
      pagesWatcher.on("all", async (event, path5) => {
        if (["add", "change", "unlink"].includes(event)) {
          await copyPublicDir();
        }
      });
      await Promise.all([clientCtx.watch(), serverCtx.watch()]);
    },
    dispose: async () => {
      if (pagesWatcher) {
        pagesWatcher.close();
      }
      Promise.all([clientCtx.dispose(), serverCtx.dispose()]);
    },
    rebuild: async () => {
      await copyPublicDir();
      await Promise.all([clientCtx.rebuild(), serverCtx.rebuild()]);
      return {};
    },
    cancel: async () => {
      if (pagesWatcher) {
        await pagesWatcher.close();
      }
      await Promise.all([clientCtx.cancel(), serverCtx.cancel()]);
    }
  };
};
export {
  build
};
//# sourceMappingURL=build-TGNP3US3.js.map