Le transport est figé au build par Vite : un seul `dist` ne peut pas servir
à la fois le desktop (IPC Tauri) et le navigateur (HTTP+WS). Le serveur
embarqué servait donc un bundle desktop, d'où `__TAURI_INTERNALS__ is
undefined` côté navigateur.
- `vite.config.ts` devient une factory `({ mode })` : le mode par défaut émet
le bundle desktop (`dist`), `--mode web` lit `.env.web` et émet le bundle
navigateur (`dist-web`).
- `.env.web` porte `VITE_TRANSPORT=http` dans un fichier de mode plutôt qu'en
préfixe de commande, syntaxe qui n'existe pas sous Windows (bundle NSIS).
- `transport.ts` extrait le prédicat `transportFromEnv()`, partagé par l'app et
la config de build : le constant `__IDEA_TRANSPORT__` et le transport résolu
dérivent de la même variable via le même prédicat, ils ne peuvent pas diverger.
- `main.tsx` publie `__IDEA_TRANSPORT__` sur `window` : l'affectation est un
effet de bord, elle survit à la minification et rend un bundle identifiable
sans grep d'un symbole minifié. Les deux jeux d'adapters étant présents dans
les deux bundles, leur présence ne prouve rien.
Le chemin desktop est inchangé : le web reste opt-in.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
/** React bootstrap: mounts the app inside the DI provider. */
|
|
|
|
import React from "react";
|
|
import ReactDOM from "react-dom/client";
|
|
|
|
import { App } from "./App";
|
|
import { ViewWindow, parseViewWindowParams } from "./ViewWindow";
|
|
import { WebApp } from "@/features/web";
|
|
import { DIProvider, resolveTransport } from "./di";
|
|
import "@/shared/styles/theme.css";
|
|
|
|
const root = document.getElementById("root");
|
|
if (!root) {
|
|
throw new Error("missing #root element");
|
|
}
|
|
|
|
// #23/#47: a detached view window loads the SPA with `?panel=` (panel-only, no
|
|
// project id). When the param is present and valid, render only that view — it
|
|
// follows the main window's focused project; otherwise the full app.
|
|
const viewParams = parseViewWindowParams(window.location.search);
|
|
|
|
// Ticket #74, F1: publish the transport this bundle was built for. `define`
|
|
// inlines it as a literal, and assigning it is a side effect, so it survives
|
|
// minification and tree-shaking — a built bundle can be identified (by QA, or
|
|
// from devtools) without grepping for a minified symbol. Both adapter sets ship
|
|
// in either bundle, so their mere presence proves nothing.
|
|
(window as unknown as { __IDEA_TRANSPORT__?: string }).__IDEA_TRANSPORT__ =
|
|
__IDEA_TRANSPORT__;
|
|
|
|
// Ticket #13, F2: in web (HTTP) transport mode the browser client renders the
|
|
// pairing-gated, read-only `WebApp`. Desktop (Tauri) is unchanged — it renders
|
|
// the full `App` (or a detached view window). Detached windows are desktop-only.
|
|
const isWeb = resolveTransport() === "http";
|
|
|
|
ReactDOM.createRoot(root).render(
|
|
<React.StrictMode>
|
|
<DIProvider>
|
|
{isWeb ? (
|
|
<WebApp />
|
|
) : viewParams ? (
|
|
<ViewWindow panel={viewParams.panel} />
|
|
) : (
|
|
<App />
|
|
)}
|
|
</DIProvider>
|
|
</React.StrictMode>,
|
|
);
|