managarten/apps/mana/apps/web/vite.config.ts
Till JS 8a991f7c39 feat(articles): M7 share-target + bookmarklet — save from anywhere
@mana/shared-pwa gains PWAShareTarget + PWAShareTargetParams types
plus ManifestConfig.share_target pass-through. createPWAConfig now
accepts an optional `shareTarget` and threads it into the generated
manifest. Other apps keep working unchanged — the field is omitted
unless set.

Web app wiring:
 - vite.config.ts passes shareTarget: { action: '/articles/add',
   method: 'GET', params: { title, text, url } } so the installed PWA
   shows up as a destination in the Android / Chromium share sheet.
 - AddUrlForm reads ?url / ?text / ?title in onMount; falls back to
   the first URL-shaped token in ?text because some senders (Chrome
   Android, WhatsApp) put the shared link there instead of ?url. When
   a URL is pre-filled the Readability preview auto-triggers, so the
   user just hits "In Leseliste speichern" to confirm.
 - New /articles/settings route hosts the bookmarklet (drag-to-
   bookmarks-bar button + copy-to-clipboard + expandable snippet
   viewer) and a short Share-Target explainer with an iOS-Safari
   caveat. Linked from the ListView via a new gear button next to
   "+ Neu speichern".

Bookmarklet form (origin-prefixed so it works across tenants):
  javascript:void(window.open('${origin}/articles/add?url='+…))

Not in scope (plan marked optional): _pendingUrls offline queue.
Share without internet shows the existing error + retry state today;
can slot in as M7b if users hit it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 19:03:33 +02:00

134 lines
4.9 KiB
TypeScript

import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';
// `defineConfig` from vitest/config is a superset of vite's that
// recognizes the `test:` block. Without this, the inline test exclude
// below trips a "test does not exist on UserConfigExport" type error.
import { defineConfig } from 'vitest/config';
import { SvelteKitPWA } from '@vite-pwa/sveltekit';
import { createPWAConfig } from '@mana/shared-pwa';
import { MANA_SHARED_PACKAGES, getBuildDefines } from '@mana/shared-vite-config';
/** App-specific shared packages used by migrated modules */
const APP_SHARED_PACKAGES = ['@quotes/content', '@calc/shared'];
export default defineConfig({
plugins: [
tailwindcss(),
sveltekit(),
SvelteKitPWA(
createPWAConfig({
name: 'Mana',
shortName: 'Mana',
description: 'Mana App Ecosystem',
themeColor: '#6366f1',
registerType: 'prompt',
preset: 'full',
// SW disabled in dev. Reasons:
// 1. Workbox precache doesn't run under `vite dev`, so the
// `navigateFallback: '/offline'` rule fires for every
// navigation → users land on the offline page even while
// online. (Observed 2026-04-14.)
// 2. The 2026-04-08 dreams mic-button bug: a stuck dev SW
// kept serving old JS chunks through HMR reloads.
// Test install prompt + offline behavior via `pnpm build &&
// pnpm preview` instead — production SW works correctly.
devEnabled: false,
shortcuts: [
{ name: 'Dashboard', short_name: 'Home', url: '/', description: 'Zum Dashboard' },
{
name: 'Neue Aufgabe',
short_name: 'Aufgabe',
url: '/todo',
description: 'Neue Aufgabe erstellen',
},
{
name: 'Kalender',
short_name: 'Kalender',
url: '/calendar',
description: 'Kalender öffnen',
},
{ name: 'Chat', short_name: 'Chat', url: '/chat', description: 'Chat öffnen' },
],
// Web Share Target — installed PWA shows up in the OS share
// sheet as "Mana" and lands on /articles/add with the URL
// pre-filled (AddUrlForm reads ?url + ?text + ?title). The
// `text` param is listed alongside `url` because some
// senders (Chrome Android, WhatsApp) stuff the URL into the
// text field.
shareTarget: {
action: '/articles/add',
method: 'GET',
params: { title: 'title', text: 'text', url: 'url' },
},
})
),
],
server: {
port: 5173,
strictPort: true,
fs: {
// Allow serving files from the monorepo root so that workspace
// packages (e.g. @mana/local-llm's Web Worker entry) can be
// resolved by Vite's dev server. Without this, worker.ts in
// packages/local-llm triggers "request url is outside of Vite
// serving allow list".
allow: ['../../../..'],
},
},
preview: {
port: 4173,
strictPort: true,
},
worker: {
// Vite defaults to IIFE worker format, which does not support code
// splitting. @mana/local-llm's worker imports transformers.js, which
// is internally code-split into many chunks. Without 'es' format the
// build fails with "Invalid value 'iife' for option 'worker.format'
// - UMD and IIFE output formats are not supported for code-splitting
// builds." All modern browsers (which we already require for WebGPU)
// support module workers.
format: 'es',
},
ssr: {
// `rrule@2` ships dual CJS/ESM but its package.json has no `exports`
// field, so the SvelteKit Node adapter resolves it to the CJS bundle
// at runtime — and `import { RRule } from 'rrule'` then throws
// `Named export 'RRule' not found` when /calendar SSRs. Bundling rrule
// into the server build forces Vite's interop layer to handle the
// CJS↔ESM mismatch correctly.
noExternal: [...MANA_SHARED_PACKAGES, ...APP_SHARED_PACKAGES, 'rrule'],
// transformers.js is browser-only (uses WebGPU + the Cache API). The
// dynamic import in @mana/local-llm only ever fires client-side, but
// SvelteKit's adapter-node Rollup pass would otherwise warn that the
// import is unresolved at SSR time. Marking it external both silences
// the warning and ensures the SSR bundle never tries to load it.
external: ['@huggingface/transformers'],
},
optimizeDeps: {
exclude: [...MANA_SHARED_PACKAGES, ...APP_SHARED_PACKAGES],
},
define: {
...getBuildDefines(),
},
// Vitest unit-test config — keeps Playwright e2e specs out of the
// vitest run. Without this exclude, vitest imports them and they
// crash on `test.afterAll()` because they expect a Playwright runner.
test: {
exclude: ['**/node_modules/**', '**/dist/**', '**/build/**', 'e2e/**', 'tests/e2e/**'],
coverage: {
provider: 'v8',
reporter: ['text', 'lcov', 'json-summary'],
reportsDirectory: './coverage',
include: ['src/**/*.{ts,svelte}'],
exclude: [
'src/**/*.{test,spec}.{ts,js}',
'src/**/*.d.ts',
'src/**/__tests__/**',
'src/**/__mocks__/**',
'src/routes/**/+{page,layout,server,error}.{ts,svelte}',
'src/app.d.ts',
'src/hooks.*.ts',
],
},
},
});