# @theorchard/frontend-vite

Vite plugins and config helpers for suite apps. A standalone alternative to `frontend-cli-vite` that lets you bring your own Vite setup instead of relying on the opinionated CLI.

## Installation

```sh
pnpm add -D @theorchard/frontend-vite vite
```

## Usage

A minimal `vite.config.ts` for a suite app:

```ts
import { suiteApp } from '@theorchard/frontend-vite';
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
import graphqlLoader from 'vite-plugin-graphql-loader';

export default defineConfig(({ mode }) => {
    const env = loadEnv(mode, process.cwd(), '');
    Object.assign(process.env, env);

    return {
        plugins: [suiteApp(), react(), graphqlLoader()],
        resolve: {
            tsconfigPaths: true,
        },
    };
});
```

`suiteApp()` automatically sets `base`, `build`, and `server.port` to the correct suite defaults. Any of these can be overridden in your config and the plugin will leave your values untouched.

## API

### Plugins

#### `suiteApp(options?: { serve?: { htmlFile?: string; html?: HtmlBuildConfig; locale?: string }; build?: { html?: HtmlBuildConfig; locale?: string } }): Plugin[]`

The core suite bootstrap. Returns four Vite plugins:

1. **`suite-app-defaults`** (`enforce: 'pre'`) — sets `base`, `build`, and `server.port` to the correct suite defaults if not already present in the user config. User config values always take precedence.
2. **`frontend-config-bootstrap`** — injects `window.FRONTEND_CONFIG` and the Segment analytics snippet into the HTML head via mustache placeholders. Runs in both dev and build.
3. **`frontend-config-mustache`** — reads `frontend.json` (or `frontend.config.json`, etc.) from the project root and renders the HTML through mustache with the resolved config. Dev only (`apply: 'serve'`).
4. **`frontend-config-build`** — production only (`apply: 'build'`). Uses the `generateBundle` hook to fan out all HTML variants defined in `html.files`. Each variant is rendered with mustache and emitted as a separate asset (e.g. `index.html`, `index-sme.html`, `index-admin.html`).

```ts
import { suiteApp } from '@theorchard/frontend-vite';

// in plugins:
suiteApp();
```

The optional `serve.htmlFile` selects which variant to render during dev. `serve.html` overrides the html config for dev; `build.html` overrides it for production (affecting which variant files are generated).

```ts
// Select an HTML file variant for local dev:
suiteApp({ serve: { htmlFile: process.env.HTML_FILE } });
// HTML_FILE=sme vite dev
```

```ts
// Override html config for production fan-out:
suiteApp({ build: { html: { files: [...] } } })
```

During a production build (`vite build`), all variants listed in `html.files` in your frontend config are automatically generated — no post-processing step required.

### Config helpers

These utilities are used internally by `suite-app-defaults` and are exported for advanced use cases where you need explicit control (e.g. computing values outside of a plugin hook).

#### `resolveBase(): Promise<string>`

Resolves the Vite [`base`](https://vite.dev/config/shared-options.html#base) path for a suite app. Priority order:

-   `PUBLIC_PATH` env var — runtime override, highest priority (e.g. set by Jenkins for PR deployments)
-   `publicPath` in `frontend.json` — static config override
-   In production: `<CDN_URL>/<package-slug>/` (from `CDN_URL` env var)
-   In development: `/`

**Jenkins / CI example** — set `PUBLIC_PATH` before the build:

```sh
PUBLIC_PATH=https://qa-cdn.theorchard.io/my-app/prs/42/ pnpm build
```

```ts
export default defineConfig(async () => ({
    base: await resolveBase(),
    // ...
}));
```

#### `resolveBuildConfig(): BuildOptions`

Resolves the Vite [`build`](https://vite.dev/config/build-options.html) options for a suite app. Sets the output directory to `build/`, enables the manifest and sourcemaps, and applies slug-based chunk naming expected by the suite CDN deployment pipeline.

The resolved config looks like:

```ts
{
    outDir: 'build',
    manifest: true,
    assetsDir: '',
    sourcemap: true,
    rollupOptions: {
        output: {
            entryFileNames: '<slug>-[name]-[hash].js',
            assetFileNames: '<slug>-[name]-[hash][extname]',
            chunkFileNames: '<slug>-[name]-[hash].js',
        },
    },
}
```

## Frontend config

The plugins read your app's frontend config from the project root. Supported filenames (in order of precedence):

-   `frontend.json`
-   `frontend.config.json`
-   `frontend.config.js`
-   `config/frontend.json`
-   `frontend.<ENV>.json` / `config/frontend.<ENV>.json`
-   `frontend.local.json` / `config/frontend.local.json`

## Peer dependencies

| Package | Version   |
| ------- | --------- |
| `vite`  | `>=7.0.0` |
