{"version":3,"file":"vite.mjs","names":[],"sources":["../src/vite.ts"],"sourcesContent":["import { mergeConfig } from \"vite\";\nimport type { Plugin, ResolvedConfig, ViteBuilder } from \"vite\";\n\nimport {\n  analyzeUseClientDirectives,\n  cleanId,\n  isJavaScriptId,\n  patchClientReferencePlaceholdersInBundle,\n  publicOutputPath,\n  transformUseClientForClient,\n  transformUseClientForServer,\n  type AstProgram,\n  type ClientReference,\n} from \"./transforms.ts\";\n\ntype Options = {\n  clientEnvironment?: string;\n  serverEnvironments?: string[];\n};\n\ntype BuildState = {\n  builder: ViteBuilder;\n  clientEnvironment: string;\n  serverEnvironmentNames: Set<string>;\n  serverEnvironmentsAtGenerateBundle: Set<string>;\n  clientBuild: PromiseWithResolvers<void>;\n  clientBuildStart?: Promise<void>;\n};\n\nexport default function srvJsx(options?: Options): Plugin {\n  const clientEnvironment = options?.clientEnvironment ?? \"client\";\n  const serverEnvironments = new Set(options?.serverEnvironments ?? [\"ssr\"]);\n  const clientReferences = new Map<string, ClientReference>();\n  const directiveFiles = new Set<string>();\n  let config: ResolvedConfig | undefined;\n  let buildState: BuildState | undefined;\n\n  return {\n    name: \"srv-jsx\",\n    sharedDuringBuild: true,\n    perEnvironmentStartEndDuringDev: true,\n    configResolved(resolvedConfig) {\n      config = resolvedConfig;\n    },\n    configEnvironment(name, userConfig) {\n      if (name !== clientEnvironment) return;\n      return mergeConfig(\n        {\n          build: {\n            rolldownOptions: {\n              preserveEntrySignatures: \"exports-only\",\n            },\n          },\n        } as typeof userConfig,\n        userConfig,\n      );\n    },\n    config: {\n      order: \"post\",\n      handler(userConfig) {\n        return mergeConfig(\n          {\n            builder: {\n              async buildApp(builder) {\n                await buildEnvironmentsServerFirst(\n                  builder,\n                  clientEnvironment,\n                  serverEnvironments,\n                  (state) => {\n                    buildState = state;\n                  },\n                );\n              },\n            },\n          } satisfies typeof userConfig,\n          userConfig,\n        );\n      },\n    },\n    buildApp: {\n      order: \"pre\",\n      async handler(builder) {\n        await buildEnvironmentsServerFirst(\n          builder,\n          clientEnvironment,\n          serverEnvironments,\n          (state) => {\n            buildState = state;\n          },\n        );\n      },\n    },\n    options(inputOptions) {\n      if (this.environment.name !== clientEnvironment) return null;\n      if (directiveFiles.size === 0) return null;\n\n      return {\n        ...inputOptions,\n        input: addClientInputs(inputOptions.input, directiveFiles) as typeof inputOptions.input,\n        preserveEntrySignatures: \"exports-only\",\n      };\n    },\n    async generateBundle(_outputOptions, bundle) {\n      const currentConfig = config;\n      const environmentName = this.environment.name;\n\n      if (environmentName === clientEnvironment && currentConfig) {\n        for (const output of Object.values(bundle)) {\n          if (output.type !== \"chunk\" || !output.facadeModuleId) continue;\n\n          const id = cleanId(output.facadeModuleId);\n          if (!directiveFiles.has(id)) continue;\n\n          clientReferences.set(id, {\n            mod: publicOutputPath(output.fileName, currentConfig.base),\n            deps: output.imports.map((fileName) => publicOutputPath(fileName, currentConfig.base)),\n          });\n        }\n        return;\n      }\n\n      if (!serverEnvironments.has(environmentName)) return;\n\n      if (buildState?.serverEnvironmentNames.has(environmentName)) {\n        await waitForClientBuildFromServerGenerateBundle(buildState, environmentName);\n        patchClientReferencePlaceholdersInBundle(bundle, clientReferences);\n      }\n    },\n    transform(code, id) {\n      if (!code.includes(\"use client\")) return null;\n\n      const cleanModuleId = cleanId(id);\n      if (!isJavaScriptId(cleanModuleId)) return null;\n\n      const ast = this.parse(code) as unknown as AstProgram;\n      const analysis = analyzeUseClientDirectives(code, ast);\n      if (!analysis.moduleDirective && analysis.inlineDirectives.length === 0) return null;\n\n      directiveFiles.add(cleanModuleId);\n\n      const transformOptions = {\n        id: cleanModuleId,\n        root: config?.root,\n        base: config?.base,\n        references: clientReferences,\n        placeholders: buildState?.serverEnvironmentNames.has(this.environment.name),\n      };\n\n      if (this.environment.name === clientEnvironment) {\n        return transformUseClientForClient(code, ast, transformOptions);\n      }\n\n      if (serverEnvironments.has(this.environment.name)) {\n        return transformUseClientForServer(code, ast, transformOptions);\n      }\n\n      return null;\n    },\n  };\n}\n\nfunction buildEnvironmentsServerFirst(\n  builder: ViteBuilder,\n  clientEnvironment: string,\n  serverEnvironments: Set<string>,\n  setBuildState: (state: BuildState | undefined) => void,\n) {\n  return (async () => {\n    const serverEnvironmentNames = new Set(\n      [...serverEnvironments].filter(\n        (name) => builder.environments[name] && !builder.environments[name].isBuilt,\n      ),\n    );\n    const buildState: BuildState = {\n      builder,\n      clientEnvironment,\n      serverEnvironmentNames,\n      serverEnvironmentsAtGenerateBundle: new Set(),\n      clientBuild: Promise.withResolvers<void>(),\n    };\n\n    setBuildState(buildState);\n    try {\n      if (serverEnvironmentNames.size > 0) {\n        await Promise.all(\n          [...serverEnvironmentNames].map((name) => builder.build(builder.environments[name]!)),\n        );\n      } else {\n        startClientBuild(buildState);\n        await buildState.clientBuild.promise;\n      }\n\n      for (const environment of Object.values(builder.environments)) {\n        if (!environment.isBuilt) {\n          await builder.build(environment);\n        }\n      }\n    } finally {\n      setBuildState(undefined);\n    }\n  })();\n}\n\nfunction waitForClientBuildFromServerGenerateBundle(\n  buildState: BuildState,\n  environmentName: string,\n) {\n  buildState.serverEnvironmentsAtGenerateBundle.add(environmentName);\n\n  if (\n    buildState.serverEnvironmentsAtGenerateBundle.size === buildState.serverEnvironmentNames.size\n  ) {\n    startClientBuild(buildState);\n  }\n\n  return buildState.clientBuild.promise;\n}\n\nfunction startClientBuild(buildState: BuildState) {\n  if (buildState.clientBuildStart) return;\n\n  const client = buildState.builder.environments[buildState.clientEnvironment];\n  if (!client || client.isBuilt) {\n    buildState.clientBuild.resolve();\n    buildState.clientBuildStart = buildState.clientBuild.promise;\n    return;\n  }\n\n  buildState.clientBuildStart = buildState.builder.build(client).then(\n    () => {\n      buildState.clientBuild.resolve();\n    },\n    (error: unknown) => {\n      buildState.clientBuild.reject(error);\n    },\n  );\n}\n\nfunction addClientInputs(input: unknown, files: Set<string>) {\n  if (files.size === 0) return input;\n\n  const entries = [...files].sort();\n\n  if (typeof input === \"string\") return [input, ...entries];\n  if (Array.isArray(input)) return [...input, ...entries];\n\n  const objectInput: Record<string, unknown> =\n    input && typeof input === \"object\" ? { ...input } : {};\n  for (const file of entries) {\n    objectInput[`srv-jsx-client-${hashString(file)}`] = file;\n  }\n  return objectInput;\n}\n\nfunction hashString(value: string) {\n  let hash = 5381;\n  for (let index = 0; index < value.length; index++) {\n    hash = (hash * 33) ^ value.charCodeAt(index);\n  }\n  return (hash >>> 0).toString(36);\n}\n"],"mappings":"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"}