import {
  INITIAL_STATE_WINDOW_PROPERTY,
  getApp,
  getChildNodes
} from "./chunk-PPE2X6R3.mjs";

// src/server/toolpadAppBuilder.ts
import * as path3 from "path";
import * as url from "node:url";
import react from "@vitejs/plugin-react";
import { indent } from "@mui/toolpad-utils/strings";

// src/utils/paths.ts
import * as path from "path";
function toPosixPath(importPath) {
  return path.normalize(importPath).split(path.sep).join(path.posix.sep);
}
function pathToNodeImportSpecifier(importPath) {
  const normalized = toPosixPath(importPath);
  return normalized.startsWith("/") || normalized.startsWith(".") ? normalized : `./${normalized}`;
}

// src/server/viteVirtualPlugin.ts
import { posix as path2 } from "path";
import { transformWithEsbuild } from "vite";
var API_PROPERTY = Symbol("virtual-fs-api");
function virtualFsPlugin(initialFiles, userIdentifier) {
  const prefix = `virtual:${userIdentifier}:`;
  const resolvedPrefix = `\0${prefix}`;
  const transformExtensions = /* @__PURE__ */ new Set([".js", ".jsx", ".ts", ".tsx"]);
  const resolveExtensions = /* @__PURE__ */ new Set([".js", ".jsx", ".ts", ".tsx", ".json"]);
  let serverInstance;
  let files = initialFiles;
  return {
    name: "virtual-fs",
    enforce: "pre",
    configureServer(server) {
      serverInstance = server;
    },
    resolveId(id, importer) {
      if (id.startsWith(prefix)) {
        const entryPath = id.slice(prefix.length);
        if (files.has(entryPath)) {
          return `${resolvedPrefix}${entryPath}`;
        }
        for (const extension of resolveExtensions) {
          const entryPathWithExtension = `${entryPath}${extension}`;
          if (files.has(entryPathWithExtension)) {
            return `${resolvedPrefix}${entryPathWithExtension}`;
          }
        }
      } else if (importer?.startsWith(resolvedPrefix)) {
        const importerPath = importer.slice(resolvedPrefix.length);
        const fullPath = path2.resolve(path2.dirname(importerPath), id);
        return this.resolve(`${prefix}${fullPath}`, importer);
      }
      return null;
    },
    async load(id) {
      if (id.startsWith(resolvedPrefix)) {
        const virtualPath = id.slice(resolvedPrefix.length);
        const content = files.get(virtualPath);
        return content;
      }
      return null;
    },
    async transform(code, id) {
      if (id.startsWith(resolvedPrefix)) {
        const virtualPath = id.slice(resolvedPrefix.length);
        if (transformExtensions.has(path2.extname(virtualPath))) {
          return transformWithEsbuild(code, virtualPath);
        }
      }
      return null;
    },
    [API_PROPERTY]: {
      async replaceFiles(newFiles) {
        const filesToInvalidate = [];
        for (const [virtualPath, content] of files) {
          if (!newFiles.has(virtualPath) || newFiles.get(virtualPath) !== content) {
            filesToInvalidate.push(virtualPath);
          }
        }
        files = newFiles;
        if (serverInstance) {
          for (const virtualPath of filesToInvalidate) {
            const resolvedId = `${resolvedPrefix}${virtualPath}`;
            const mod = serverInstance.moduleGraph.getModuleById(resolvedId);
            if (mod) {
              serverInstance.reloadModule(mod);
            }
          }
        } else {
          console.warn("Server instance not found, cannot invalidate files");
        }
      }
    }
  };
}
function replaceFiles(plugin, newFiles) {
  return plugin[API_PROPERTY].replaceFiles(newFiles);
}

// src/server/toolpadAppBuilder.ts
import.meta.url ??= url.pathToFileURL(__filename).toString();
var currentDirectory = url.fileURLToPath(new URL(".", import.meta.url));
var MAIN_ENTRY = "/main.tsx";
var CANVAS_ENTRY = "/canvas.tsx";
function getHtmlContent({ canvas, base }) {
  const entryPoint = canvas ? CANVAS_ENTRY : MAIN_ENTRY;
  const devtoolsSrc = `${base}/__toolpad_dev__/reactDevtools/bootstrap.global.js`;
  return `
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>Toolpad</title>
        <link
          rel="stylesheet"
          href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
        />
      </head>
      <body>
        <div id="root"></div>

        ${canvas ? `
              <script>
                // Add the data-toolpad-canvas attribute to the canvas iframe element
                if (window.frameElement?.dataset.toolpadCanvas) {
                  var script = document.createElement('script');
                  script.src = ${JSON.stringify(devtoolsSrc)};
                  document.write(script.outerHTML);
                }
              </script>
            ` : ""}
    
        <!-- __TOOLPAD_SCRIPTS__ -->

        <script type="module" src=${JSON.stringify(entryPoint)}></script>
      </body>
    </html>
  `;
}
function toolpadVitePlugin({ base }) {
  return {
    name: "toolpad",
    async resolveId(id) {
      if (id.endsWith(".html")) {
        return id;
      }
      return null;
    },
    async load(id) {
      if (id.endsWith(".html")) {
        return getHtmlContent({ canvas: false, base });
      }
      return null;
    },
    transform(code, id) {
      if (/\/resources\//.test(id)) {
        const codeFile = path3.basename(id);
        const functionExports = [];
        const lines = code.split("\n");
        for (let i = 0; i < lines.length; i += 1) {
          const line = lines[i];
          const lineNr = i + 1;
          if (/\s*export\b/.test(line)) {
            const match = line.match(/\s*export\s+async\s+function\s+([a-zA-Z0-9]+)\b/);
            if (match) {
              const functionName = match[1];
              functionExports.push(functionName);
            } else {
              console.warn(
                `Unsupported export at "${id}:${lineNr}". Only exports of the form "export async function foo(...) {" are supported.`
              );
            }
          }
        }
        return `
          import { createRemoteFunction } from '@mui/toolpad/runtime';

          const functionFile = ${JSON.stringify(codeFile)};

          ${functionExports.map(
          (functionName) => `const __${functionName} = createRemoteFunction(functionFile, ${JSON.stringify(
            functionName
          )})`
        ).join("\n")}

          export {
            ${functionExports.map((functionName) => `__${functionName} as ${functionName}`).join(",\n")}
          }
        `;
      }
      return code;
    }
  };
}
async function createViteConfig({
  outDir,
  root,
  dev,
  base,
  customServer,
  plugins = [],
  getComponents,
  loadDom,
  getPagesManifest
}) {
  const mode = dev ? "development" : "production";
  const getEntryPoint = (isCanvas) => {
    const componentsId = "virtual:toolpad-files:components.tsx";
    const pageComponentsId = "virtual:toolpad-files:page-components.tsx";
    return `
import { init, setComponents } from '@mui/toolpad/runtime';
import components from ${JSON.stringify(componentsId)};
import pageComponents from ${JSON.stringify(pageComponentsId)};
${isCanvas ? `import AppCanvas from '@mui/toolpad/canvas'` : ""}

const initialState = window[${JSON.stringify(INITIAL_STATE_WINDOW_PROPERTY)}];

setComponents(components, pageComponents);

init({
  ${isCanvas ? `ToolpadApp: AppCanvas,` : ""}
  base: ${JSON.stringify(base)},
  initialState,
})

if (import.meta.hot) {
  // TODO: investigate why this doesn't work, see https://github.com/vitejs/vite/issues/12912
  import.meta.hot.accept(
    [${JSON.stringify(componentsId)}, ${JSON.stringify(pageComponentsId)}],
    (newComponents, newPageComponents) => {
    if (newComponents) {
      console.log('hot updating Toolpad components')
      setComponents(
        newComponents ?? components,
        newPageComponents ?? pageComponents
      );
    }
  });
}
`;
  };
  const createComponentsFile = async () => {
    const components = await getComponents();
    const imports = components.map(
      ({ name }) => `import ${name} from 'toolpad-user-project:./components/${name}';`
    );
    const defaultExportProperties = components.map(
      ({ name }) => `${JSON.stringify(`codeComponent.${name}`)}: ${name}`
    );
    const code = `
      ${imports.join("\n")}

      export default {
        ${indent(defaultExportProperties.join(",\n"), 2)}
      };
    `;
    return {
      code,
      map: null
    };
  };
  const createPageComponentsFile = async () => {
    const dom = await loadDom();
    const appNode = getApp(dom);
    const { pages = [] } = getChildNodes(dom, appNode);
    const imports = /* @__PURE__ */ new Map();
    for (const page of pages) {
      const codeFile = page.attributes.codeFile;
      if (codeFile) {
        const importPath = path3.resolve(root, `./pages/${page.name}/page`);
        const relativeImportPath = path3.relative(root, importPath);
        const importSpec = `toolpad-user-project:${pathToNodeImportSpecifier(relativeImportPath)}`;
        imports.set(page.name, importSpec);
      }
    }
    const importLines = Array.from(
      imports.entries(),
      ([name, spec]) => `${name}: React.lazy(() => import(${JSON.stringify(spec)}))`
    );
    const code = `
      import * as React from 'react';
      
      export default {
        ${importLines.join(",\n")}
      }
    `;
    return {
      code,
      map: null
    };
  };
  const virtualFiles = /* @__PURE__ */ new Map([
    ["main.tsx", getEntryPoint(false)],
    ["canvas.tsx", getEntryPoint(true)],
    ["components.tsx", await createComponentsFile()],
    ["page-components.tsx", await createPageComponentsFile()],
    ["pages-manifest.json", JSON.stringify(await getPagesManifest(), null, 2)]
  ]);
  const virtualToolpadFiles = virtualFsPlugin(virtualFiles, "toolpad-files");
  return {
    reloadComponents: async () => {
      const newFiles = new Map(virtualFiles);
      newFiles.set("components.tsx", await createComponentsFile());
      replaceFiles(virtualToolpadFiles, newFiles);
    },
    viteConfig: {
      configFile: false,
      mode,
      build: {
        outDir,
        chunkSizeWarningLimit: Infinity,
        rollupOptions: {
          onwarn(warning, warn) {
            if (warning.code === "MODULE_LEVEL_DIRECTIVE") {
              return;
            }
            warn(warning);
          }
        }
      },
      envFile: false,
      resolve: {
        alias: [
          {
            // FIXME(https://github.com/mui/material-ui/issues/35233)
            find: /^@mui\/icons-material\/(?!esm\/)([^/]*)/,
            replacement: "@mui/icons-material/esm/$1"
          },
          {
            find: /^toolpad-user-project:(.*)$/,
            replacement: `${root}/$1`
          },
          {
            find: MAIN_ENTRY,
            replacement: "virtual:toolpad-files:main.tsx"
          },
          {
            find: CANVAS_ENTRY,
            replacement: "virtual:toolpad-files:canvas.tsx"
          }
        ]
      },
      server: {
        fs: {
          allow: [root, path3.resolve(currentDirectory, "../../../../")]
        }
      },
      optimizeDeps: {
        include: [
          "@emotion/cache",
          "@emotion/react",
          "@mui/icons-material",
          "@mui/icons-material/ArrowDropDownRounded",
          "@mui/icons-material/Close",
          "@mui/icons-material/Delete",
          "@mui/icons-material/DarkMode",
          "@mui/icons-material/Edit",
          "@mui/icons-material/Error",
          "@mui/icons-material/HelpOutlined",
          "@mui/icons-material/LightMode",
          "@mui/icons-material/OpenInNew",
          "@mui/icons-material/SettingsBrightnessOutlined",
          "@mui/lab",
          "@mui/material",
          "@mui/material/CircularProgress",
          "@mui/material/Button",
          "@mui/material/colors",
          "@mui/material/styles",
          "@mui/material/useMediaQuery",
          "@mui/utils",
          "@mui/utils/useEventCallback",
          "@mui/x-data-grid-pro",
          "@mui/x-date-pickers/AdapterDayjs",
          "@mui/x-date-pickers/DesktopDatePicker",
          "@mui/x-date-pickers/LocalizationProvider",
          "@mui/x-license-pro",
          "@tanstack/react-query",
          "@tanstack/react-query-devtools/build/modern/production.js",
          "dayjs",
          "dayjs/locale/en",
          "dayjs/locale/fr",
          "dayjs/locale/nl",
          "fractional-indexing",
          "invariant",
          "lodash-es",
          "markdown-to-jsx",
          "nanoid/non-secure",
          "prop-types",
          "react",
          "react-dom",
          "react-dom/client",
          "react-error-boundary",
          "react-hook-form",
          "react-is",
          "react-router-dom",
          "react/jsx-dev-runtime",
          "react/jsx-runtime",
          "recharts",
          "superjson",
          "title",
          "zod"
        ],
        exclude: [
          "@mui/toolpad-core",
          "@mui/toolpad/browser",
          "@mui/toolpad/runtime",
          "@mui/toolpad/canvas"
        ]
      },
      appType: "custom",
      logLevel: "info",
      root,
      plugins: [virtualToolpadFiles, react(), toolpadVitePlugin({ base }), ...plugins],
      base,
      define: {
        "process.env.NODE_ENV": `'${mode}'`,
        "process.env.BASE_URL": `'${base}'`,
        "process.env.TOOLPAD_CUSTOM_SERVER": `'${JSON.stringify(customServer)}'`
      }
    }
  };
}
async function buildApp({
  root,
  base,
  getComponents,
  getPagesManifest,
  loadDom,
  outDir
}) {
  const { viteConfig } = await createViteConfig({
    dev: false,
    root,
    base,
    outDir,
    getComponents,
    getPagesManifest,
    loadDom
  });
  const vite = await import("vite");
  await vite.build(viteConfig);
}

export {
  getHtmlContent,
  createViteConfig,
  buildApp
};
//# sourceMappingURL=chunk-REPPYLTL.mjs.map