@tatchi-xyz/sdk 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,6 +29,14 @@ function parseWalletOriginsEnv(value) {
29
29
  const origins = normalizeWalletOrigins(parts);
30
30
  return origins.length ? origins : void 0;
31
31
  }
32
+ function resolveCoopMode(explicit) {
33
+ if (explicit === "off" || explicit === "same-origin" || explicit === "same-origin-allow-popups") return explicit;
34
+ const raw = String(globalThis?.process?.env?.VITE_COOP_MODE || "").trim().toLowerCase();
35
+ if (raw === "off" || raw === "0" || raw === "false" || raw === "none") return "off";
36
+ if (raw === "same-origin-allow-popups" || raw === "allow-popups") return "same-origin-allow-popups";
37
+ if (raw === "same-origin" || raw === "strict" || raw === "1") return "same-origin";
38
+ return "off";
39
+ }
32
40
  /**
33
41
  * Return the first candidate path that exists and is a file.
34
42
  * Helper for robust /sdk/* asset resolution on dev servers (app and wallet).
@@ -224,6 +232,7 @@ function tatchiHeaders(opts = {}) {
224
232
  const sdkBasePath = require_validation.toBasePath(opts.sdkBasePath || process.env.VITE_SDK_BASE_PATH, "/sdk");
225
233
  const devCSPMode = opts.devCSP ?? process.env.VITE_WALLET_DEV_CSP;
226
234
  const coepMode = require_plugin_utils.resolveCoepMode(opts.coepMode);
235
+ const coopMode = resolveCoopMode(opts.coopMode);
227
236
  const permissionsPolicy = require_headers.buildPermissionsPolicy(walletOrigins);
228
237
  const rorContractId = (process.env.VITE_WEBAUTHN_CONTRACT_ID || "").toString().trim();
229
238
  const rorMethod = (process.env.VITE_ROR_METHOD || "get_allowed_origins").toString().trim();
@@ -244,7 +253,8 @@ function tatchiHeaders(opts = {}) {
244
253
  server.middlewares.use((req, res, next) => {
245
254
  const url = (req.url || "").split("?")[0] || "";
246
255
  const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`;
247
- res.setHeader("Cross-Origin-Opener-Policy", isWalletRoute ? "unsafe-none" : "same-origin");
256
+ if (isWalletRoute) res.setHeader("Cross-Origin-Opener-Policy", "unsafe-none");
257
+ else if (coopMode !== "off") res.setHeader("Cross-Origin-Opener-Policy", coopMode);
248
258
  if (coepMode !== "off") {
249
259
  res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
250
260
  res.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
@@ -319,6 +329,7 @@ function tatchiDevServer(options = {}) {
319
329
  const enableDebugRoutes = options.enableDebugRoutes === true;
320
330
  const sdkDistRoot = require_plugin_utils.resolveSdkDistRoot(options.sdkDistRoot);
321
331
  const coepMode = require_plugin_utils.resolveCoepMode(options.coepMode);
332
+ const coopMode = options.coopMode;
322
333
  const sdkPlugin = tatchiServeSdk({
323
334
  sdkBasePath,
324
335
  sdkDistRoot,
@@ -336,7 +347,8 @@ function tatchiDevServer(options = {}) {
336
347
  walletServicePath,
337
348
  sdkBasePath,
338
349
  devCSP: "strict",
339
- coepMode
350
+ coepMode,
351
+ coopMode
340
352
  }) : void 0;
341
353
  return {
342
354
  name: "tatchi:dev",
@@ -362,6 +374,7 @@ function tatchiBuildHeaders(opts = {}) {
362
374
  const walletServicePath = require_validation.toBasePath(process.env.VITE_WALLET_SERVICE_PATH, "/wallet-service");
363
375
  const sdkBasePath = require_validation.toBasePath(process.env.VITE_SDK_BASE_PATH, "/sdk");
364
376
  const coepMode = require_plugin_utils.resolveCoepMode(opts.coepMode);
377
+ const coopMode = resolveCoopMode(opts.coopMode);
365
378
  const permissionsPolicy = require_headers.buildPermissionsPolicy(walletOrigins);
366
379
  const walletCsp = require_headers.buildWalletCsp({ mode: "strict" });
367
380
  let outDir = "dist";
@@ -379,7 +392,7 @@ function tatchiBuildHeaders(opts = {}) {
379
392
  else {
380
393
  const contentLines = [
381
394
  "/*",
382
- " Cross-Origin-Opener-Policy: same-origin",
395
+ ...coopMode === "off" ? [] : [` Cross-Origin-Opener-Policy: ${coopMode}`],
383
396
  ...coepMode === "off" ? [] : [" Cross-Origin-Embedder-Policy: require-corp", " Cross-Origin-Resource-Policy: cross-origin"],
384
397
  ` Permissions-Policy: ${permissionsPolicy}`,
385
398
  "",
@@ -491,7 +504,7 @@ function tatchiAppServer(options = {}) {
491
504
  * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify
492
505
  * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to
493
506
  * wallet HTML routes only.
494
- * - Emits: `COOP: same-origin`, `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
507
+ * - Emits: `COOP` (defaults to `same-origin-allow-popups`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
495
508
  * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).
496
509
  *
497
510
  * Notes
@@ -505,7 +518,8 @@ function tatchiApp(options = {}) {
505
518
  const app = tatchiAppServer(devOpts);
506
519
  const hdr = emitHeaders ? tatchiBuildHeaders({
507
520
  walletOrigins,
508
- coepMode: devOpts.coepMode
521
+ coepMode: devOpts.coepMode,
522
+ coopMode: devOpts.coopMode
509
523
  }) : void 0;
510
524
  return [app, hdr].filter(Boolean);
511
525
  }
@@ -517,7 +531,7 @@ function tatchiApp(options = {}) {
517
531
  * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify
518
532
  * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to
519
533
  * wallet HTML routes only.
520
- * - Emits: `COOP: same-origin` (wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
534
+ * - Emits: `COOP` on app routes (defaults to `same-origin-allow-popups`; wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
521
535
  * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).
522
536
  *
523
537
  * Notes
@@ -530,7 +544,8 @@ function tatchiWallet(options = {}) {
530
544
  const wallet = tatchiWalletServer(devOpts);
531
545
  const hdr = emitHeaders ? tatchiBuildHeaders({
532
546
  walletOrigins,
533
- coepMode: devOpts.coepMode
547
+ coepMode: devOpts.coepMode,
548
+ coopMode: devOpts.coopMode
534
549
  }) : void 0;
535
550
  return [wallet, hdr].filter(Boolean);
536
551
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","names":["out: string[]","toOriginOrUndefined","fs","path","toBasePath","resolveSdkDistRoot","resolveCoepMode","buildOfflineExportHtml","buildWalletServiceHtml","buildPermissionsPolicy","buildWalletCsp","fetchRorOriginsFromNear","echoCorsFromRequest","mode: Required<Web3AuthnDevOptions>['mode']","contentLines: string[]","buildExportViewerHtml"],"sources":["../../../src/plugins/vite.ts"],"sourcesContent":["// Minimal Vite dev plugin(s) to support Passkey Manager modes.\n// See docs/passkey-manager-modes.md (Vite Plugin section).\n//\n// What these plugins do:\n// - Serve SDK assets under a base path, expose a wallet service route,\n// - Add dev headers (COOP + Permissions-Policy, optional COEP/CORP), and enforce WASM MIME.\n// - IMPORTANT: Strict CSP is scoped only to wallet HTML routes (/wallet-service, /export-viewer),\n// not to the host app pages. App routes remain free to use inline styles/scripts.\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { buildPermissionsPolicy, buildWalletCsp } from './headers'\nimport { toOriginOrUndefined } from '../utils/validation'\nimport {\n addPreconnectLink,\n buildWalletServiceHtml,\n buildExportViewerHtml,\n applyCoepCorpIfNeeded,\n echoCorsFromRequest,\n fetchRorOriginsFromNear,\n toBasePath,\n resolveCoepMode,\n resolveSdkDistRoot,\n} from './plugin-utils'\nimport { addOfflineExportDevRoutes, buildOfflineExportHtml, emitOfflineExportAssets } from './offline'\nimport { setContentType } from './plugin-utils'\n\nexport type VitePlugin = {\n name: string\n apply?: 'serve' | 'build'\n enforce?: 'pre' | 'post'\n configureServer?: (server: any) => void | Promise<void>\n}\nexport type ViteLikePlugin = VitePlugin\n\nexport type Web3AuthnDevOptions = {\n mode?: 'self-contained' | 'front-only' | 'wallet-only'\n sdkDistRoot?: string\n sdkBasePath?: string\n walletServicePath?: string\n walletOrigins?: string[]\n setDevHeaders?: boolean\n enableDebugRoutes?: boolean\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP on app pages.\n * - 'strict': emit `Cross-Origin-Embedder-Policy: require-corp`\n * and `Cross-Origin-Resource-Policy: cross-origin` on app pages.\n *\n * Tip: set `VITE_COEP_MODE=strict` in tests/CI to enable isolation automatically.\n */\n coepMode?: 'strict' | 'off'\n}\n\nexport type ServeSdkOptions = {\n sdkDistRoot?: string\n sdkBasePath?: string\n enableDebugRoutes?: boolean\n coepMode?: 'strict' | 'off'\n}\n\nexport type WalletServiceOptions = {\n walletServicePath?: string\n sdkBasePath?: string\n coepMode?: 'strict' | 'off'\n}\n\nexport type DevHeadersOptions = {\n walletOrigins?: string[]\n walletServicePath?: string\n sdkBasePath?: string\n /**\n * Optional dev-time CSP for the wallet service route.\n * - 'strict': no inline scripts/styles (mirrors production defaults)\n * - 'compatible': allows inline scripts/styles (useful for debugging)\n */\n devCSP?: 'strict' | 'compatible'\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP headers on app pages.\n * - 'strict': emit COEP/CORP headers on app pages.\n */\n coepMode?: 'strict' | 'off'\n}\n\nfunction normalizeWalletOrigins(walletOrigins?: string[]): string[] {\n if (!Array.isArray(walletOrigins) || walletOrigins.length === 0) return []\n const out: string[] = []\n const seen = new Set<string>()\n for (const origin of walletOrigins) {\n const normalized = toOriginOrUndefined(origin)\n if (!normalized || seen.has(normalized)) continue\n seen.add(normalized)\n out.push(normalized)\n }\n return out\n}\n\nfunction parseWalletOriginsEnv(value: unknown): string[] | undefined {\n if (typeof value !== 'string') return undefined\n const raw = value.trim()\n if (!raw) return undefined\n const parts = raw.split(/[,\\s]+/).map((v) => v.trim()).filter(Boolean)\n const origins = normalizeWalletOrigins(parts)\n return origins.length ? origins : undefined\n}\n\n/**\n * Return the first candidate path that exists and is a file.\n * Helper for robust /sdk/* asset resolution on dev servers (app and wallet).\n */\nfunction tryFile(...candidates: string[]): string | undefined {\n for (const file of candidates) {\n try {\n const stat = fs.statSync(file)\n if (stat.isFile()) return file\n } catch {}\n }\n return undefined\n}\n\n// Dev convenience: allow Vite's cacheDir so `/@fs/.../deps/*.js` dynamic imports can load under `server.fs.strict`.\nfunction ensureViteCacheDirAllowed(server: any): void {\n const config = server?.config\n const cacheDir = config?.cacheDir\n const fsConfig = config?.server?.fs\n const allow = fsConfig?.allow\n if (!cacheDir || fsConfig?.strict === false || !Array.isArray(allow)) return\n\n const absCacheDir = path.resolve(String(cacheDir))\n if (!allow.some((p: any) => path.resolve(String(p)) === absCacheDir)) {\n allow.push(absCacheDir)\n }\n}\n\n// Shared assets emitted/served for the wallet service bootstrap.\nconst WALLET_SHIM_SOURCE = \"window.global ||= window; window.process ||= { env: {} };\\n\"\nconst WALLET_SURFACE_CSS = [\n 'html, body { background: transparent !important; margin:0; padding:0; }',\n 'html, body { color-scheme: normal; }',\n '',\n // Class-based surface for strict CSP setups toggled by JS\n 'html.w3a-transparent, body.w3a-transparent { background: transparent !important; margin:0; padding:0; color-scheme: normal; }',\n '',\n // Minimal portal styles used by confirm-ui (no animation; child components handle transitions)\n '.w3a-portal { position: relative; z-index: 2147483647; opacity: 0; pointer-events: none; }',\n '.w3a-portal.w3a-portal--visible { opacity: 1; pointer-events: auto; }',\n '',\n // Provide baseline tokens only when the document does not declare a theme.\n // This avoids overriding :root[data-w3a-theme] values supplied by token sheet\n // or integrator-injected themes.\n ':root:not([data-w3a-theme]) {',\n ' --w3a-colors-textPrimary: #f6f7f8;',\n ' --w3a-colors-textSecondary: rgba(255,255,255,0.7);',\n ' --w3a-colors-surface: rgba(255,255,255,0.08);',\n ' --w3a-colors-surface2: rgba(255,255,255,0.06);',\n ' --w3a-colors-surface3: rgba(255,255,255,0.04);',\n ' --w3a-colors-borderPrimary: rgba(255,255,255,0.14);',\n ' --w3a-colors-borderSecondary: rgba(255,255,255,0.1);',\n ' --w3a-colors-colorBackground: #0b0c10;',\n ' /* Default viewport custom properties for width/height calculations */',\n ' --w3a-vw: 100vw;',\n ' --w3a-vh: 100vh;',\n '}',\n '',\n].join('\\n')\n\n/**\n * Tatchi SDK plugin: serve SDK assets under a stable base (default: /sdk) with optional COEP/CORP (strict mode) and permissive CORS.\n * Where it runs: both the app server and the wallet-iframe server.\n * - App server: lets host pages and Lit components load SDK CSS/JS locally.\n * - Wallet server: used by /wallet-service to load wallet-iframe-host.js and related CSS/JS.\n */\nexport function tatchiServeSdk(opts: ServeSdkOptions = {}): VitePlugin {\n const configuredBase = toBasePath(opts.sdkBasePath, '/sdk')\n const sdkDistRoot = resolveSdkDistRoot(opts.sdkDistRoot)\n const enableDebugRoutes = opts.enableDebugRoutes === true\n const coepMode = resolveCoepMode(opts.coepMode)\n const offlineHtml = buildOfflineExportHtml(configuredBase)\n\n // In dev we want both '/sdk' and a custom base to work.\n const bases = Array.from(new Set([configuredBase, toBasePath('/sdk')]))\n .sort((a, b) => b.length - a.length)\n // Prefer longest base match first (e.g., '/sdk/esm/react' before '/sdk')\n\n return {\n name: 'tatchi:serve-sdk',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Mount Offline Export dev routes once here (includes app module + chunks)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath: configuredBase,\n offlineHtml,\n includeAppModule: true,\n coepMode,\n })\n // Serve a tiny shim as a virtual asset to enable strict CSP (no inline scripts)\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0]\n if (url === configuredBase + '/wallet-shims.js') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/javascript; charset=utf-8')\n // Align with SDK asset headers so COEP/CORP environments can import\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SHIM_SOURCE)\n return\n }\n if (url === configuredBase + '/wallet-service.css') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/css; charset=utf-8')\n // Important: provide CORP for cross‑origin CSS so COEP documents can load it\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SURFACE_CSS)\n return\n }\n next()\n })\n\n // Optional debug route to confirm resolution\n if (enableDebugRoutes) {\n server.middlewares.use('/__sdk-root', (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/plain; charset=utf-8')\n res.end(sdkDistRoot)\n })\n }\n\n // Serve files under any recognized base from sdkDistRoot with fallbacks\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n\n const matchBase = bases.find((b) => url.startsWith(b + '/'))\n if (!matchBase) return next()\n\n const rel = url.slice((matchBase + '/').length)\n // Try dist/esm/sdk first (canonical), then common fallbacks\n const candidate = tryFile(\n path.join(sdkDistRoot, 'esm', 'sdk', rel),\n path.join(sdkDistRoot, rel),\n path.join(sdkDistRoot, 'esm', rel)\n )\n\n if (!candidate) {\n res.statusCode = 404\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.end(JSON.stringify({ error: 'SDK asset not found', path: rel }))\n return\n }\n\n setContentType(res, candidate)\n // SDK assets need COEP headers to work in wallet iframe with COEP enabled\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling here)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n const stream = fs.createReadStream(candidate)\n stream.on('error', () => next())\n stream.pipe(res)\n })\n },\n }\n}\n\n/**\n * Dev plugin: expose the wallet service HTML route (default: /wallet-service) that links only external CSS/JS.\n * Where it runs: wallet-iframe dev server (wallet origins). Used by tatchiWalletServer.\n */\nexport function tatchiWalletService(opts: WalletServiceOptions = {}): VitePlugin {\n const walletServicePath = toBasePath(opts.walletServicePath, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n\n const html = buildWalletServiceHtml(sdkBasePath)\n const offlineHtml = buildOfflineExportHtml(sdkBasePath)\n const sdkDistRoot = resolveSdkDistRoot()\n\n return {\n name: 'tatchi:wallet-service',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n if (isWalletRoute) {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/html; charset=utf-8')\n // Important: allow embedding this wallet HTML into COEP=require-corp apps even\n // when the wallet itself is not running with COEP enabled.\n // Without CORP, the iframe can be blocked and remain on an opaque 'null' origin,\n // causing CONNECT/READY handshake timeouts in the parent.\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n applyCoepCorpIfNeeded(res, coepMode)\n res.end(html)\n return\n }\n next()\n })\n\n // Mount Offline Export routes here as well (no app module duplication)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath,\n offlineHtml,\n includeAppModule: false,\n coepMode,\n })\n },\n }\n}\n\n/**\n * Dev plugin: force the correct `.wasm` MIME type (application/wasm) for any served wasm file.\n * Where it runs: both app and wallet-iframe dev servers.\n */\nexport function tatchiWasmMime(): VitePlugin {\n return {\n name: 'tatchi:wasm-mime',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n if (url.endsWith('.wasm')) {\n res.setHeader('Content-Type', 'application/wasm')\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin: add Permissions-Policy (delegating WebAuthn + clipboard), COOP, optional COEP/CORP, and optional dev CSP.\n * Where it runs: both app and wallet-iframe dev servers.\n * Notes:\n * - Uses Structured Header format for Permissions-Policy (double-quoted origins).\n * - Wallet dev CSP can be toggled strict/compatible via opts.devCSP.\n */\nexport function tatchiHeaders(opts: DevHeadersOptions = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(opts.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const devCSPMode = (opts.devCSP ?? (process.env.VITE_WALLET_DEV_CSP as 'strict' | 'compatible' | undefined))\n const coepMode = resolveCoepMode(opts.coepMode)\n\n // Build headers via shared helpers to avoid drift.\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n\n // Dev convenience: dynamic ROR from NEAR RPC (no relay dependency)\n // The dev server will fetch the allowlist from chain on demand when a contract id is provided.\n const rorContractId = (process.env.VITE_WEBAUTHN_CONTRACT_ID || '').toString().trim()\n const rorMethod = (process.env.VITE_ROR_METHOD || 'get_allowed_origins').toString().trim()\n const nearRpcUrl = (process.env.VITE_NEAR_RPC_URL || 'https://test.rpc.fastnear.com').toString().trim()\n // Caching is handled inside fetchRorOriginsFromNear via TTL\n\n return {\n name: 'tatchi:dev-headers',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n console.log('[tatchi] headers enabled', {\n walletServicePath,\n sdkBasePath,\n coepMode,\n rorContractId: rorContractId || '(none)',\n nearRpcUrl\n })\n\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0] || ''\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n res.setHeader('Cross-Origin-Opener-Policy', isWalletRoute ? 'unsafe-none' : 'same-origin')\n if (coepMode !== 'off') {\n res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n }\n res.setHeader('Permissions-Policy', permissionsPolicy)\n // Optional dev-time CSP for the wallet service page only (app pages are unaffected)\n if (isWalletRoute && devCSPMode) {\n const mode = devCSPMode === 'strict' ? 'strict' : 'compatible'\n const walletCsp = buildWalletCsp({ mode })\n res.setHeader('Content-Security-Policy', walletCsp)\n }\n // Resource hints: help parent pages preconnect to the wallet origins early in dev\n addPreconnectLink(res, walletOrigins)\n\n // Serve /.well-known/webauthn for ROR using chain state in dev\n const isWellKnown = url === '/.well-known/webauthn' || url === '/.well-known/webauthn/'\n if (isWellKnown) {\n // Direct fetch from NEAR RPC (no relay). Caching handled inside helper.\n // Requires contract id; RPC URL falls back to a reliable public endpoint.\n if (rorContractId) {\n ;(async () => {\n try {\n const origins = await fetchRorOriginsFromNear({\n rpcUrl: nearRpcUrl,\n contractId: rorContractId,\n method: rorMethod,\n })\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins }))\n } catch (e) {\n console.warn('[tatchi] ROR dynamic fetch failed:', e)\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n }\n })()\n return\n }\n // No configuration; respond with empty allowlist to avoid hard 404 in dev\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n return\n }\n\n if (url.startsWith(`${sdkBasePath}/`)) {\n // Dev-only CORS for SDK assets served by Vite\n applyCoepCorpIfNeeded(res, coepMode)\n // Honor existing echo from SDK server; otherwise echo\n const ended = echoCorsFromRequest(res, req, { honorExistingAcaOrigin: true, handlePreflight: true })\n if (ended) return\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin (composed): convenience entry that wires SDK server, WASM MIME, optional headers,\n * and (in wallet modes) the wallet service route.\n * Where it runs:\n * - App server: mode 'front-only' (or 'self-contained' when serving wallet pages on the same origin).\n * - Wallet-iframe server: modes 'wallet-only' or 'self-contained'.\n */\n/**\n * Compose dev plugins for serving SDK assets, wallet service HTML and dev headers.\n * External-facing entry for configuring either the app or wallet-iframe dev server.\n */\nfunction tatchiDevServer(options: Web3AuthnDevOptions = {}): VitePlugin {\n const mode: Required<Web3AuthnDevOptions>['mode'] = options.mode || 'self-contained'\n const sdkBasePath = toBasePath(options.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const walletServicePath = toBasePath(options.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const walletOrigins = normalizeWalletOrigins(\n options.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const setDevHeaders = options.setDevHeaders !== false // default true\n const enableDebugRoutes = options.enableDebugRoutes === true\n const sdkDistRoot = resolveSdkDistRoot(options.sdkDistRoot)\n const coepMode = resolveCoepMode(options.coepMode)\n\n // Build the sub-plugins to keep logic small and testable\n const sdkPlugin = tatchiServeSdk({ sdkBasePath, sdkDistRoot, enableDebugRoutes, coepMode })\n const walletPlugin = tatchiWalletService({ walletServicePath, sdkBasePath, coepMode })\n const wasmMimePlugin = tatchiWasmMime()\n // Flip wallet CSP to strict by default in dev. Consumers can override via\n // VITE_WALLET_DEV_CSP or by composing tatchiHeaders directly.\n const headersPlugin = setDevHeaders\n ? tatchiHeaders({ walletOrigins, walletServicePath, sdkBasePath, devCSP: 'strict', coepMode })\n : undefined\n\n return {\n name: 'tatchi:dev',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Always add WASM MIME + SDK server\n sdkPlugin.configureServer?.(server)\n wasmMimePlugin.configureServer?.(server)\n if (headersPlugin) headersPlugin.configureServer?.(server)\n\n // Mode-specific wallet service route\n if (mode === 'self-contained' || mode === 'wallet-only') {\n walletPlugin.configureServer?.(server)\n }\n },\n }\n}\n\n// === Build-time helper: emit Cloudflare Pages/Netlify _headers ===\n// This plugin writes a _headers file into Vite's outDir with COOP and optional COEP and a\n// Permissions-Policy delegating WebAuthn to the configured wallet origins.\n// It is a no-op if a _headers file already exists (to avoid overriding app settings).\n/**\n * Build-time plugin: writes a Cloudflare Pages/Netlify-compatible `_headers` file into Vite's `outDir`.\n * Adds COOP + Permissions-Policy and optional COEP/CORP (configurable via coepMode) delegating WebAuthn to the configured wallet origins.\n * Where it runs: build for either the app or a static wallet host (not used in dev).\n * Notes: no-ops if `_headers` already exists in `outDir` (to avoid overriding platform config).\n */\nexport function tatchiBuildHeaders(opts: { walletOrigins?: string[], cors?: { accessControlAllowOrigin?: string }, coepMode?: 'strict' | 'off' } = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(process.env.VITE_SDK_BASE_PATH, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n\n // Build headers via shared helpers to avoid drift between frameworks\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n const walletCsp = buildWalletCsp({ mode: 'strict' })\n\n let outDir = 'dist'\n\n // We intentionally return a broader shape than VitePlugin; cast at the end\n const plugin = {\n name: 'tatchi:build-headers',\n apply: 'build' as const,\n enforce: 'post' as const,\n // Capture the resolved outDir\n configResolved(config: any) {\n outDir = (config?.build?.outDir as string) || outDir\n },\n generateBundle() {\n try {\n const hdrPath = path.join(outDir, '_headers')\n if (fs.existsSync(hdrPath)) {\n // Do not override existing headers; leave a note in build logs\n console.warn('[tatchi] _headers already exists in outDir; skipping auto-emission')\n } else {\n // Strict CSP is emitted only for wallet HTML routes; not for app pages.\n const contentLines: string[] = [\n '/*',\n ' Cross-Origin-Opener-Policy: same-origin',\n ...(coepMode === 'off'\n ? []\n : [\n ' Cross-Origin-Embedder-Policy: require-corp',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ]),\n ` Permissions-Policy: ${permissionsPolicy}`,\n '',\n `${walletServicePath}`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n // Always allow COEP=require-corp apps to embed wallet HTML, even when\n // the wallet host itself is not using COEP.\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n `${walletServicePath}/`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n '/export-viewer',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n '/export-viewer/',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n // Offline export cache policy (no-cache for HTML/SW; immutable for other assets)\n '/offline-export',\n ' Cache-Control: no-cache',\n '/offline-export/',\n ' Cache-Control: no-cache',\n '/offline-export/index.html',\n ' Cache-Control: no-cache',\n '/offline-export/sw.js',\n ' Cache-Control: no-cache',\n '/offline-export/precache.manifest.json',\n ' Cache-Control: no-cache',\n '/offline-export/manifest.webmanifest',\n ' Cache-Control: no-cache',\n '/offline-export/offline-export-app.js',\n ' Cache-Control: no-cache',\n '/offline-export/*',\n ' Cache-Control: public, max-age=31536000, immutable',\n ]\n // Optional: emit CORS headers when explicitly configured via plugin option.\n // Prefer a single source of truth (platform or plugin), not both.\n const configuredAcaOrigin = (opts.cors && typeof opts.cors.accessControlAllowOrigin === 'string'\n ? opts.cors.accessControlAllowOrigin.trim()\n : undefined) as string | undefined;\n if (configuredAcaOrigin) {\n contentLines.push(\n `${sdkBasePath}/*`,\n ` Access-Control-Allow-Origin: ${configuredAcaOrigin}`,\n )\n }\n const content = contentLines.join('\\n') + '\\n'\n fs.mkdirSync(outDir, { recursive: true })\n fs.writeFileSync(hdrPath, content, 'utf-8')\n console.log('[tatchi] emitted _headers with COOP' + (coepMode === 'off' ? '' : '/COEP/CORP') + ' + Permissions-Policy' + (configuredAcaOrigin ? ' + CORS' : ''))\n }\n\n const sdkDir = path.join(outDir, sdkBasePath.replace(/^\\//, ''))\n try { fs.mkdirSync(sdkDir, { recursive: true }) } catch {}\n const shimPath = path.join(sdkDir, 'wallet-shims.js')\n if (!fs.existsSync(shimPath)) {\n fs.writeFileSync(shimPath, WALLET_SHIM_SOURCE, 'utf-8')\n }\n const cssPath = path.join(sdkDir, 'wallet-service.css')\n if (!fs.existsSync(cssPath)) {\n fs.writeFileSync(cssPath, WALLET_SURFACE_CSS, 'utf-8')\n }\n\n // Emit minimal wallet-service/index.html if the app hasn't provided one\n const walletRel = walletServicePath.replace(/^\\//, '')\n const wsDir = path.join(outDir, walletRel)\n const wsHtml = path.join(wsDir, 'index.html')\n if (!fs.existsSync(wsHtml)) {\n fs.mkdirSync(wsDir, { recursive: true })\n fs.writeFileSync(wsHtml, buildWalletServiceHtml(sdkBasePath), 'utf-8')\n console.log(`[tatchi] emitted ${path.posix.join('/', walletRel, 'index.html')} (minimal wallet service)`)\n }\n\n // Emit minimal export viewer HTML for production\n const evDir = path.join(outDir, 'export-viewer')\n const evHtml = path.join(evDir, 'index.html')\n if (!fs.existsSync(evHtml)) {\n fs.mkdirSync(evDir, { recursive: true })\n fs.writeFileSync(evHtml, buildExportViewerHtml(sdkBasePath), 'utf-8')\n console.log('[tatchi] emitted /export-viewer/index.html (minimal export viewer)')\n }\n\n // Emit offline-export assets (SW, workers, app, HTML, manifest, precache) via helper\n try {\n const sdkDistRoot = resolveSdkDistRoot()\n emitOfflineExportAssets({ outDir, sdkBasePath, sdkDistRoot })\n } catch (e) {\n console.warn('[tatchi] failed to emit offline-export assets:', e)\n }\n } catch (e) {\n console.warn('[tatchi] failed to emit _headers:', e)\n }\n },\n }\n\n return plugin as unknown as VitePlugin\n}\n\n// Small test helpers to keep unit tests decoupled from Vite server implementation\nexport function computeDevPermissionsPolicy(walletOrigins?: string[]): string {\n return buildPermissionsPolicy(walletOrigins)\n}\n\nexport function computeDevWalletCsp(mode: 'strict' | 'compatible' = 'strict'): string {\n return buildWalletCsp({ mode })\n}\n\nexport function tatchiWalletServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'wallet-only' })\n}\n\nexport function tatchiAppServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'front-only' })\n}\n\n/**\n * Convenience wrapper: app origin helper that combines dev-time headers with optional\n * build-time headers emission for static hosts.\n *\n * Dev-time (serve): applies COOP + Permissions-Policy, plus optional COEP/CORP, via tatchiAppServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP: same-origin`, `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid surprising overrides when apps\n * already manage headers via custom servers or platform rules.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiApp(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const app = tatchiAppServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode }) : undefined\n return [app, hdr].filter(Boolean) as any[]\n}\n\n/**\n * Convenience wrapper: wallet origins helper that combines dev-time wallet server\n * with optional build-time headers emission for static hosts.\n *\n * Dev-time (serve): serves `/wallet-service` and `/sdk/*` plus headers via tatchiWalletServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP: same-origin` (wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid overriding platform/server configs.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiWallet(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const wallet = tatchiWalletServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode }) : undefined\n return [wallet, hdr].filter(Boolean) as any[]\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"vite.js","names":["out: string[]","toOriginOrUndefined","fs","path","toBasePath","resolveSdkDistRoot","resolveCoepMode","buildOfflineExportHtml","buildWalletServiceHtml","buildPermissionsPolicy","buildWalletCsp","fetchRorOriginsFromNear","echoCorsFromRequest","mode: Required<Web3AuthnDevOptions>['mode']","contentLines: string[]","buildExportViewerHtml"],"sources":["../../../src/plugins/vite.ts"],"sourcesContent":["// Minimal Vite dev plugin(s) to support Passkey Manager modes.\n// See docs/passkey-manager-modes.md (Vite Plugin section).\n//\n// What these plugins do:\n// - Serve SDK assets under a base path, expose a wallet service route,\n// - Add dev headers (COOP + Permissions-Policy, optional COEP/CORP), and enforce WASM MIME.\n// - IMPORTANT: Strict CSP is scoped only to wallet HTML routes (/wallet-service, /export-viewer),\n// not to the host app pages. App routes remain free to use inline styles/scripts.\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { buildPermissionsPolicy, buildWalletCsp } from './headers'\nimport { toOriginOrUndefined } from '../utils/validation'\nimport {\n addPreconnectLink,\n buildWalletServiceHtml,\n buildExportViewerHtml,\n applyCoepCorpIfNeeded,\n echoCorsFromRequest,\n fetchRorOriginsFromNear,\n toBasePath,\n resolveCoepMode,\n resolveSdkDistRoot,\n} from './plugin-utils'\nimport { addOfflineExportDevRoutes, buildOfflineExportHtml, emitOfflineExportAssets } from './offline'\nimport { setContentType } from './plugin-utils'\n\nexport type VitePlugin = {\n name: string\n apply?: 'serve' | 'build'\n enforce?: 'pre' | 'post'\n configureServer?: (server: any) => void | Promise<void>\n}\nexport type ViteLikePlugin = VitePlugin\n\nexport type Web3AuthnDevOptions = {\n mode?: 'self-contained' | 'front-only' | 'wallet-only'\n sdkDistRoot?: string\n sdkBasePath?: string\n walletServicePath?: string\n walletOrigins?: string[]\n setDevHeaders?: boolean\n enableDebugRoutes?: boolean\n /** See DevHeadersOptions.coopMode */\n coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups'\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP on app pages.\n * - 'strict': emit `Cross-Origin-Embedder-Policy: require-corp`\n * and `Cross-Origin-Resource-Policy: cross-origin` on app pages.\n *\n * Tip: set `VITE_COEP_MODE=strict` in tests/CI to enable isolation automatically.\n */\n coepMode?: 'strict' | 'off'\n}\n\nexport type ServeSdkOptions = {\n sdkDistRoot?: string\n sdkBasePath?: string\n enableDebugRoutes?: boolean\n coepMode?: 'strict' | 'off'\n}\n\nexport type WalletServiceOptions = {\n walletServicePath?: string\n sdkBasePath?: string\n coepMode?: 'strict' | 'off'\n}\n\nexport type DevHeadersOptions = {\n walletOrigins?: string[]\n walletServicePath?: string\n sdkBasePath?: string\n /**\n * Controls Cross-Origin-Opener-Policy (COOP) behavior.\n *\n * COOP can break popup-based third-party wallet flows by severing `window.opener`\n * when set to `same-origin`. Prefer `same-origin-allow-popups` if you need COOP\n * but still rely on popups.\n *\n * - 'off': do not emit COOP on app routes (wallet HTML routes still use `unsafe-none`)\n * - 'same-origin': strict isolation (may break other wallets)\n * - 'same-origin-allow-popups': more compatible with popup flows\n */\n coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups'\n /**\n * Optional dev-time CSP for the wallet service route.\n * - 'strict': no inline scripts/styles (mirrors production defaults)\n * - 'compatible': allows inline scripts/styles (useful for debugging)\n */\n devCSP?: 'strict' | 'compatible'\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP headers on app pages.\n * - 'strict': emit COEP/CORP headers on app pages.\n */\n coepMode?: 'strict' | 'off'\n}\n\nfunction normalizeWalletOrigins(walletOrigins?: string[]): string[] {\n if (!Array.isArray(walletOrigins) || walletOrigins.length === 0) return []\n const out: string[] = []\n const seen = new Set<string>()\n for (const origin of walletOrigins) {\n const normalized = toOriginOrUndefined(origin)\n if (!normalized || seen.has(normalized)) continue\n seen.add(normalized)\n out.push(normalized)\n }\n return out\n}\n\nfunction parseWalletOriginsEnv(value: unknown): string[] | undefined {\n if (typeof value !== 'string') return undefined\n const raw = value.trim()\n if (!raw) return undefined\n const parts = raw.split(/[,\\s]+/).map((v) => v.trim()).filter(Boolean)\n const origins = normalizeWalletOrigins(parts)\n return origins.length ? origins : undefined\n}\n\nfunction resolveCoopMode(explicit?: 'off' | 'same-origin' | 'same-origin-allow-popups'): 'off' | 'same-origin' | 'same-origin-allow-popups' {\n if (explicit === 'off' || explicit === 'same-origin' || explicit === 'same-origin-allow-popups') return explicit\n const raw = String((globalThis as any)?.process?.env?.VITE_COOP_MODE || '').trim().toLowerCase()\n if (raw === 'off' || raw === '0' || raw === 'false' || raw === 'none') return 'off'\n if (raw === 'same-origin-allow-popups' || raw === 'allow-popups') return 'same-origin-allow-popups'\n if (raw === 'same-origin' || raw === 'strict' || raw === '1') return 'same-origin'\n // Default off to avoid breaking popup-based third-party wallet flows.\n return 'off'\n}\n\n/**\n * Return the first candidate path that exists and is a file.\n * Helper for robust /sdk/* asset resolution on dev servers (app and wallet).\n */\nfunction tryFile(...candidates: string[]): string | undefined {\n for (const file of candidates) {\n try {\n const stat = fs.statSync(file)\n if (stat.isFile()) return file\n } catch {}\n }\n return undefined\n}\n\n// Dev convenience: allow Vite's cacheDir so `/@fs/.../deps/*.js` dynamic imports can load under `server.fs.strict`.\nfunction ensureViteCacheDirAllowed(server: any): void {\n const config = server?.config\n const cacheDir = config?.cacheDir\n const fsConfig = config?.server?.fs\n const allow = fsConfig?.allow\n if (!cacheDir || fsConfig?.strict === false || !Array.isArray(allow)) return\n\n const absCacheDir = path.resolve(String(cacheDir))\n if (!allow.some((p: any) => path.resolve(String(p)) === absCacheDir)) {\n allow.push(absCacheDir)\n }\n}\n\n// Shared assets emitted/served for the wallet service bootstrap.\nconst WALLET_SHIM_SOURCE = \"window.global ||= window; window.process ||= { env: {} };\\n\"\nconst WALLET_SURFACE_CSS = [\n 'html, body { background: transparent !important; margin:0; padding:0; }',\n 'html, body { color-scheme: normal; }',\n '',\n // Class-based surface for strict CSP setups toggled by JS\n 'html.w3a-transparent, body.w3a-transparent { background: transparent !important; margin:0; padding:0; color-scheme: normal; }',\n '',\n // Minimal portal styles used by confirm-ui (no animation; child components handle transitions)\n '.w3a-portal { position: relative; z-index: 2147483647; opacity: 0; pointer-events: none; }',\n '.w3a-portal.w3a-portal--visible { opacity: 1; pointer-events: auto; }',\n '',\n // Provide baseline tokens only when the document does not declare a theme.\n // This avoids overriding :root[data-w3a-theme] values supplied by token sheet\n // or integrator-injected themes.\n ':root:not([data-w3a-theme]) {',\n ' --w3a-colors-textPrimary: #f6f7f8;',\n ' --w3a-colors-textSecondary: rgba(255,255,255,0.7);',\n ' --w3a-colors-surface: rgba(255,255,255,0.08);',\n ' --w3a-colors-surface2: rgba(255,255,255,0.06);',\n ' --w3a-colors-surface3: rgba(255,255,255,0.04);',\n ' --w3a-colors-borderPrimary: rgba(255,255,255,0.14);',\n ' --w3a-colors-borderSecondary: rgba(255,255,255,0.1);',\n ' --w3a-colors-colorBackground: #0b0c10;',\n ' /* Default viewport custom properties for width/height calculations */',\n ' --w3a-vw: 100vw;',\n ' --w3a-vh: 100vh;',\n '}',\n '',\n].join('\\n')\n\n/**\n * Tatchi SDK plugin: serve SDK assets under a stable base (default: /sdk) with optional COEP/CORP (strict mode) and permissive CORS.\n * Where it runs: both the app server and the wallet-iframe server.\n * - App server: lets host pages and Lit components load SDK CSS/JS locally.\n * - Wallet server: used by /wallet-service to load wallet-iframe-host.js and related CSS/JS.\n */\nexport function tatchiServeSdk(opts: ServeSdkOptions = {}): VitePlugin {\n const configuredBase = toBasePath(opts.sdkBasePath, '/sdk')\n const sdkDistRoot = resolveSdkDistRoot(opts.sdkDistRoot)\n const enableDebugRoutes = opts.enableDebugRoutes === true\n const coepMode = resolveCoepMode(opts.coepMode)\n const offlineHtml = buildOfflineExportHtml(configuredBase)\n\n // In dev we want both '/sdk' and a custom base to work.\n const bases = Array.from(new Set([configuredBase, toBasePath('/sdk')]))\n .sort((a, b) => b.length - a.length)\n // Prefer longest base match first (e.g., '/sdk/esm/react' before '/sdk')\n\n return {\n name: 'tatchi:serve-sdk',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Mount Offline Export dev routes once here (includes app module + chunks)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath: configuredBase,\n offlineHtml,\n includeAppModule: true,\n coepMode,\n })\n // Serve a tiny shim as a virtual asset to enable strict CSP (no inline scripts)\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0]\n if (url === configuredBase + '/wallet-shims.js') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/javascript; charset=utf-8')\n // Align with SDK asset headers so COEP/CORP environments can import\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SHIM_SOURCE)\n return\n }\n if (url === configuredBase + '/wallet-service.css') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/css; charset=utf-8')\n // Important: provide CORP for cross‑origin CSS so COEP documents can load it\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SURFACE_CSS)\n return\n }\n next()\n })\n\n // Optional debug route to confirm resolution\n if (enableDebugRoutes) {\n server.middlewares.use('/__sdk-root', (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/plain; charset=utf-8')\n res.end(sdkDistRoot)\n })\n }\n\n // Serve files under any recognized base from sdkDistRoot with fallbacks\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n\n const matchBase = bases.find((b) => url.startsWith(b + '/'))\n if (!matchBase) return next()\n\n const rel = url.slice((matchBase + '/').length)\n // Try dist/esm/sdk first (canonical), then common fallbacks\n const candidate = tryFile(\n path.join(sdkDistRoot, 'esm', 'sdk', rel),\n path.join(sdkDistRoot, rel),\n path.join(sdkDistRoot, 'esm', rel)\n )\n\n if (!candidate) {\n res.statusCode = 404\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.end(JSON.stringify({ error: 'SDK asset not found', path: rel }))\n return\n }\n\n setContentType(res, candidate)\n // SDK assets need COEP headers to work in wallet iframe with COEP enabled\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling here)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n const stream = fs.createReadStream(candidate)\n stream.on('error', () => next())\n stream.pipe(res)\n })\n },\n }\n}\n\n/**\n * Dev plugin: expose the wallet service HTML route (default: /wallet-service) that links only external CSS/JS.\n * Where it runs: wallet-iframe dev server (wallet origins). Used by tatchiWalletServer.\n */\nexport function tatchiWalletService(opts: WalletServiceOptions = {}): VitePlugin {\n const walletServicePath = toBasePath(opts.walletServicePath, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n\n const html = buildWalletServiceHtml(sdkBasePath)\n const offlineHtml = buildOfflineExportHtml(sdkBasePath)\n const sdkDistRoot = resolveSdkDistRoot()\n\n return {\n name: 'tatchi:wallet-service',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n if (isWalletRoute) {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/html; charset=utf-8')\n // Important: allow embedding this wallet HTML into COEP=require-corp apps even\n // when the wallet itself is not running with COEP enabled.\n // Without CORP, the iframe can be blocked and remain on an opaque 'null' origin,\n // causing CONNECT/READY handshake timeouts in the parent.\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n applyCoepCorpIfNeeded(res, coepMode)\n res.end(html)\n return\n }\n next()\n })\n\n // Mount Offline Export routes here as well (no app module duplication)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath,\n offlineHtml,\n includeAppModule: false,\n coepMode,\n })\n },\n }\n}\n\n/**\n * Dev plugin: force the correct `.wasm` MIME type (application/wasm) for any served wasm file.\n * Where it runs: both app and wallet-iframe dev servers.\n */\nexport function tatchiWasmMime(): VitePlugin {\n return {\n name: 'tatchi:wasm-mime',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n if (url.endsWith('.wasm')) {\n res.setHeader('Content-Type', 'application/wasm')\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin: add Permissions-Policy (delegating WebAuthn + clipboard), COOP, optional COEP/CORP, and optional dev CSP.\n * Where it runs: both app and wallet-iframe dev servers.\n * Notes:\n * - Uses Structured Header format for Permissions-Policy (double-quoted origins).\n * - Wallet dev CSP can be toggled strict/compatible via opts.devCSP.\n */\nexport function tatchiHeaders(opts: DevHeadersOptions = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(opts.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const devCSPMode = (opts.devCSP ?? (process.env.VITE_WALLET_DEV_CSP as 'strict' | 'compatible' | undefined))\n const coepMode = resolveCoepMode(opts.coepMode)\n const coopMode = resolveCoopMode(opts.coopMode)\n\n // Build headers via shared helpers to avoid drift.\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n\n // Dev convenience: dynamic ROR from NEAR RPC (no relay dependency)\n // The dev server will fetch the allowlist from chain on demand when a contract id is provided.\n const rorContractId = (process.env.VITE_WEBAUTHN_CONTRACT_ID || '').toString().trim()\n const rorMethod = (process.env.VITE_ROR_METHOD || 'get_allowed_origins').toString().trim()\n const nearRpcUrl = (process.env.VITE_NEAR_RPC_URL || 'https://test.rpc.fastnear.com').toString().trim()\n // Caching is handled inside fetchRorOriginsFromNear via TTL\n\n return {\n name: 'tatchi:dev-headers',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n console.log('[tatchi] headers enabled', {\n walletServicePath,\n sdkBasePath,\n coepMode,\n rorContractId: rorContractId || '(none)',\n nearRpcUrl\n })\n\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0] || ''\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n if (isWalletRoute) {\n res.setHeader('Cross-Origin-Opener-Policy', 'unsafe-none')\n } else if (coopMode !== 'off') {\n res.setHeader('Cross-Origin-Opener-Policy', coopMode)\n }\n if (coepMode !== 'off') {\n res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n }\n res.setHeader('Permissions-Policy', permissionsPolicy)\n // Optional dev-time CSP for the wallet service page only (app pages are unaffected)\n if (isWalletRoute && devCSPMode) {\n const mode = devCSPMode === 'strict' ? 'strict' : 'compatible'\n const walletCsp = buildWalletCsp({ mode })\n res.setHeader('Content-Security-Policy', walletCsp)\n }\n // Resource hints: help parent pages preconnect to the wallet origins early in dev\n addPreconnectLink(res, walletOrigins)\n\n // Serve /.well-known/webauthn for ROR using chain state in dev\n const isWellKnown = url === '/.well-known/webauthn' || url === '/.well-known/webauthn/'\n if (isWellKnown) {\n // Direct fetch from NEAR RPC (no relay). Caching handled inside helper.\n // Requires contract id; RPC URL falls back to a reliable public endpoint.\n if (rorContractId) {\n ;(async () => {\n try {\n const origins = await fetchRorOriginsFromNear({\n rpcUrl: nearRpcUrl,\n contractId: rorContractId,\n method: rorMethod,\n })\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins }))\n } catch (e) {\n console.warn('[tatchi] ROR dynamic fetch failed:', e)\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n }\n })()\n return\n }\n // No configuration; respond with empty allowlist to avoid hard 404 in dev\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n return\n }\n\n if (url.startsWith(`${sdkBasePath}/`)) {\n // Dev-only CORS for SDK assets served by Vite\n applyCoepCorpIfNeeded(res, coepMode)\n // Honor existing echo from SDK server; otherwise echo\n const ended = echoCorsFromRequest(res, req, { honorExistingAcaOrigin: true, handlePreflight: true })\n if (ended) return\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin (composed): convenience entry that wires SDK server, WASM MIME, optional headers,\n * and (in wallet modes) the wallet service route.\n * Where it runs:\n * - App server: mode 'front-only' (or 'self-contained' when serving wallet pages on the same origin).\n * - Wallet-iframe server: modes 'wallet-only' or 'self-contained'.\n */\n/**\n * Compose dev plugins for serving SDK assets, wallet service HTML and dev headers.\n * External-facing entry for configuring either the app or wallet-iframe dev server.\n */\nfunction tatchiDevServer(options: Web3AuthnDevOptions = {}): VitePlugin {\n const mode: Required<Web3AuthnDevOptions>['mode'] = options.mode || 'self-contained'\n const sdkBasePath = toBasePath(options.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const walletServicePath = toBasePath(options.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const walletOrigins = normalizeWalletOrigins(\n options.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const setDevHeaders = options.setDevHeaders !== false // default true\n const enableDebugRoutes = options.enableDebugRoutes === true\n const sdkDistRoot = resolveSdkDistRoot(options.sdkDistRoot)\n const coepMode = resolveCoepMode(options.coepMode)\n const coopMode = options.coopMode\n\n // Build the sub-plugins to keep logic small and testable\n const sdkPlugin = tatchiServeSdk({ sdkBasePath, sdkDistRoot, enableDebugRoutes, coepMode })\n const walletPlugin = tatchiWalletService({ walletServicePath, sdkBasePath, coepMode })\n const wasmMimePlugin = tatchiWasmMime()\n // Flip wallet CSP to strict by default in dev. Consumers can override via\n // VITE_WALLET_DEV_CSP or by composing tatchiHeaders directly.\n const headersPlugin = setDevHeaders\n ? tatchiHeaders({ walletOrigins, walletServicePath, sdkBasePath, devCSP: 'strict', coepMode, coopMode })\n : undefined\n\n return {\n name: 'tatchi:dev',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Always add WASM MIME + SDK server\n sdkPlugin.configureServer?.(server)\n wasmMimePlugin.configureServer?.(server)\n if (headersPlugin) headersPlugin.configureServer?.(server)\n\n // Mode-specific wallet service route\n if (mode === 'self-contained' || mode === 'wallet-only') {\n walletPlugin.configureServer?.(server)\n }\n },\n }\n}\n\n// === Build-time helper: emit Cloudflare Pages/Netlify _headers ===\n// This plugin writes a _headers file into Vite's outDir with COOP and optional COEP and a\n// Permissions-Policy delegating WebAuthn to the configured wallet origins.\n// It is a no-op if a _headers file already exists (to avoid overriding app settings).\n/**\n * Build-time plugin: writes a Cloudflare Pages/Netlify-compatible `_headers` file into Vite's `outDir`.\n * Adds COOP + Permissions-Policy and optional COEP/CORP (configurable via coepMode) delegating WebAuthn to the configured wallet origins.\n * Where it runs: build for either the app or a static wallet host (not used in dev).\n * Notes: no-ops if `_headers` already exists in `outDir` (to avoid overriding platform config).\n */\nexport function tatchiBuildHeaders(opts: {\n walletOrigins?: string[],\n cors?: { accessControlAllowOrigin?: string },\n coepMode?: 'strict' | 'off',\n coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups',\n} = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(process.env.VITE_SDK_BASE_PATH, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n const coopMode = resolveCoopMode(opts.coopMode)\n\n // Build headers via shared helpers to avoid drift between frameworks\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n const walletCsp = buildWalletCsp({ mode: 'strict' })\n\n let outDir = 'dist'\n\n // We intentionally return a broader shape than VitePlugin; cast at the end\n const plugin = {\n name: 'tatchi:build-headers',\n apply: 'build' as const,\n enforce: 'post' as const,\n // Capture the resolved outDir\n configResolved(config: any) {\n outDir = (config?.build?.outDir as string) || outDir\n },\n generateBundle() {\n try {\n const hdrPath = path.join(outDir, '_headers')\n if (fs.existsSync(hdrPath)) {\n // Do not override existing headers; leave a note in build logs\n console.warn('[tatchi] _headers already exists in outDir; skipping auto-emission')\n } else {\n // Strict CSP is emitted only for wallet HTML routes; not for app pages.\n const contentLines: string[] = [\n '/*',\n ...(coopMode === 'off' ? [] : [` Cross-Origin-Opener-Policy: ${coopMode}`]),\n ...(coepMode === 'off'\n ? []\n : [\n ' Cross-Origin-Embedder-Policy: require-corp',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ]),\n ` Permissions-Policy: ${permissionsPolicy}`,\n '',\n `${walletServicePath}`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n // Always allow COEP=require-corp apps to embed wallet HTML, even when\n // the wallet host itself is not using COEP.\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n `${walletServicePath}/`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n '/export-viewer',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n '/export-viewer/',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n // Offline export cache policy (no-cache for HTML/SW; immutable for other assets)\n '/offline-export',\n ' Cache-Control: no-cache',\n '/offline-export/',\n ' Cache-Control: no-cache',\n '/offline-export/index.html',\n ' Cache-Control: no-cache',\n '/offline-export/sw.js',\n ' Cache-Control: no-cache',\n '/offline-export/precache.manifest.json',\n ' Cache-Control: no-cache',\n '/offline-export/manifest.webmanifest',\n ' Cache-Control: no-cache',\n '/offline-export/offline-export-app.js',\n ' Cache-Control: no-cache',\n '/offline-export/*',\n ' Cache-Control: public, max-age=31536000, immutable',\n ]\n // Optional: emit CORS headers when explicitly configured via plugin option.\n // Prefer a single source of truth (platform or plugin), not both.\n const configuredAcaOrigin = (opts.cors && typeof opts.cors.accessControlAllowOrigin === 'string'\n ? opts.cors.accessControlAllowOrigin.trim()\n : undefined) as string | undefined;\n if (configuredAcaOrigin) {\n contentLines.push(\n `${sdkBasePath}/*`,\n ` Access-Control-Allow-Origin: ${configuredAcaOrigin}`,\n )\n }\n const content = contentLines.join('\\n') + '\\n'\n fs.mkdirSync(outDir, { recursive: true })\n fs.writeFileSync(hdrPath, content, 'utf-8')\n console.log('[tatchi] emitted _headers with COOP' + (coepMode === 'off' ? '' : '/COEP/CORP') + ' + Permissions-Policy' + (configuredAcaOrigin ? ' + CORS' : ''))\n }\n\n const sdkDir = path.join(outDir, sdkBasePath.replace(/^\\//, ''))\n try { fs.mkdirSync(sdkDir, { recursive: true }) } catch {}\n const shimPath = path.join(sdkDir, 'wallet-shims.js')\n if (!fs.existsSync(shimPath)) {\n fs.writeFileSync(shimPath, WALLET_SHIM_SOURCE, 'utf-8')\n }\n const cssPath = path.join(sdkDir, 'wallet-service.css')\n if (!fs.existsSync(cssPath)) {\n fs.writeFileSync(cssPath, WALLET_SURFACE_CSS, 'utf-8')\n }\n\n // Emit minimal wallet-service/index.html if the app hasn't provided one\n const walletRel = walletServicePath.replace(/^\\//, '')\n const wsDir = path.join(outDir, walletRel)\n const wsHtml = path.join(wsDir, 'index.html')\n if (!fs.existsSync(wsHtml)) {\n fs.mkdirSync(wsDir, { recursive: true })\n fs.writeFileSync(wsHtml, buildWalletServiceHtml(sdkBasePath), 'utf-8')\n console.log(`[tatchi] emitted ${path.posix.join('/', walletRel, 'index.html')} (minimal wallet service)`)\n }\n\n // Emit minimal export viewer HTML for production\n const evDir = path.join(outDir, 'export-viewer')\n const evHtml = path.join(evDir, 'index.html')\n if (!fs.existsSync(evHtml)) {\n fs.mkdirSync(evDir, { recursive: true })\n fs.writeFileSync(evHtml, buildExportViewerHtml(sdkBasePath), 'utf-8')\n console.log('[tatchi] emitted /export-viewer/index.html (minimal export viewer)')\n }\n\n // Emit offline-export assets (SW, workers, app, HTML, manifest, precache) via helper\n try {\n const sdkDistRoot = resolveSdkDistRoot()\n emitOfflineExportAssets({ outDir, sdkBasePath, sdkDistRoot })\n } catch (e) {\n console.warn('[tatchi] failed to emit offline-export assets:', e)\n }\n } catch (e) {\n console.warn('[tatchi] failed to emit _headers:', e)\n }\n },\n }\n\n return plugin as unknown as VitePlugin\n}\n\n// Small test helpers to keep unit tests decoupled from Vite server implementation\nexport function computeDevPermissionsPolicy(walletOrigins?: string[]): string {\n return buildPermissionsPolicy(walletOrigins)\n}\n\nexport function computeDevWalletCsp(mode: 'strict' | 'compatible' = 'strict'): string {\n return buildWalletCsp({ mode })\n}\n\nexport function tatchiWalletServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'wallet-only' })\n}\n\nexport function tatchiAppServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'front-only' })\n}\n\n/**\n * Convenience wrapper: app origin helper that combines dev-time headers with optional\n * build-time headers emission for static hosts.\n *\n * Dev-time (serve): applies COOP + Permissions-Policy, plus optional COEP/CORP, via tatchiAppServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP` (defaults to `same-origin-allow-popups`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid surprising overrides when apps\n * already manage headers via custom servers or platform rules.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiApp(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const app = tatchiAppServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders\n ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode, coopMode: devOpts.coopMode })\n : undefined\n return [app, hdr].filter(Boolean) as any[]\n}\n\n/**\n * Convenience wrapper: wallet origins helper that combines dev-time wallet server\n * with optional build-time headers emission for static hosts.\n *\n * Dev-time (serve): serves `/wallet-service` and `/sdk/*` plus headers via tatchiWalletServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP` on app routes (defaults to `same-origin-allow-popups`; wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid overriding platform/server configs.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiWallet(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const wallet = tatchiWalletServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders\n ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode, coopMode: devOpts.coopMode })\n : undefined\n return [wallet, hdr].filter(Boolean) as any[]\n}\n"],"mappings":"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"}
@@ -26,6 +26,14 @@ function parseWalletOriginsEnv(value) {
26
26
  const origins = normalizeWalletOrigins(parts);
27
27
  return origins.length ? origins : void 0;
28
28
  }
29
+ function resolveCoopMode(explicit) {
30
+ if (explicit === "off" || explicit === "same-origin" || explicit === "same-origin-allow-popups") return explicit;
31
+ const raw = String(globalThis?.process?.env?.VITE_COOP_MODE || "").trim().toLowerCase();
32
+ if (raw === "off" || raw === "0" || raw === "false" || raw === "none") return "off";
33
+ if (raw === "same-origin-allow-popups" || raw === "allow-popups") return "same-origin-allow-popups";
34
+ if (raw === "same-origin" || raw === "strict" || raw === "1") return "same-origin";
35
+ return "off";
36
+ }
29
37
  /**
30
38
  * Return the first candidate path that exists and is a file.
31
39
  * Helper for robust /sdk/* asset resolution on dev servers (app and wallet).
@@ -221,6 +229,7 @@ function tatchiHeaders(opts = {}) {
221
229
  const sdkBasePath = toBasePath(opts.sdkBasePath || process.env.VITE_SDK_BASE_PATH, "/sdk");
222
230
  const devCSPMode = opts.devCSP ?? process.env.VITE_WALLET_DEV_CSP;
223
231
  const coepMode = resolveCoepMode(opts.coepMode);
232
+ const coopMode = resolveCoopMode(opts.coopMode);
224
233
  const permissionsPolicy = buildPermissionsPolicy(walletOrigins);
225
234
  const rorContractId = (process.env.VITE_WEBAUTHN_CONTRACT_ID || "").toString().trim();
226
235
  const rorMethod = (process.env.VITE_ROR_METHOD || "get_allowed_origins").toString().trim();
@@ -241,7 +250,8 @@ function tatchiHeaders(opts = {}) {
241
250
  server.middlewares.use((req, res, next) => {
242
251
  const url = (req.url || "").split("?")[0] || "";
243
252
  const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`;
244
- res.setHeader("Cross-Origin-Opener-Policy", isWalletRoute ? "unsafe-none" : "same-origin");
253
+ if (isWalletRoute) res.setHeader("Cross-Origin-Opener-Policy", "unsafe-none");
254
+ else if (coopMode !== "off") res.setHeader("Cross-Origin-Opener-Policy", coopMode);
245
255
  if (coepMode !== "off") {
246
256
  res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
247
257
  res.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
@@ -316,6 +326,7 @@ function tatchiDevServer(options = {}) {
316
326
  const enableDebugRoutes = options.enableDebugRoutes === true;
317
327
  const sdkDistRoot = resolveSdkDistRoot(options.sdkDistRoot);
318
328
  const coepMode = resolveCoepMode(options.coepMode);
329
+ const coopMode = options.coopMode;
319
330
  const sdkPlugin = tatchiServeSdk({
320
331
  sdkBasePath,
321
332
  sdkDistRoot,
@@ -333,7 +344,8 @@ function tatchiDevServer(options = {}) {
333
344
  walletServicePath,
334
345
  sdkBasePath,
335
346
  devCSP: "strict",
336
- coepMode
347
+ coepMode,
348
+ coopMode
337
349
  }) : void 0;
338
350
  return {
339
351
  name: "tatchi:dev",
@@ -359,6 +371,7 @@ function tatchiBuildHeaders(opts = {}) {
359
371
  const walletServicePath = toBasePath(process.env.VITE_WALLET_SERVICE_PATH, "/wallet-service");
360
372
  const sdkBasePath = toBasePath(process.env.VITE_SDK_BASE_PATH, "/sdk");
361
373
  const coepMode = resolveCoepMode(opts.coepMode);
374
+ const coopMode = resolveCoopMode(opts.coopMode);
362
375
  const permissionsPolicy = buildPermissionsPolicy(walletOrigins);
363
376
  const walletCsp = buildWalletCsp({ mode: "strict" });
364
377
  let outDir = "dist";
@@ -376,7 +389,7 @@ function tatchiBuildHeaders(opts = {}) {
376
389
  else {
377
390
  const contentLines = [
378
391
  "/*",
379
- " Cross-Origin-Opener-Policy: same-origin",
392
+ ...coopMode === "off" ? [] : [` Cross-Origin-Opener-Policy: ${coopMode}`],
380
393
  ...coepMode === "off" ? [] : [" Cross-Origin-Embedder-Policy: require-corp", " Cross-Origin-Resource-Policy: cross-origin"],
381
394
  ` Permissions-Policy: ${permissionsPolicy}`,
382
395
  "",
@@ -488,7 +501,7 @@ function tatchiAppServer(options = {}) {
488
501
  * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify
489
502
  * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to
490
503
  * wallet HTML routes only.
491
- * - Emits: `COOP: same-origin`, `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
504
+ * - Emits: `COOP` (defaults to `same-origin-allow-popups`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
492
505
  * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).
493
506
  *
494
507
  * Notes
@@ -502,7 +515,8 @@ function tatchiApp(options = {}) {
502
515
  const app = tatchiAppServer(devOpts);
503
516
  const hdr = emitHeaders ? tatchiBuildHeaders({
504
517
  walletOrigins,
505
- coepMode: devOpts.coepMode
518
+ coepMode: devOpts.coepMode,
519
+ coopMode: devOpts.coopMode
506
520
  }) : void 0;
507
521
  return [app, hdr].filter(Boolean);
508
522
  }
@@ -514,7 +528,7 @@ function tatchiApp(options = {}) {
514
528
  * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify
515
529
  * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to
516
530
  * wallet HTML routes only.
517
- * - Emits: `COOP: same-origin` (wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
531
+ * - Emits: `COOP` on app routes (defaults to `same-origin-allow-popups`; wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
518
532
  * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).
519
533
  *
520
534
  * Notes
@@ -527,7 +541,8 @@ function tatchiWallet(options = {}) {
527
541
  const wallet = tatchiWalletServer(devOpts);
528
542
  const hdr = emitHeaders ? tatchiBuildHeaders({
529
543
  walletOrigins,
530
- coepMode: devOpts.coepMode
544
+ coepMode: devOpts.coepMode,
545
+ coopMode: devOpts.coopMode
531
546
  }) : void 0;
532
547
  return [wallet, hdr].filter(Boolean);
533
548
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","names":["out: string[]","mode: Required<Web3AuthnDevOptions>['mode']","contentLines: string[]"],"sources":["../../../src/plugins/vite.ts"],"sourcesContent":["// Minimal Vite dev plugin(s) to support Passkey Manager modes.\n// See docs/passkey-manager-modes.md (Vite Plugin section).\n//\n// What these plugins do:\n// - Serve SDK assets under a base path, expose a wallet service route,\n// - Add dev headers (COOP + Permissions-Policy, optional COEP/CORP), and enforce WASM MIME.\n// - IMPORTANT: Strict CSP is scoped only to wallet HTML routes (/wallet-service, /export-viewer),\n// not to the host app pages. App routes remain free to use inline styles/scripts.\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { buildPermissionsPolicy, buildWalletCsp } from './headers'\nimport { toOriginOrUndefined } from '../utils/validation'\nimport {\n addPreconnectLink,\n buildWalletServiceHtml,\n buildExportViewerHtml,\n applyCoepCorpIfNeeded,\n echoCorsFromRequest,\n fetchRorOriginsFromNear,\n toBasePath,\n resolveCoepMode,\n resolveSdkDistRoot,\n} from './plugin-utils'\nimport { addOfflineExportDevRoutes, buildOfflineExportHtml, emitOfflineExportAssets } from './offline'\nimport { setContentType } from './plugin-utils'\n\nexport type VitePlugin = {\n name: string\n apply?: 'serve' | 'build'\n enforce?: 'pre' | 'post'\n configureServer?: (server: any) => void | Promise<void>\n}\nexport type ViteLikePlugin = VitePlugin\n\nexport type Web3AuthnDevOptions = {\n mode?: 'self-contained' | 'front-only' | 'wallet-only'\n sdkDistRoot?: string\n sdkBasePath?: string\n walletServicePath?: string\n walletOrigins?: string[]\n setDevHeaders?: boolean\n enableDebugRoutes?: boolean\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP on app pages.\n * - 'strict': emit `Cross-Origin-Embedder-Policy: require-corp`\n * and `Cross-Origin-Resource-Policy: cross-origin` on app pages.\n *\n * Tip: set `VITE_COEP_MODE=strict` in tests/CI to enable isolation automatically.\n */\n coepMode?: 'strict' | 'off'\n}\n\nexport type ServeSdkOptions = {\n sdkDistRoot?: string\n sdkBasePath?: string\n enableDebugRoutes?: boolean\n coepMode?: 'strict' | 'off'\n}\n\nexport type WalletServiceOptions = {\n walletServicePath?: string\n sdkBasePath?: string\n coepMode?: 'strict' | 'off'\n}\n\nexport type DevHeadersOptions = {\n walletOrigins?: string[]\n walletServicePath?: string\n sdkBasePath?: string\n /**\n * Optional dev-time CSP for the wallet service route.\n * - 'strict': no inline scripts/styles (mirrors production defaults)\n * - 'compatible': allows inline scripts/styles (useful for debugging)\n */\n devCSP?: 'strict' | 'compatible'\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP headers on app pages.\n * - 'strict': emit COEP/CORP headers on app pages.\n */\n coepMode?: 'strict' | 'off'\n}\n\nfunction normalizeWalletOrigins(walletOrigins?: string[]): string[] {\n if (!Array.isArray(walletOrigins) || walletOrigins.length === 0) return []\n const out: string[] = []\n const seen = new Set<string>()\n for (const origin of walletOrigins) {\n const normalized = toOriginOrUndefined(origin)\n if (!normalized || seen.has(normalized)) continue\n seen.add(normalized)\n out.push(normalized)\n }\n return out\n}\n\nfunction parseWalletOriginsEnv(value: unknown): string[] | undefined {\n if (typeof value !== 'string') return undefined\n const raw = value.trim()\n if (!raw) return undefined\n const parts = raw.split(/[,\\s]+/).map((v) => v.trim()).filter(Boolean)\n const origins = normalizeWalletOrigins(parts)\n return origins.length ? origins : undefined\n}\n\n/**\n * Return the first candidate path that exists and is a file.\n * Helper for robust /sdk/* asset resolution on dev servers (app and wallet).\n */\nfunction tryFile(...candidates: string[]): string | undefined {\n for (const file of candidates) {\n try {\n const stat = fs.statSync(file)\n if (stat.isFile()) return file\n } catch {}\n }\n return undefined\n}\n\n// Dev convenience: allow Vite's cacheDir so `/@fs/.../deps/*.js` dynamic imports can load under `server.fs.strict`.\nfunction ensureViteCacheDirAllowed(server: any): void {\n const config = server?.config\n const cacheDir = config?.cacheDir\n const fsConfig = config?.server?.fs\n const allow = fsConfig?.allow\n if (!cacheDir || fsConfig?.strict === false || !Array.isArray(allow)) return\n\n const absCacheDir = path.resolve(String(cacheDir))\n if (!allow.some((p: any) => path.resolve(String(p)) === absCacheDir)) {\n allow.push(absCacheDir)\n }\n}\n\n// Shared assets emitted/served for the wallet service bootstrap.\nconst WALLET_SHIM_SOURCE = \"window.global ||= window; window.process ||= { env: {} };\\n\"\nconst WALLET_SURFACE_CSS = [\n 'html, body { background: transparent !important; margin:0; padding:0; }',\n 'html, body { color-scheme: normal; }',\n '',\n // Class-based surface for strict CSP setups toggled by JS\n 'html.w3a-transparent, body.w3a-transparent { background: transparent !important; margin:0; padding:0; color-scheme: normal; }',\n '',\n // Minimal portal styles used by confirm-ui (no animation; child components handle transitions)\n '.w3a-portal { position: relative; z-index: 2147483647; opacity: 0; pointer-events: none; }',\n '.w3a-portal.w3a-portal--visible { opacity: 1; pointer-events: auto; }',\n '',\n // Provide baseline tokens only when the document does not declare a theme.\n // This avoids overriding :root[data-w3a-theme] values supplied by token sheet\n // or integrator-injected themes.\n ':root:not([data-w3a-theme]) {',\n ' --w3a-colors-textPrimary: #f6f7f8;',\n ' --w3a-colors-textSecondary: rgba(255,255,255,0.7);',\n ' --w3a-colors-surface: rgba(255,255,255,0.08);',\n ' --w3a-colors-surface2: rgba(255,255,255,0.06);',\n ' --w3a-colors-surface3: rgba(255,255,255,0.04);',\n ' --w3a-colors-borderPrimary: rgba(255,255,255,0.14);',\n ' --w3a-colors-borderSecondary: rgba(255,255,255,0.1);',\n ' --w3a-colors-colorBackground: #0b0c10;',\n ' /* Default viewport custom properties for width/height calculations */',\n ' --w3a-vw: 100vw;',\n ' --w3a-vh: 100vh;',\n '}',\n '',\n].join('\\n')\n\n/**\n * Tatchi SDK plugin: serve SDK assets under a stable base (default: /sdk) with optional COEP/CORP (strict mode) and permissive CORS.\n * Where it runs: both the app server and the wallet-iframe server.\n * - App server: lets host pages and Lit components load SDK CSS/JS locally.\n * - Wallet server: used by /wallet-service to load wallet-iframe-host.js and related CSS/JS.\n */\nexport function tatchiServeSdk(opts: ServeSdkOptions = {}): VitePlugin {\n const configuredBase = toBasePath(opts.sdkBasePath, '/sdk')\n const sdkDistRoot = resolveSdkDistRoot(opts.sdkDistRoot)\n const enableDebugRoutes = opts.enableDebugRoutes === true\n const coepMode = resolveCoepMode(opts.coepMode)\n const offlineHtml = buildOfflineExportHtml(configuredBase)\n\n // In dev we want both '/sdk' and a custom base to work.\n const bases = Array.from(new Set([configuredBase, toBasePath('/sdk')]))\n .sort((a, b) => b.length - a.length)\n // Prefer longest base match first (e.g., '/sdk/esm/react' before '/sdk')\n\n return {\n name: 'tatchi:serve-sdk',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Mount Offline Export dev routes once here (includes app module + chunks)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath: configuredBase,\n offlineHtml,\n includeAppModule: true,\n coepMode,\n })\n // Serve a tiny shim as a virtual asset to enable strict CSP (no inline scripts)\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0]\n if (url === configuredBase + '/wallet-shims.js') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/javascript; charset=utf-8')\n // Align with SDK asset headers so COEP/CORP environments can import\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SHIM_SOURCE)\n return\n }\n if (url === configuredBase + '/wallet-service.css') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/css; charset=utf-8')\n // Important: provide CORP for cross‑origin CSS so COEP documents can load it\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SURFACE_CSS)\n return\n }\n next()\n })\n\n // Optional debug route to confirm resolution\n if (enableDebugRoutes) {\n server.middlewares.use('/__sdk-root', (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/plain; charset=utf-8')\n res.end(sdkDistRoot)\n })\n }\n\n // Serve files under any recognized base from sdkDistRoot with fallbacks\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n\n const matchBase = bases.find((b) => url.startsWith(b + '/'))\n if (!matchBase) return next()\n\n const rel = url.slice((matchBase + '/').length)\n // Try dist/esm/sdk first (canonical), then common fallbacks\n const candidate = tryFile(\n path.join(sdkDistRoot, 'esm', 'sdk', rel),\n path.join(sdkDistRoot, rel),\n path.join(sdkDistRoot, 'esm', rel)\n )\n\n if (!candidate) {\n res.statusCode = 404\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.end(JSON.stringify({ error: 'SDK asset not found', path: rel }))\n return\n }\n\n setContentType(res, candidate)\n // SDK assets need COEP headers to work in wallet iframe with COEP enabled\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling here)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n const stream = fs.createReadStream(candidate)\n stream.on('error', () => next())\n stream.pipe(res)\n })\n },\n }\n}\n\n/**\n * Dev plugin: expose the wallet service HTML route (default: /wallet-service) that links only external CSS/JS.\n * Where it runs: wallet-iframe dev server (wallet origins). Used by tatchiWalletServer.\n */\nexport function tatchiWalletService(opts: WalletServiceOptions = {}): VitePlugin {\n const walletServicePath = toBasePath(opts.walletServicePath, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n\n const html = buildWalletServiceHtml(sdkBasePath)\n const offlineHtml = buildOfflineExportHtml(sdkBasePath)\n const sdkDistRoot = resolveSdkDistRoot()\n\n return {\n name: 'tatchi:wallet-service',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n if (isWalletRoute) {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/html; charset=utf-8')\n // Important: allow embedding this wallet HTML into COEP=require-corp apps even\n // when the wallet itself is not running with COEP enabled.\n // Without CORP, the iframe can be blocked and remain on an opaque 'null' origin,\n // causing CONNECT/READY handshake timeouts in the parent.\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n applyCoepCorpIfNeeded(res, coepMode)\n res.end(html)\n return\n }\n next()\n })\n\n // Mount Offline Export routes here as well (no app module duplication)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath,\n offlineHtml,\n includeAppModule: false,\n coepMode,\n })\n },\n }\n}\n\n/**\n * Dev plugin: force the correct `.wasm` MIME type (application/wasm) for any served wasm file.\n * Where it runs: both app and wallet-iframe dev servers.\n */\nexport function tatchiWasmMime(): VitePlugin {\n return {\n name: 'tatchi:wasm-mime',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n if (url.endsWith('.wasm')) {\n res.setHeader('Content-Type', 'application/wasm')\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin: add Permissions-Policy (delegating WebAuthn + clipboard), COOP, optional COEP/CORP, and optional dev CSP.\n * Where it runs: both app and wallet-iframe dev servers.\n * Notes:\n * - Uses Structured Header format for Permissions-Policy (double-quoted origins).\n * - Wallet dev CSP can be toggled strict/compatible via opts.devCSP.\n */\nexport function tatchiHeaders(opts: DevHeadersOptions = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(opts.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const devCSPMode = (opts.devCSP ?? (process.env.VITE_WALLET_DEV_CSP as 'strict' | 'compatible' | undefined))\n const coepMode = resolveCoepMode(opts.coepMode)\n\n // Build headers via shared helpers to avoid drift.\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n\n // Dev convenience: dynamic ROR from NEAR RPC (no relay dependency)\n // The dev server will fetch the allowlist from chain on demand when a contract id is provided.\n const rorContractId = (process.env.VITE_WEBAUTHN_CONTRACT_ID || '').toString().trim()\n const rorMethod = (process.env.VITE_ROR_METHOD || 'get_allowed_origins').toString().trim()\n const nearRpcUrl = (process.env.VITE_NEAR_RPC_URL || 'https://test.rpc.fastnear.com').toString().trim()\n // Caching is handled inside fetchRorOriginsFromNear via TTL\n\n return {\n name: 'tatchi:dev-headers',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n console.log('[tatchi] headers enabled', {\n walletServicePath,\n sdkBasePath,\n coepMode,\n rorContractId: rorContractId || '(none)',\n nearRpcUrl\n })\n\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0] || ''\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n res.setHeader('Cross-Origin-Opener-Policy', isWalletRoute ? 'unsafe-none' : 'same-origin')\n if (coepMode !== 'off') {\n res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n }\n res.setHeader('Permissions-Policy', permissionsPolicy)\n // Optional dev-time CSP for the wallet service page only (app pages are unaffected)\n if (isWalletRoute && devCSPMode) {\n const mode = devCSPMode === 'strict' ? 'strict' : 'compatible'\n const walletCsp = buildWalletCsp({ mode })\n res.setHeader('Content-Security-Policy', walletCsp)\n }\n // Resource hints: help parent pages preconnect to the wallet origins early in dev\n addPreconnectLink(res, walletOrigins)\n\n // Serve /.well-known/webauthn for ROR using chain state in dev\n const isWellKnown = url === '/.well-known/webauthn' || url === '/.well-known/webauthn/'\n if (isWellKnown) {\n // Direct fetch from NEAR RPC (no relay). Caching handled inside helper.\n // Requires contract id; RPC URL falls back to a reliable public endpoint.\n if (rorContractId) {\n ;(async () => {\n try {\n const origins = await fetchRorOriginsFromNear({\n rpcUrl: nearRpcUrl,\n contractId: rorContractId,\n method: rorMethod,\n })\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins }))\n } catch (e) {\n console.warn('[tatchi] ROR dynamic fetch failed:', e)\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n }\n })()\n return\n }\n // No configuration; respond with empty allowlist to avoid hard 404 in dev\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n return\n }\n\n if (url.startsWith(`${sdkBasePath}/`)) {\n // Dev-only CORS for SDK assets served by Vite\n applyCoepCorpIfNeeded(res, coepMode)\n // Honor existing echo from SDK server; otherwise echo\n const ended = echoCorsFromRequest(res, req, { honorExistingAcaOrigin: true, handlePreflight: true })\n if (ended) return\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin (composed): convenience entry that wires SDK server, WASM MIME, optional headers,\n * and (in wallet modes) the wallet service route.\n * Where it runs:\n * - App server: mode 'front-only' (or 'self-contained' when serving wallet pages on the same origin).\n * - Wallet-iframe server: modes 'wallet-only' or 'self-contained'.\n */\n/**\n * Compose dev plugins for serving SDK assets, wallet service HTML and dev headers.\n * External-facing entry for configuring either the app or wallet-iframe dev server.\n */\nfunction tatchiDevServer(options: Web3AuthnDevOptions = {}): VitePlugin {\n const mode: Required<Web3AuthnDevOptions>['mode'] = options.mode || 'self-contained'\n const sdkBasePath = toBasePath(options.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const walletServicePath = toBasePath(options.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const walletOrigins = normalizeWalletOrigins(\n options.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const setDevHeaders = options.setDevHeaders !== false // default true\n const enableDebugRoutes = options.enableDebugRoutes === true\n const sdkDistRoot = resolveSdkDistRoot(options.sdkDistRoot)\n const coepMode = resolveCoepMode(options.coepMode)\n\n // Build the sub-plugins to keep logic small and testable\n const sdkPlugin = tatchiServeSdk({ sdkBasePath, sdkDistRoot, enableDebugRoutes, coepMode })\n const walletPlugin = tatchiWalletService({ walletServicePath, sdkBasePath, coepMode })\n const wasmMimePlugin = tatchiWasmMime()\n // Flip wallet CSP to strict by default in dev. Consumers can override via\n // VITE_WALLET_DEV_CSP or by composing tatchiHeaders directly.\n const headersPlugin = setDevHeaders\n ? tatchiHeaders({ walletOrigins, walletServicePath, sdkBasePath, devCSP: 'strict', coepMode })\n : undefined\n\n return {\n name: 'tatchi:dev',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Always add WASM MIME + SDK server\n sdkPlugin.configureServer?.(server)\n wasmMimePlugin.configureServer?.(server)\n if (headersPlugin) headersPlugin.configureServer?.(server)\n\n // Mode-specific wallet service route\n if (mode === 'self-contained' || mode === 'wallet-only') {\n walletPlugin.configureServer?.(server)\n }\n },\n }\n}\n\n// === Build-time helper: emit Cloudflare Pages/Netlify _headers ===\n// This plugin writes a _headers file into Vite's outDir with COOP and optional COEP and a\n// Permissions-Policy delegating WebAuthn to the configured wallet origins.\n// It is a no-op if a _headers file already exists (to avoid overriding app settings).\n/**\n * Build-time plugin: writes a Cloudflare Pages/Netlify-compatible `_headers` file into Vite's `outDir`.\n * Adds COOP + Permissions-Policy and optional COEP/CORP (configurable via coepMode) delegating WebAuthn to the configured wallet origins.\n * Where it runs: build for either the app or a static wallet host (not used in dev).\n * Notes: no-ops if `_headers` already exists in `outDir` (to avoid overriding platform config).\n */\nexport function tatchiBuildHeaders(opts: { walletOrigins?: string[], cors?: { accessControlAllowOrigin?: string }, coepMode?: 'strict' | 'off' } = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(process.env.VITE_SDK_BASE_PATH, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n\n // Build headers via shared helpers to avoid drift between frameworks\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n const walletCsp = buildWalletCsp({ mode: 'strict' })\n\n let outDir = 'dist'\n\n // We intentionally return a broader shape than VitePlugin; cast at the end\n const plugin = {\n name: 'tatchi:build-headers',\n apply: 'build' as const,\n enforce: 'post' as const,\n // Capture the resolved outDir\n configResolved(config: any) {\n outDir = (config?.build?.outDir as string) || outDir\n },\n generateBundle() {\n try {\n const hdrPath = path.join(outDir, '_headers')\n if (fs.existsSync(hdrPath)) {\n // Do not override existing headers; leave a note in build logs\n console.warn('[tatchi] _headers already exists in outDir; skipping auto-emission')\n } else {\n // Strict CSP is emitted only for wallet HTML routes; not for app pages.\n const contentLines: string[] = [\n '/*',\n ' Cross-Origin-Opener-Policy: same-origin',\n ...(coepMode === 'off'\n ? []\n : [\n ' Cross-Origin-Embedder-Policy: require-corp',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ]),\n ` Permissions-Policy: ${permissionsPolicy}`,\n '',\n `${walletServicePath}`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n // Always allow COEP=require-corp apps to embed wallet HTML, even when\n // the wallet host itself is not using COEP.\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n `${walletServicePath}/`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n '/export-viewer',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n '/export-viewer/',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n // Offline export cache policy (no-cache for HTML/SW; immutable for other assets)\n '/offline-export',\n ' Cache-Control: no-cache',\n '/offline-export/',\n ' Cache-Control: no-cache',\n '/offline-export/index.html',\n ' Cache-Control: no-cache',\n '/offline-export/sw.js',\n ' Cache-Control: no-cache',\n '/offline-export/precache.manifest.json',\n ' Cache-Control: no-cache',\n '/offline-export/manifest.webmanifest',\n ' Cache-Control: no-cache',\n '/offline-export/offline-export-app.js',\n ' Cache-Control: no-cache',\n '/offline-export/*',\n ' Cache-Control: public, max-age=31536000, immutable',\n ]\n // Optional: emit CORS headers when explicitly configured via plugin option.\n // Prefer a single source of truth (platform or plugin), not both.\n const configuredAcaOrigin = (opts.cors && typeof opts.cors.accessControlAllowOrigin === 'string'\n ? opts.cors.accessControlAllowOrigin.trim()\n : undefined) as string | undefined;\n if (configuredAcaOrigin) {\n contentLines.push(\n `${sdkBasePath}/*`,\n ` Access-Control-Allow-Origin: ${configuredAcaOrigin}`,\n )\n }\n const content = contentLines.join('\\n') + '\\n'\n fs.mkdirSync(outDir, { recursive: true })\n fs.writeFileSync(hdrPath, content, 'utf-8')\n console.log('[tatchi] emitted _headers with COOP' + (coepMode === 'off' ? '' : '/COEP/CORP') + ' + Permissions-Policy' + (configuredAcaOrigin ? ' + CORS' : ''))\n }\n\n const sdkDir = path.join(outDir, sdkBasePath.replace(/^\\//, ''))\n try { fs.mkdirSync(sdkDir, { recursive: true }) } catch {}\n const shimPath = path.join(sdkDir, 'wallet-shims.js')\n if (!fs.existsSync(shimPath)) {\n fs.writeFileSync(shimPath, WALLET_SHIM_SOURCE, 'utf-8')\n }\n const cssPath = path.join(sdkDir, 'wallet-service.css')\n if (!fs.existsSync(cssPath)) {\n fs.writeFileSync(cssPath, WALLET_SURFACE_CSS, 'utf-8')\n }\n\n // Emit minimal wallet-service/index.html if the app hasn't provided one\n const walletRel = walletServicePath.replace(/^\\//, '')\n const wsDir = path.join(outDir, walletRel)\n const wsHtml = path.join(wsDir, 'index.html')\n if (!fs.existsSync(wsHtml)) {\n fs.mkdirSync(wsDir, { recursive: true })\n fs.writeFileSync(wsHtml, buildWalletServiceHtml(sdkBasePath), 'utf-8')\n console.log(`[tatchi] emitted ${path.posix.join('/', walletRel, 'index.html')} (minimal wallet service)`)\n }\n\n // Emit minimal export viewer HTML for production\n const evDir = path.join(outDir, 'export-viewer')\n const evHtml = path.join(evDir, 'index.html')\n if (!fs.existsSync(evHtml)) {\n fs.mkdirSync(evDir, { recursive: true })\n fs.writeFileSync(evHtml, buildExportViewerHtml(sdkBasePath), 'utf-8')\n console.log('[tatchi] emitted /export-viewer/index.html (minimal export viewer)')\n }\n\n // Emit offline-export assets (SW, workers, app, HTML, manifest, precache) via helper\n try {\n const sdkDistRoot = resolveSdkDistRoot()\n emitOfflineExportAssets({ outDir, sdkBasePath, sdkDistRoot })\n } catch (e) {\n console.warn('[tatchi] failed to emit offline-export assets:', e)\n }\n } catch (e) {\n console.warn('[tatchi] failed to emit _headers:', e)\n }\n },\n }\n\n return plugin as unknown as VitePlugin\n}\n\n// Small test helpers to keep unit tests decoupled from Vite server implementation\nexport function computeDevPermissionsPolicy(walletOrigins?: string[]): string {\n return buildPermissionsPolicy(walletOrigins)\n}\n\nexport function computeDevWalletCsp(mode: 'strict' | 'compatible' = 'strict'): string {\n return buildWalletCsp({ mode })\n}\n\nexport function tatchiWalletServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'wallet-only' })\n}\n\nexport function tatchiAppServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'front-only' })\n}\n\n/**\n * Convenience wrapper: app origin helper that combines dev-time headers with optional\n * build-time headers emission for static hosts.\n *\n * Dev-time (serve): applies COOP + Permissions-Policy, plus optional COEP/CORP, via tatchiAppServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP: same-origin`, `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid surprising overrides when apps\n * already manage headers via custom servers or platform rules.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiApp(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const app = tatchiAppServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode }) : undefined\n return [app, hdr].filter(Boolean) as any[]\n}\n\n/**\n * Convenience wrapper: wallet origins helper that combines dev-time wallet server\n * with optional build-time headers emission for static hosts.\n *\n * Dev-time (serve): serves `/wallet-service` and `/sdk/*` plus headers via tatchiWalletServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP: same-origin` (wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid overriding platform/server configs.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiWallet(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const wallet = tatchiWalletServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode }) : undefined\n return [wallet, hdr].filter(Boolean) as any[]\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"vite.js","names":["out: string[]","mode: Required<Web3AuthnDevOptions>['mode']","contentLines: string[]"],"sources":["../../../src/plugins/vite.ts"],"sourcesContent":["// Minimal Vite dev plugin(s) to support Passkey Manager modes.\n// See docs/passkey-manager-modes.md (Vite Plugin section).\n//\n// What these plugins do:\n// - Serve SDK assets under a base path, expose a wallet service route,\n// - Add dev headers (COOP + Permissions-Policy, optional COEP/CORP), and enforce WASM MIME.\n// - IMPORTANT: Strict CSP is scoped only to wallet HTML routes (/wallet-service, /export-viewer),\n// not to the host app pages. App routes remain free to use inline styles/scripts.\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { buildPermissionsPolicy, buildWalletCsp } from './headers'\nimport { toOriginOrUndefined } from '../utils/validation'\nimport {\n addPreconnectLink,\n buildWalletServiceHtml,\n buildExportViewerHtml,\n applyCoepCorpIfNeeded,\n echoCorsFromRequest,\n fetchRorOriginsFromNear,\n toBasePath,\n resolveCoepMode,\n resolveSdkDistRoot,\n} from './plugin-utils'\nimport { addOfflineExportDevRoutes, buildOfflineExportHtml, emitOfflineExportAssets } from './offline'\nimport { setContentType } from './plugin-utils'\n\nexport type VitePlugin = {\n name: string\n apply?: 'serve' | 'build'\n enforce?: 'pre' | 'post'\n configureServer?: (server: any) => void | Promise<void>\n}\nexport type ViteLikePlugin = VitePlugin\n\nexport type Web3AuthnDevOptions = {\n mode?: 'self-contained' | 'front-only' | 'wallet-only'\n sdkDistRoot?: string\n sdkBasePath?: string\n walletServicePath?: string\n walletOrigins?: string[]\n setDevHeaders?: boolean\n enableDebugRoutes?: boolean\n /** See DevHeadersOptions.coopMode */\n coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups'\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP on app pages.\n * - 'strict': emit `Cross-Origin-Embedder-Policy: require-corp`\n * and `Cross-Origin-Resource-Policy: cross-origin` on app pages.\n *\n * Tip: set `VITE_COEP_MODE=strict` in tests/CI to enable isolation automatically.\n */\n coepMode?: 'strict' | 'off'\n}\n\nexport type ServeSdkOptions = {\n sdkDistRoot?: string\n sdkBasePath?: string\n enableDebugRoutes?: boolean\n coepMode?: 'strict' | 'off'\n}\n\nexport type WalletServiceOptions = {\n walletServicePath?: string\n sdkBasePath?: string\n coepMode?: 'strict' | 'off'\n}\n\nexport type DevHeadersOptions = {\n walletOrigins?: string[]\n walletServicePath?: string\n sdkBasePath?: string\n /**\n * Controls Cross-Origin-Opener-Policy (COOP) behavior.\n *\n * COOP can break popup-based third-party wallet flows by severing `window.opener`\n * when set to `same-origin`. Prefer `same-origin-allow-popups` if you need COOP\n * but still rely on popups.\n *\n * - 'off': do not emit COOP on app routes (wallet HTML routes still use `unsafe-none`)\n * - 'same-origin': strict isolation (may break other wallets)\n * - 'same-origin-allow-popups': more compatible with popup flows\n */\n coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups'\n /**\n * Optional dev-time CSP for the wallet service route.\n * - 'strict': no inline scripts/styles (mirrors production defaults)\n * - 'compatible': allows inline scripts/styles (useful for debugging)\n */\n devCSP?: 'strict' | 'compatible'\n /**\n * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.\n * - 'off' (default): do not emit COEP/CORP headers on app pages.\n * - 'strict': emit COEP/CORP headers on app pages.\n */\n coepMode?: 'strict' | 'off'\n}\n\nfunction normalizeWalletOrigins(walletOrigins?: string[]): string[] {\n if (!Array.isArray(walletOrigins) || walletOrigins.length === 0) return []\n const out: string[] = []\n const seen = new Set<string>()\n for (const origin of walletOrigins) {\n const normalized = toOriginOrUndefined(origin)\n if (!normalized || seen.has(normalized)) continue\n seen.add(normalized)\n out.push(normalized)\n }\n return out\n}\n\nfunction parseWalletOriginsEnv(value: unknown): string[] | undefined {\n if (typeof value !== 'string') return undefined\n const raw = value.trim()\n if (!raw) return undefined\n const parts = raw.split(/[,\\s]+/).map((v) => v.trim()).filter(Boolean)\n const origins = normalizeWalletOrigins(parts)\n return origins.length ? origins : undefined\n}\n\nfunction resolveCoopMode(explicit?: 'off' | 'same-origin' | 'same-origin-allow-popups'): 'off' | 'same-origin' | 'same-origin-allow-popups' {\n if (explicit === 'off' || explicit === 'same-origin' || explicit === 'same-origin-allow-popups') return explicit\n const raw = String((globalThis as any)?.process?.env?.VITE_COOP_MODE || '').trim().toLowerCase()\n if (raw === 'off' || raw === '0' || raw === 'false' || raw === 'none') return 'off'\n if (raw === 'same-origin-allow-popups' || raw === 'allow-popups') return 'same-origin-allow-popups'\n if (raw === 'same-origin' || raw === 'strict' || raw === '1') return 'same-origin'\n // Default off to avoid breaking popup-based third-party wallet flows.\n return 'off'\n}\n\n/**\n * Return the first candidate path that exists and is a file.\n * Helper for robust /sdk/* asset resolution on dev servers (app and wallet).\n */\nfunction tryFile(...candidates: string[]): string | undefined {\n for (const file of candidates) {\n try {\n const stat = fs.statSync(file)\n if (stat.isFile()) return file\n } catch {}\n }\n return undefined\n}\n\n// Dev convenience: allow Vite's cacheDir so `/@fs/.../deps/*.js` dynamic imports can load under `server.fs.strict`.\nfunction ensureViteCacheDirAllowed(server: any): void {\n const config = server?.config\n const cacheDir = config?.cacheDir\n const fsConfig = config?.server?.fs\n const allow = fsConfig?.allow\n if (!cacheDir || fsConfig?.strict === false || !Array.isArray(allow)) return\n\n const absCacheDir = path.resolve(String(cacheDir))\n if (!allow.some((p: any) => path.resolve(String(p)) === absCacheDir)) {\n allow.push(absCacheDir)\n }\n}\n\n// Shared assets emitted/served for the wallet service bootstrap.\nconst WALLET_SHIM_SOURCE = \"window.global ||= window; window.process ||= { env: {} };\\n\"\nconst WALLET_SURFACE_CSS = [\n 'html, body { background: transparent !important; margin:0; padding:0; }',\n 'html, body { color-scheme: normal; }',\n '',\n // Class-based surface for strict CSP setups toggled by JS\n 'html.w3a-transparent, body.w3a-transparent { background: transparent !important; margin:0; padding:0; color-scheme: normal; }',\n '',\n // Minimal portal styles used by confirm-ui (no animation; child components handle transitions)\n '.w3a-portal { position: relative; z-index: 2147483647; opacity: 0; pointer-events: none; }',\n '.w3a-portal.w3a-portal--visible { opacity: 1; pointer-events: auto; }',\n '',\n // Provide baseline tokens only when the document does not declare a theme.\n // This avoids overriding :root[data-w3a-theme] values supplied by token sheet\n // or integrator-injected themes.\n ':root:not([data-w3a-theme]) {',\n ' --w3a-colors-textPrimary: #f6f7f8;',\n ' --w3a-colors-textSecondary: rgba(255,255,255,0.7);',\n ' --w3a-colors-surface: rgba(255,255,255,0.08);',\n ' --w3a-colors-surface2: rgba(255,255,255,0.06);',\n ' --w3a-colors-surface3: rgba(255,255,255,0.04);',\n ' --w3a-colors-borderPrimary: rgba(255,255,255,0.14);',\n ' --w3a-colors-borderSecondary: rgba(255,255,255,0.1);',\n ' --w3a-colors-colorBackground: #0b0c10;',\n ' /* Default viewport custom properties for width/height calculations */',\n ' --w3a-vw: 100vw;',\n ' --w3a-vh: 100vh;',\n '}',\n '',\n].join('\\n')\n\n/**\n * Tatchi SDK plugin: serve SDK assets under a stable base (default: /sdk) with optional COEP/CORP (strict mode) and permissive CORS.\n * Where it runs: both the app server and the wallet-iframe server.\n * - App server: lets host pages and Lit components load SDK CSS/JS locally.\n * - Wallet server: used by /wallet-service to load wallet-iframe-host.js and related CSS/JS.\n */\nexport function tatchiServeSdk(opts: ServeSdkOptions = {}): VitePlugin {\n const configuredBase = toBasePath(opts.sdkBasePath, '/sdk')\n const sdkDistRoot = resolveSdkDistRoot(opts.sdkDistRoot)\n const enableDebugRoutes = opts.enableDebugRoutes === true\n const coepMode = resolveCoepMode(opts.coepMode)\n const offlineHtml = buildOfflineExportHtml(configuredBase)\n\n // In dev we want both '/sdk' and a custom base to work.\n const bases = Array.from(new Set([configuredBase, toBasePath('/sdk')]))\n .sort((a, b) => b.length - a.length)\n // Prefer longest base match first (e.g., '/sdk/esm/react' before '/sdk')\n\n return {\n name: 'tatchi:serve-sdk',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Mount Offline Export dev routes once here (includes app module + chunks)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath: configuredBase,\n offlineHtml,\n includeAppModule: true,\n coepMode,\n })\n // Serve a tiny shim as a virtual asset to enable strict CSP (no inline scripts)\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0]\n if (url === configuredBase + '/wallet-shims.js') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/javascript; charset=utf-8')\n // Align with SDK asset headers so COEP/CORP environments can import\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SHIM_SOURCE)\n return\n }\n if (url === configuredBase + '/wallet-service.css') {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/css; charset=utf-8')\n // Important: provide CORP for cross‑origin CSS so COEP documents can load it\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling on this route)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n res.end(WALLET_SURFACE_CSS)\n return\n }\n next()\n })\n\n // Optional debug route to confirm resolution\n if (enableDebugRoutes) {\n server.middlewares.use('/__sdk-root', (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/plain; charset=utf-8')\n res.end(sdkDistRoot)\n })\n }\n\n // Serve files under any recognized base from sdkDistRoot with fallbacks\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n\n const matchBase = bases.find((b) => url.startsWith(b + '/'))\n if (!matchBase) return next()\n\n const rel = url.slice((matchBase + '/').length)\n // Try dist/esm/sdk first (canonical), then common fallbacks\n const candidate = tryFile(\n path.join(sdkDistRoot, 'esm', 'sdk', rel),\n path.join(sdkDistRoot, rel),\n path.join(sdkDistRoot, 'esm', rel)\n )\n\n if (!candidate) {\n res.statusCode = 404\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.end(JSON.stringify({ error: 'SDK asset not found', path: rel }))\n return\n }\n\n setContentType(res, candidate)\n // SDK assets need COEP headers to work in wallet iframe with COEP enabled\n applyCoepCorpIfNeeded(res, coepMode)\n // Dev-only CORS echo (no preflight handling here)\n echoCorsFromRequest(res, req, { handlePreflight: false })\n const stream = fs.createReadStream(candidate)\n stream.on('error', () => next())\n stream.pipe(res)\n })\n },\n }\n}\n\n/**\n * Dev plugin: expose the wallet service HTML route (default: /wallet-service) that links only external CSS/JS.\n * Where it runs: wallet-iframe dev server (wallet origins). Used by tatchiWalletServer.\n */\nexport function tatchiWalletService(opts: WalletServiceOptions = {}): VitePlugin {\n const walletServicePath = toBasePath(opts.walletServicePath, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n\n const html = buildWalletServiceHtml(sdkBasePath)\n const offlineHtml = buildOfflineExportHtml(sdkBasePath)\n const sdkDistRoot = resolveSdkDistRoot()\n\n return {\n name: 'tatchi:wallet-service',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n if (isWalletRoute) {\n res.statusCode = 200\n res.setHeader('Content-Type', 'text/html; charset=utf-8')\n // Important: allow embedding this wallet HTML into COEP=require-corp apps even\n // when the wallet itself is not running with COEP enabled.\n // Without CORP, the iframe can be blocked and remain on an opaque 'null' origin,\n // causing CONNECT/READY handshake timeouts in the parent.\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n applyCoepCorpIfNeeded(res, coepMode)\n res.end(html)\n return\n }\n next()\n })\n\n // Mount Offline Export routes here as well (no app module duplication)\n addOfflineExportDevRoutes(server, {\n sdkDistRoot,\n sdkBasePath,\n offlineHtml,\n includeAppModule: false,\n coepMode,\n })\n },\n }\n}\n\n/**\n * Dev plugin: force the correct `.wasm` MIME type (application/wasm) for any served wasm file.\n * Where it runs: both app and wallet-iframe dev servers.\n */\nexport function tatchiWasmMime(): VitePlugin {\n return {\n name: 'tatchi:wasm-mime',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n server.middlewares.use((req: any, res: any, next: any) => {\n if (!req.url) return next()\n const url = req.url.split('?')[0]\n if (url.endsWith('.wasm')) {\n res.setHeader('Content-Type', 'application/wasm')\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin: add Permissions-Policy (delegating WebAuthn + clipboard), COOP, optional COEP/CORP, and optional dev CSP.\n * Where it runs: both app and wallet-iframe dev servers.\n * Notes:\n * - Uses Structured Header format for Permissions-Policy (double-quoted origins).\n * - Wallet dev CSP can be toggled strict/compatible via opts.devCSP.\n */\nexport function tatchiHeaders(opts: DevHeadersOptions = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(opts.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(opts.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const devCSPMode = (opts.devCSP ?? (process.env.VITE_WALLET_DEV_CSP as 'strict' | 'compatible' | undefined))\n const coepMode = resolveCoepMode(opts.coepMode)\n const coopMode = resolveCoopMode(opts.coopMode)\n\n // Build headers via shared helpers to avoid drift.\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n\n // Dev convenience: dynamic ROR from NEAR RPC (no relay dependency)\n // The dev server will fetch the allowlist from chain on demand when a contract id is provided.\n const rorContractId = (process.env.VITE_WEBAUTHN_CONTRACT_ID || '').toString().trim()\n const rorMethod = (process.env.VITE_ROR_METHOD || 'get_allowed_origins').toString().trim()\n const nearRpcUrl = (process.env.VITE_NEAR_RPC_URL || 'https://test.rpc.fastnear.com').toString().trim()\n // Caching is handled inside fetchRorOriginsFromNear via TTL\n\n return {\n name: 'tatchi:dev-headers',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n console.log('[tatchi] headers enabled', {\n walletServicePath,\n sdkBasePath,\n coepMode,\n rorContractId: rorContractId || '(none)',\n nearRpcUrl\n })\n\n server.middlewares.use((req: any, res: any, next: any) => {\n const url = (req.url || '').split('?')[0] || ''\n const isWalletRoute = url === walletServicePath || url === `${walletServicePath}/` || url === `${walletServicePath}//`\n if (isWalletRoute) {\n res.setHeader('Cross-Origin-Opener-Policy', 'unsafe-none')\n } else if (coopMode !== 'off') {\n res.setHeader('Cross-Origin-Opener-Policy', coopMode)\n }\n if (coepMode !== 'off') {\n res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')\n }\n res.setHeader('Permissions-Policy', permissionsPolicy)\n // Optional dev-time CSP for the wallet service page only (app pages are unaffected)\n if (isWalletRoute && devCSPMode) {\n const mode = devCSPMode === 'strict' ? 'strict' : 'compatible'\n const walletCsp = buildWalletCsp({ mode })\n res.setHeader('Content-Security-Policy', walletCsp)\n }\n // Resource hints: help parent pages preconnect to the wallet origins early in dev\n addPreconnectLink(res, walletOrigins)\n\n // Serve /.well-known/webauthn for ROR using chain state in dev\n const isWellKnown = url === '/.well-known/webauthn' || url === '/.well-known/webauthn/'\n if (isWellKnown) {\n // Direct fetch from NEAR RPC (no relay). Caching handled inside helper.\n // Requires contract id; RPC URL falls back to a reliable public endpoint.\n if (rorContractId) {\n ;(async () => {\n try {\n const origins = await fetchRorOriginsFromNear({\n rpcUrl: nearRpcUrl,\n contractId: rorContractId,\n method: rorMethod,\n })\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins }))\n } catch (e) {\n console.warn('[tatchi] ROR dynamic fetch failed:', e)\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n }\n })()\n return\n }\n // No configuration; respond with empty allowlist to avoid hard 404 in dev\n res.statusCode = 200\n res.setHeader('Content-Type', 'application/json; charset=utf-8')\n res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=600')\n res.end(JSON.stringify({ origins: [] }))\n return\n }\n\n if (url.startsWith(`${sdkBasePath}/`)) {\n // Dev-only CORS for SDK assets served by Vite\n applyCoepCorpIfNeeded(res, coepMode)\n // Honor existing echo from SDK server; otherwise echo\n const ended = echoCorsFromRequest(res, req, { honorExistingAcaOrigin: true, handlePreflight: true })\n if (ended) return\n }\n next()\n })\n },\n }\n}\n\n/**\n * Dev plugin (composed): convenience entry that wires SDK server, WASM MIME, optional headers,\n * and (in wallet modes) the wallet service route.\n * Where it runs:\n * - App server: mode 'front-only' (or 'self-contained' when serving wallet pages on the same origin).\n * - Wallet-iframe server: modes 'wallet-only' or 'self-contained'.\n */\n/**\n * Compose dev plugins for serving SDK assets, wallet service HTML and dev headers.\n * External-facing entry for configuring either the app or wallet-iframe dev server.\n */\nfunction tatchiDevServer(options: Web3AuthnDevOptions = {}): VitePlugin {\n const mode: Required<Web3AuthnDevOptions>['mode'] = options.mode || 'self-contained'\n const sdkBasePath = toBasePath(options.sdkBasePath || process.env.VITE_SDK_BASE_PATH, '/sdk')\n const walletServicePath = toBasePath(options.walletServicePath || process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const walletOrigins = normalizeWalletOrigins(\n options.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const setDevHeaders = options.setDevHeaders !== false // default true\n const enableDebugRoutes = options.enableDebugRoutes === true\n const sdkDistRoot = resolveSdkDistRoot(options.sdkDistRoot)\n const coepMode = resolveCoepMode(options.coepMode)\n const coopMode = options.coopMode\n\n // Build the sub-plugins to keep logic small and testable\n const sdkPlugin = tatchiServeSdk({ sdkBasePath, sdkDistRoot, enableDebugRoutes, coepMode })\n const walletPlugin = tatchiWalletService({ walletServicePath, sdkBasePath, coepMode })\n const wasmMimePlugin = tatchiWasmMime()\n // Flip wallet CSP to strict by default in dev. Consumers can override via\n // VITE_WALLET_DEV_CSP or by composing tatchiHeaders directly.\n const headersPlugin = setDevHeaders\n ? tatchiHeaders({ walletOrigins, walletServicePath, sdkBasePath, devCSP: 'strict', coepMode, coopMode })\n : undefined\n\n return {\n name: 'tatchi:dev',\n apply: 'serve',\n enforce: 'pre',\n configureServer(server) {\n ensureViteCacheDirAllowed(server)\n\n // Always add WASM MIME + SDK server\n sdkPlugin.configureServer?.(server)\n wasmMimePlugin.configureServer?.(server)\n if (headersPlugin) headersPlugin.configureServer?.(server)\n\n // Mode-specific wallet service route\n if (mode === 'self-contained' || mode === 'wallet-only') {\n walletPlugin.configureServer?.(server)\n }\n },\n }\n}\n\n// === Build-time helper: emit Cloudflare Pages/Netlify _headers ===\n// This plugin writes a _headers file into Vite's outDir with COOP and optional COEP and a\n// Permissions-Policy delegating WebAuthn to the configured wallet origins.\n// It is a no-op if a _headers file already exists (to avoid overriding app settings).\n/**\n * Build-time plugin: writes a Cloudflare Pages/Netlify-compatible `_headers` file into Vite's `outDir`.\n * Adds COOP + Permissions-Policy and optional COEP/CORP (configurable via coepMode) delegating WebAuthn to the configured wallet origins.\n * Where it runs: build for either the app or a static wallet host (not used in dev).\n * Notes: no-ops if `_headers` already exists in `outDir` (to avoid overriding platform config).\n */\nexport function tatchiBuildHeaders(opts: {\n walletOrigins?: string[],\n cors?: { accessControlAllowOrigin?: string },\n coepMode?: 'strict' | 'off',\n coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups',\n} = {}): VitePlugin {\n const walletOrigins = normalizeWalletOrigins(\n opts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const walletServicePath = toBasePath(process.env.VITE_WALLET_SERVICE_PATH, '/wallet-service')\n const sdkBasePath = toBasePath(process.env.VITE_SDK_BASE_PATH, '/sdk')\n const coepMode = resolveCoepMode(opts.coepMode)\n const coopMode = resolveCoopMode(opts.coopMode)\n\n // Build headers via shared helpers to avoid drift between frameworks\n const permissionsPolicy = buildPermissionsPolicy(walletOrigins)\n const walletCsp = buildWalletCsp({ mode: 'strict' })\n\n let outDir = 'dist'\n\n // We intentionally return a broader shape than VitePlugin; cast at the end\n const plugin = {\n name: 'tatchi:build-headers',\n apply: 'build' as const,\n enforce: 'post' as const,\n // Capture the resolved outDir\n configResolved(config: any) {\n outDir = (config?.build?.outDir as string) || outDir\n },\n generateBundle() {\n try {\n const hdrPath = path.join(outDir, '_headers')\n if (fs.existsSync(hdrPath)) {\n // Do not override existing headers; leave a note in build logs\n console.warn('[tatchi] _headers already exists in outDir; skipping auto-emission')\n } else {\n // Strict CSP is emitted only for wallet HTML routes; not for app pages.\n const contentLines: string[] = [\n '/*',\n ...(coopMode === 'off' ? [] : [` Cross-Origin-Opener-Policy: ${coopMode}`]),\n ...(coepMode === 'off'\n ? []\n : [\n ' Cross-Origin-Embedder-Policy: require-corp',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ]),\n ` Permissions-Policy: ${permissionsPolicy}`,\n '',\n `${walletServicePath}`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n // Always allow COEP=require-corp apps to embed wallet HTML, even when\n // the wallet host itself is not using COEP.\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n `${walletServicePath}/`,\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n ` Content-Security-Policy: ${walletCsp}`,\n '/export-viewer',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n '/export-viewer/',\n ' Cross-Origin-Opener-Policy: unsafe-none',\n ' Cross-Origin-Resource-Policy: cross-origin',\n ` Permissions-Policy: ${permissionsPolicy}`,\n // Offline export cache policy (no-cache for HTML/SW; immutable for other assets)\n '/offline-export',\n ' Cache-Control: no-cache',\n '/offline-export/',\n ' Cache-Control: no-cache',\n '/offline-export/index.html',\n ' Cache-Control: no-cache',\n '/offline-export/sw.js',\n ' Cache-Control: no-cache',\n '/offline-export/precache.manifest.json',\n ' Cache-Control: no-cache',\n '/offline-export/manifest.webmanifest',\n ' Cache-Control: no-cache',\n '/offline-export/offline-export-app.js',\n ' Cache-Control: no-cache',\n '/offline-export/*',\n ' Cache-Control: public, max-age=31536000, immutable',\n ]\n // Optional: emit CORS headers when explicitly configured via plugin option.\n // Prefer a single source of truth (platform or plugin), not both.\n const configuredAcaOrigin = (opts.cors && typeof opts.cors.accessControlAllowOrigin === 'string'\n ? opts.cors.accessControlAllowOrigin.trim()\n : undefined) as string | undefined;\n if (configuredAcaOrigin) {\n contentLines.push(\n `${sdkBasePath}/*`,\n ` Access-Control-Allow-Origin: ${configuredAcaOrigin}`,\n )\n }\n const content = contentLines.join('\\n') + '\\n'\n fs.mkdirSync(outDir, { recursive: true })\n fs.writeFileSync(hdrPath, content, 'utf-8')\n console.log('[tatchi] emitted _headers with COOP' + (coepMode === 'off' ? '' : '/COEP/CORP') + ' + Permissions-Policy' + (configuredAcaOrigin ? ' + CORS' : ''))\n }\n\n const sdkDir = path.join(outDir, sdkBasePath.replace(/^\\//, ''))\n try { fs.mkdirSync(sdkDir, { recursive: true }) } catch {}\n const shimPath = path.join(sdkDir, 'wallet-shims.js')\n if (!fs.existsSync(shimPath)) {\n fs.writeFileSync(shimPath, WALLET_SHIM_SOURCE, 'utf-8')\n }\n const cssPath = path.join(sdkDir, 'wallet-service.css')\n if (!fs.existsSync(cssPath)) {\n fs.writeFileSync(cssPath, WALLET_SURFACE_CSS, 'utf-8')\n }\n\n // Emit minimal wallet-service/index.html if the app hasn't provided one\n const walletRel = walletServicePath.replace(/^\\//, '')\n const wsDir = path.join(outDir, walletRel)\n const wsHtml = path.join(wsDir, 'index.html')\n if (!fs.existsSync(wsHtml)) {\n fs.mkdirSync(wsDir, { recursive: true })\n fs.writeFileSync(wsHtml, buildWalletServiceHtml(sdkBasePath), 'utf-8')\n console.log(`[tatchi] emitted ${path.posix.join('/', walletRel, 'index.html')} (minimal wallet service)`)\n }\n\n // Emit minimal export viewer HTML for production\n const evDir = path.join(outDir, 'export-viewer')\n const evHtml = path.join(evDir, 'index.html')\n if (!fs.existsSync(evHtml)) {\n fs.mkdirSync(evDir, { recursive: true })\n fs.writeFileSync(evHtml, buildExportViewerHtml(sdkBasePath), 'utf-8')\n console.log('[tatchi] emitted /export-viewer/index.html (minimal export viewer)')\n }\n\n // Emit offline-export assets (SW, workers, app, HTML, manifest, precache) via helper\n try {\n const sdkDistRoot = resolveSdkDistRoot()\n emitOfflineExportAssets({ outDir, sdkBasePath, sdkDistRoot })\n } catch (e) {\n console.warn('[tatchi] failed to emit offline-export assets:', e)\n }\n } catch (e) {\n console.warn('[tatchi] failed to emit _headers:', e)\n }\n },\n }\n\n return plugin as unknown as VitePlugin\n}\n\n// Small test helpers to keep unit tests decoupled from Vite server implementation\nexport function computeDevPermissionsPolicy(walletOrigins?: string[]): string {\n return buildPermissionsPolicy(walletOrigins)\n}\n\nexport function computeDevWalletCsp(mode: 'strict' | 'compatible' = 'strict'): string {\n return buildWalletCsp({ mode })\n}\n\nexport function tatchiWalletServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'wallet-only' })\n}\n\nexport function tatchiAppServer(options: Omit<Web3AuthnDevOptions, 'mode'> = {}): VitePlugin {\n return tatchiDevServer({ ...options, mode: 'front-only' })\n}\n\n/**\n * Convenience wrapper: app origin helper that combines dev-time headers with optional\n * build-time headers emission for static hosts.\n *\n * Dev-time (serve): applies COOP + Permissions-Policy, plus optional COEP/CORP, via tatchiAppServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP` (defaults to `same-origin-allow-popups`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid surprising overrides when apps\n * already manage headers via custom servers or platform rules.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiApp(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const app = tatchiAppServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders\n ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode, coopMode: devOpts.coopMode })\n : undefined\n return [app, hdr].filter(Boolean) as any[]\n}\n\n/**\n * Convenience wrapper: wallet origins helper that combines dev-time wallet server\n * with optional build-time headers emission for static hosts.\n *\n * Dev-time (serve): serves `/wallet-service` and `/sdk/*` plus headers via tatchiWalletServer.\n * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify\n * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to\n * wallet HTML routes only.\n * - Emits: `COOP` on app routes (defaults to `same-origin-allow-popups`; wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.\n * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).\n *\n * Notes\n * - Keeps production header emission opt-in to avoid overriding platform/server configs.\n * - Returns a plugin array for ergonomics; Vite accepts arrays in the `plugins` list.\n */\nexport function tatchiWallet(options: Omit<Web3AuthnDevOptions, 'mode'> & { emitHeaders?: boolean } = {}): any[] /* Vite Plugin[] */ {\n const { emitHeaders, ...devOpts } = options\n const walletOrigins = normalizeWalletOrigins(\n devOpts.walletOrigins ?? parseWalletOriginsEnv(process.env.VITE_WALLET_ORIGIN)\n )\n const wallet = tatchiWalletServer(devOpts)\n // Build-time emission is opt-in and will no-op if `_headers` already exists.\n const hdr = emitHeaders\n ? tatchiBuildHeaders({ walletOrigins, coepMode: devOpts.coepMode, coopMode: devOpts.coopMode })\n : undefined\n return [wallet, hdr].filter(Boolean) as any[]\n}\n"],"mappings":"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"}
@@ -13,6 +13,8 @@ export type Web3AuthnDevOptions = {
13
13
  walletOrigins?: string[];
14
14
  setDevHeaders?: boolean;
15
15
  enableDebugRoutes?: boolean;
16
+ /** See DevHeadersOptions.coopMode */
17
+ coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups';
16
18
  /**
17
19
  * Controls Cross-Origin-Embedder-Policy (COEP) behavior in dev.
18
20
  * - 'off' (default): do not emit COEP/CORP on app pages.
@@ -38,6 +40,18 @@ export type DevHeadersOptions = {
38
40
  walletOrigins?: string[];
39
41
  walletServicePath?: string;
40
42
  sdkBasePath?: string;
43
+ /**
44
+ * Controls Cross-Origin-Opener-Policy (COOP) behavior.
45
+ *
46
+ * COOP can break popup-based third-party wallet flows by severing `window.opener`
47
+ * when set to `same-origin`. Prefer `same-origin-allow-popups` if you need COOP
48
+ * but still rely on popups.
49
+ *
50
+ * - 'off': do not emit COOP on app routes (wallet HTML routes still use `unsafe-none`)
51
+ * - 'same-origin': strict isolation (may break other wallets)
52
+ * - 'same-origin-allow-popups': more compatible with popup flows
53
+ */
54
+ coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups';
41
55
  /**
42
56
  * Optional dev-time CSP for the wallet service route.
43
57
  * - 'strict': no inline scripts/styles (mirrors production defaults)
@@ -88,6 +102,7 @@ export declare function tatchiBuildHeaders(opts?: {
88
102
  accessControlAllowOrigin?: string;
89
103
  };
90
104
  coepMode?: 'strict' | 'off';
105
+ coopMode?: 'off' | 'same-origin' | 'same-origin-allow-popups';
91
106
  }): VitePlugin;
92
107
  export declare function computeDevPermissionsPolicy(walletOrigins?: string[]): string;
93
108
  export declare function computeDevWalletCsp(mode?: 'strict' | 'compatible'): string;
@@ -101,7 +116,7 @@ export declare function tatchiAppServer(options?: Omit<Web3AuthnDevOptions, 'mod
101
116
  * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify
102
117
  * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to
103
118
  * wallet HTML routes only.
104
- * - Emits: `COOP: same-origin`, `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
119
+ * - Emits: `COOP` (defaults to `same-origin-allow-popups`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
105
120
  * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).
106
121
  *
107
122
  * Notes
@@ -120,7 +135,7 @@ export declare function tatchiApp(options?: Omit<Web3AuthnDevOptions, 'mode'> &
120
135
  * Build-time (build): when `emitHeaders` is true, writes a Cloudflare Pages/Netlify
121
136
  * `_headers` file into Vite's `outDir` via tatchiBuildHeaders, scoping strict CSP to
122
137
  * wallet HTML routes only.
123
- * - Emits: `COOP: same-origin` (wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
138
+ * - Emits: `COOP` on app routes (defaults to `same-origin-allow-popups`; wallet HTML routes use `unsafe-none`), `Permissions-Policy: …`, and (when `coepMode === 'strict'`) `COEP: require-corp` + `CORP: cross-origin`.
124
139
  * - No-op if a `_headers` file already exists in `outDir` (avoids clobbering CI/platform rules).
125
140
  *
126
141
  * Notes
@@ -1 +1 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../../../../src/plugins/vite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../../../../src/plugins/vite.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tatchi-xyz/sdk",
3
- "version": "0.57.0",
3
+ "version": "0.58.0",
4
4
  "type": "module",
5
5
  "description": "An embedded passkey wallet SDK built on NEAR protocol",
6
6
  "main": "./dist/cjs/index.js",