Files
team2/vite.config.ts
zeekayandHanzo Dev 42a7d04c57 Open a card, and sign in without leaving the page
The credential POST carries `credentials: include`, and hanzo.id answers
allow-credentials for hanzo.team but not for team2.hanzo.ai or loopback —
so the dev proxy is what makes the exchange same-origin, and a published
build on an untrusted host falls back to the redirect.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 13:22:55 -07:00

78 lines
3.0 KiB
TypeScript

import { hanzo } from '@hanzo/vite'
import react from '@vitejs/plugin-react'
/**
* The bundler. Resolving the Hanzo runtime — `~/…`, react-native-web, one copy
* of gui — comes from `hanzo()`, stated once for every Hanzo app rather than
* copied into each. What is left is this app's own.
*
* There is no CSS pipeline because there is no CSS to build: @hanzo/ui ships one
* generated stylesheet that `<Hanzo>` imports, and the styles gui derives from
* props it inserts at runtime.
*/
/**
* A single-page app has one document and many addresses, so every address that
* is not a file has to arrive at that document. The Sites plane answers a miss
* with the site's own `404.html`, so emitting the document under that name is
* the whole fix, and it is the convention every static host already implements.
* The status stays 404 — the browser runs the bundle regardless and the router
* takes the address from there, while a crawler still reads "not a page I
* publish", which is true of every address except the ones the router invents.
*/
const fallback = {
name: 'fallback',
async writeBundle(options: { dir?: string }) {
const { copyFile } = await import('node:fs/promises')
const { join } = await import('node:path')
const dir = options.dir ?? 'dist'
await copyFile(join(dir, 'index.html'), join(dir, '404.html'))
},
}
/**
* The dev proxy, and it is load-bearing rather than a convenience.
*
* `src/data` addresses `/v1` relatively so that no module in this app learns an
* API host; without this the dev server answers its own index.html for every
* call and a JSON parse fails somewhere far from the cause. It also makes the
* issuer's credential exchange SAME-ORIGIN, which is what lets sign-in happen
* in place on a loopback host that hanzo.id does not answer with
* `Access-Control-Allow-Credentials`.
*/
const API = 'https://api.hanzo.ai'
const config = hanzo(
{
plugins: [react(), fallback],
server: {
port: 3095,
// Reachable by LAN name in dev; vite 8 refuses an unlisted Host by
// default. Dev only — a built app is static and has no host allowlist.
allowedHosts: true,
proxy: { '/v1': { target: API, changeOrigin: true } },
},
},
{ root: import.meta.dirname },
)
/**
* Dependency optimization is a SECOND resolution pass and inherits nothing from
* the first, so it has to be told the same thing: on the web a react-native
* package's `.web.js` sibling comes first. Left out, the optimizer follows
* react-native-svg's fabric components into react-native's Flow source and the
* DEV SERVER dies at startup — while `vite build`, which uses the resolver
* above, succeeds, so nothing warns you until you try to develop.
*
* The list is read back from the config rather than restated: two copies of an
* extension order is how one of them silently stops matching the other.
*/
export default {
...config,
optimizeDeps: {
rollupOptions: {
resolve: { extensions: (config.resolve as { extensions: string[] }).extensions },
},
},
}