@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.
- package/dist/cjs/plugins/vite.js +22 -7
- package/dist/cjs/plugins/vite.js.map +1 -1
- package/dist/esm/plugins/vite.js +22 -7
- package/dist/esm/plugins/vite.js.map +1 -1
- package/dist/esm/wasm_signer_worker/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/types/src/plugins/vite.d.ts +17 -2
- package/dist/types/src/plugins/vite.d.ts.map +1 -1
- package/dist/workers/wasm_signer_worker_bg.wasm +0 -0
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/package.json +1 -1
package/dist/cjs/plugins/vite.js
CHANGED
|
@@ -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",
|
|
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:
|
|
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
|
|
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
|
|
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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"}
|
package/dist/esm/plugins/vite.js
CHANGED
|
@@ -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",
|
|
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:
|
|
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
|
|
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
|
|
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":";;;;;;;;AAmGA,SAAS,uBAAuB,eAAoC;AAClE,KAAI,CAAC,MAAM,QAAQ,kBAAkB,cAAc,WAAW,EAAG,QAAO;CACxE,MAAMA,MAAgB;CACtB,MAAM,uBAAO,IAAI;AACjB,MAAK,MAAM,UAAU,eAAe;EAClC,MAAM,aAAa,oBAAoB;AACvC,MAAI,CAAC,cAAc,KAAK,IAAI,YAAa;AACzC,OAAK,IAAI;AACT,MAAI,KAAK;;AAEX,QAAO;;AAGT,SAAS,sBAAsB,OAAsC;AACnE,KAAI,OAAO,UAAU,SAAU,QAAO;CACtC,MAAM,MAAM,MAAM;AAClB,KAAI,CAAC,IAAK,QAAO;CACjB,MAAM,QAAQ,IAAI,MAAM,UAAU,KAAK,MAAM,EAAE,QAAQ,OAAO;CAC9D,MAAM,UAAU,uBAAuB;AACvC,QAAO,QAAQ,SAAS,UAAU;;AAGpC,SAAS,gBAAgB,UAAmH;AAC1I,KAAI,aAAa,SAAS,aAAa,iBAAiB,aAAa,2BAA4B,QAAO;CACxG,MAAM,MAAM,OAAQ,YAAoB,SAAS,KAAK,kBAAkB,IAAI,OAAO;AACnF,KAAI,QAAQ,SAAS,QAAQ,OAAO,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9E,KAAI,QAAQ,8BAA8B,QAAQ,eAAgB,QAAO;AACzE,KAAI,QAAQ,iBAAiB,QAAQ,YAAY,QAAQ,IAAK,QAAO;AAErE,QAAO;;;;;;AAOT,SAAS,QAAQ,GAAG,YAA0C;AAC5D,MAAK,MAAM,QAAQ,WACjB,KAAI;EACF,MAAM,OAAO,GAAG,SAAS;AACzB,MAAI,KAAK,SAAU,QAAO;SACpB;AAEV,QAAO;;AAIT,SAAS,0BAA0B,QAAmB;CACpD,MAAM,SAAS,QAAQ;CACvB,MAAM,WAAW,QAAQ;CACzB,MAAM,WAAW,QAAQ,QAAQ;CACjC,MAAM,QAAQ,UAAU;AACxB,KAAI,CAAC,YAAY,UAAU,WAAW,SAAS,CAAC,MAAM,QAAQ,OAAQ;CAEtE,MAAM,cAAc,KAAK,QAAQ,OAAO;AACxC,KAAI,CAAC,MAAM,MAAM,MAAW,KAAK,QAAQ,OAAO,QAAQ,aACtD,OAAM,KAAK;;AAKf,MAAM,qBAAqB;AAC3B,MAAM,qBAAqB;CACzB;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CAIA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;EACA,KAAK;;;;;;;AAQP,SAAgB,eAAe,OAAwB,IAAgB;CACrE,MAAM,iBAAiB,WAAW,KAAK,aAAa;CACpD,MAAM,cAAc,mBAAmB,KAAK;CAC5C,MAAM,oBAAoB,KAAK,sBAAsB;CACrD,MAAM,WAAW,gBAAgB,KAAK;CACtC,MAAM,cAAc,uBAAuB;CAG3C,MAAM,QAAQ,MAAM,KAAK,IAAI,IAAI,CAAC,gBAAgB,WAAW,WAC1D,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE;AAG/B,QAAO;EACL,MAAM;EACN,OAAO;EACP,SAAS;EACT,gBAAgB,QAAQ;AACtB,6BAA0B;AAG1B,6BAA0B,QAAQ;IAChC;IACA,aAAa;IACb;IACA,kBAAkB;IAClB;;AAGF,UAAO,YAAY,KAAK,KAAU,KAAU,SAAc;IACxD,MAAM,OAAO,IAAI,OAAO,IAAI,MAAM,KAAK;AACvC,QAAI,QAAQ,iBAAiB,oBAAoB;AAC/C,SAAI,aAAa;AACjB,SAAI,UAAU,gBAAgB;AAE9B,2BAAsB,KAAK;AAE3B,yBAAoB,KAAK,KAAK,EAAE,iBAAiB;AACjD,SAAI,IAAI;AACR;;AAEF,QAAI,QAAQ,iBAAiB,uBAAuB;AAClD,SAAI,aAAa;AACjB,SAAI,UAAU,gBAAgB;AAE9B,2BAAsB,KAAK;AAE3B,yBAAoB,KAAK,KAAK,EAAE,iBAAiB;AACjD,SAAI,IAAI;AACR;;AAEF;;AAIF,OAAI,kBACF,QAAO,YAAY,IAAI,gBAAgB,KAAU,QAAa;AAC5D,QAAI,UAAU,gBAAgB;AAC9B,QAAI,IAAI;;AAKZ,UAAO,YAAY,KAAK,KAAU,KAAU,SAAc;AACxD,QAAI,CAAC,IAAI,IAAK,QAAO;IACrB,MAAM,MAAM,IAAI,IAAI,MAAM,KAAK;IAE/B,MAAM,YAAY,MAAM,MAAM,MAAM,IAAI,WAAW,IAAI;AACvD,QAAI,CAAC,UAAW,QAAO;IAEvB,MAAM,MAAM,IAAI,OAAO,YAAY,KAAK;IAExC,MAAM,YAAY,QAChB,KAAK,KAAK,aAAa,OAAO,OAAO,MACrC,KAAK,KAAK,aAAa,MACvB,KAAK,KAAK,aAAa,OAAO;AAGhC,QAAI,CAAC,WAAW;AACd,SAAI,aAAa;AACjB,SAAI,UAAU,gBAAgB;AAC9B,SAAI,IAAI,KAAK,UAAU;MAAE,OAAO;MAAuB,MAAM;;AAC7D;;AAGF,mBAAe,KAAK;AAEpB,0BAAsB,KAAK;AAE3B,wBAAoB,KAAK,KAAK,EAAE,iBAAiB;IACjD,MAAM,SAAS,GAAG,iBAAiB;AACnC,WAAO,GAAG,eAAe;AACzB,WAAO,KAAK;;;;;;;;;AAUpB,SAAgB,oBAAoB,OAA6B,IAAgB;CAC/E,MAAM,oBAAoB,WAAW,KAAK,mBAAmB;CAC7D,MAAM,cAAc,WAAW,KAAK,aAAa;CACjD,MAAM,WAAW,gBAAgB,KAAK;CAEtC,MAAM,OAAO,uBAAuB;CACpC,MAAM,cAAc,uBAAuB;CAC3C,MAAM,cAAc;AAEpB,QAAO;EACL,MAAM;EACN,OAAO;EACP,SAAS;EACT,gBAAgB,QAAQ;AACtB,6BAA0B;AAE1B,UAAO,YAAY,KAAK,KAAU,KAAU,SAAc;AACxD,QAAI,CAAC,IAAI,IAAK,QAAO;IACrB,MAAM,MAAM,IAAI,IAAI,MAAM,KAAK;IAC/B,MAAM,gBAAgB,QAAQ,qBAAqB,QAAQ,GAAG,kBAAkB,MAAM,QAAQ,GAAG,kBAAkB;AACnH,QAAI,eAAe;AACjB,SAAI,aAAa;AACjB,SAAI,UAAU,gBAAgB;AAK9B,SAAI,UAAU,gCAAgC;AAC9C,2BAAsB,KAAK;AAC3B,SAAI,IAAI;AACR;;AAEF;;AAIF,6BAA0B,QAAQ;IAChC;IACA;IACA;IACA,kBAAkB;IAClB;;;;;;;;;AAUR,SAAgB,iBAA6B;AAC3C,QAAO;EACL,MAAM;EACN,OAAO;EACP,SAAS;EACT,gBAAgB,QAAQ;AACtB,6BAA0B;AAE1B,UAAO,YAAY,KAAK,KAAU,KAAU,SAAc;AACxD,QAAI,CAAC,IAAI,IAAK,QAAO;IACrB,MAAM,MAAM,IAAI,IAAI,MAAM,KAAK;AAC/B,QAAI,IAAI,SAAS,SACf,KAAI,UAAU,gBAAgB;AAEhC;;;;;;;;;;;;AAaR,SAAgB,cAAc,OAA0B,IAAgB;CACtE,MAAM,gBAAgB,uBACpB,KAAK,iBAAiB,sBAAsB,QAAQ,IAAI;CAE1D,MAAM,oBAAoB,WAAW,KAAK,qBAAqB,QAAQ,IAAI,0BAA0B;CACrG,MAAM,cAAc,WAAW,KAAK,eAAe,QAAQ,IAAI,oBAAoB;CACnF,MAAM,aAAc,KAAK,UAAW,QAAQ,IAAI;CAChD,MAAM,WAAW,gBAAgB,KAAK;CACtC,MAAM,WAAW,gBAAgB,KAAK;CAGtC,MAAM,oBAAoB,uBAAuB;CAIjD,MAAM,iBAAiB,QAAQ,IAAI,6BAA6B,IAAI,WAAW;CAC/E,MAAM,aAAa,QAAQ,IAAI,mBAAmB,uBAAuB,WAAW;CACpF,MAAM,cAAc,QAAQ,IAAI,qBAAqB,iCAAiC,WAAW;AAGjG,QAAO;EACL,MAAM;EACN,OAAO;EACP,SAAS;EACT,gBAAgB,QAAQ;AACtB,6BAA0B;AAE1B,WAAQ,IAAI,4BAA4B;IACtC;IACA;IACA;IACA,eAAe,iBAAiB;IAChC;;AAGF,UAAO,YAAY,KAAK,KAAU,KAAU,SAAc;IACxD,MAAM,OAAO,IAAI,OAAO,IAAI,MAAM,KAAK,MAAM;IAC7C,MAAM,gBAAgB,QAAQ,qBAAqB,QAAQ,GAAG,kBAAkB,MAAM,QAAQ,GAAG,kBAAkB;AACnH,QAAI,cACF,KAAI,UAAU,8BAA8B;aACnC,aAAa,MACtB,KAAI,UAAU,8BAA8B;AAE9C,QAAI,aAAa,OAAO;AACtB,SAAI,UAAU,gCAAgC;AAC9C,SAAI,UAAU,gCAAgC;;AAEhD,QAAI,UAAU,sBAAsB;AAEpC,QAAI,iBAAiB,YAAY;KAC/B,MAAM,OAAO,eAAe,WAAW,WAAW;KAClD,MAAM,YAAY,eAAe,EAAE;AACnC,SAAI,UAAU,2BAA2B;;AAG3C,sBAAkB,KAAK;IAGvB,MAAM,cAAc,QAAQ,2BAA2B,QAAQ;AAC/D,QAAI,aAAa;AAGf,SAAI,eAAe;AAChB,OAAC,YAAY;AACZ,WAAI;QACF,MAAM,UAAU,MAAM,wBAAwB;SAC5C,QAAQ;SACR,YAAY;SACZ,QAAQ;;AAEV,YAAI,aAAa;AACjB,YAAI,UAAU,gBAAgB;AAC9B,YAAI,UAAU,iBAAiB;AAC/B,YAAI,IAAI,KAAK,UAAU,EAAE;gBAClB,GAAG;AACV,gBAAQ,KAAK,sCAAsC;AACnD,YAAI,aAAa;AACjB,YAAI,UAAU,gBAAgB;AAC9B,YAAI,UAAU,iBAAiB;AAC/B,YAAI,IAAI,KAAK,UAAU,EAAE,SAAS;;;AAGtC;;AAGF,SAAI,aAAa;AACjB,SAAI,UAAU,gBAAgB;AAC9B,SAAI,UAAU,iBAAiB;AAC/B,SAAI,IAAI,KAAK,UAAU,EAAE,SAAS;AAClC;;AAGF,QAAI,IAAI,WAAW,GAAG,YAAY,KAAK;AAErC,2BAAsB,KAAK;KAE3B,MAAM,QAAQ,oBAAoB,KAAK,KAAK;MAAE,wBAAwB;MAAM,iBAAiB;;AAC7F,SAAI,MAAO;;AAEb;;;;;;;;;;;;;;;;AAiBR,SAAS,gBAAgB,UAA+B,IAAgB;CACtE,MAAMC,OAA8C,QAAQ,QAAQ;CACpE,MAAM,cAAc,WAAW,QAAQ,eAAe,QAAQ,IAAI,oBAAoB;CACtF,MAAM,oBAAoB,WAAW,QAAQ,qBAAqB,QAAQ,IAAI,0BAA0B;CACxG,MAAM,gBAAgB,uBACpB,QAAQ,iBAAiB,sBAAsB,QAAQ,IAAI;CAE7D,MAAM,gBAAgB,QAAQ,kBAAkB;CAChD,MAAM,oBAAoB,QAAQ,sBAAsB;CACxD,MAAM,cAAc,mBAAmB,QAAQ;CAC/C,MAAM,WAAW,gBAAgB,QAAQ;CACzC,MAAM,WAAW,QAAQ;CAGzB,MAAM,YAAY,eAAe;EAAE;EAAa;EAAa;EAAmB;;CAChF,MAAM,eAAe,oBAAoB;EAAE;EAAmB;EAAa;;CAC3E,MAAM,iBAAiB;CAGvB,MAAM,gBAAgB,gBAClB,cAAc;EAAE;EAAe;EAAmB;EAAa,QAAQ;EAAU;EAAU;MAC3F;AAEJ,QAAO;EACL,MAAM;EACN,OAAO;EACP,SAAS;EACT,gBAAgB,QAAQ;AACtB,6BAA0B;AAG1B,aAAU,kBAAkB;AAC5B,kBAAe,kBAAkB;AACjC,OAAI,cAAe,eAAc,kBAAkB;AAGnD,OAAI,SAAS,oBAAoB,SAAS,cACxC,cAAa,kBAAkB;;;;;;;;;;AAgBvC,SAAgB,mBAAmB,OAK/B,IAAgB;CAClB,MAAM,gBAAgB,uBACpB,KAAK,iBAAiB,sBAAsB,QAAQ,IAAI;CAE1D,MAAM,oBAAoB,WAAW,QAAQ,IAAI,0BAA0B;CAC3E,MAAM,cAAc,WAAW,QAAQ,IAAI,oBAAoB;CAC/D,MAAM,WAAW,gBAAgB,KAAK;CACtC,MAAM,WAAW,gBAAgB,KAAK;CAGtC,MAAM,oBAAoB,uBAAuB;CACjD,MAAM,YAAY,eAAe,EAAE,MAAM;CAEzC,IAAI,SAAS;CAGb,MAAM,SAAS;EACb,MAAM;EACN,OAAO;EACP,SAAS;EAET,eAAe,QAAa;AAC1B,YAAU,QAAQ,OAAO,UAAqB;;EAEhD,iBAAiB;AACf,OAAI;IACF,MAAM,UAAU,KAAK,KAAK,QAAQ;AAClC,QAAI,GAAG,WAAW,SAEhB,SAAQ,KAAK;SACR;KAEL,MAAMC,eAAyB;MAC7B;MACA,GAAI,aAAa,QAAQ,KAAK,CAAC,iCAAiC;MAChE,GAAI,aAAa,QACb,KACA,CACE,gDACA;MAEN,yBAAyB;MACzB;MACA,GAAG;MACH;MAGA;MACA,yBAAyB;MACzB,8BAA8B;MAC9B,GAAG,kBAAkB;MACrB;MACA;MACA,yBAAyB;MACzB,8BAA8B;MAC9B;MACA;MACA;MACA,yBAAyB;MACzB;MACA;MACA;MACA,yBAAyB;MAEzB;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;KAIF,MAAM,sBAAuB,KAAK,QAAQ,OAAO,KAAK,KAAK,6BAA6B,WACpF,KAAK,KAAK,yBAAyB,SACnC;AACJ,SAAI,oBACF,cAAa,KACX,GAAG,YAAY,KACf,kCAAkC;KAGtC,MAAM,UAAU,aAAa,KAAK,QAAQ;AAC1C,QAAG,UAAU,QAAQ,EAAE,WAAW;AAClC,QAAG,cAAc,SAAS,SAAS;AACnC,aAAQ,IAAI,yCAAyC,aAAa,QAAQ,KAAK,gBAAgB,2BAA2B,sBAAsB,YAAY;;IAG9J,MAAM,SAAS,KAAK,KAAK,QAAQ,YAAY,QAAQ,OAAO;AAC5D,QAAI;AAAE,QAAG,UAAU,QAAQ,EAAE,WAAW;YAAgB;IACxD,MAAM,WAAW,KAAK,KAAK,QAAQ;AACnC,QAAI,CAAC,GAAG,WAAW,UACjB,IAAG,cAAc,UAAU,oBAAoB;IAEjD,MAAM,UAAU,KAAK,KAAK,QAAQ;AAClC,QAAI,CAAC,GAAG,WAAW,SACjB,IAAG,cAAc,SAAS,oBAAoB;IAIhD,MAAM,YAAY,kBAAkB,QAAQ,OAAO;IACnD,MAAM,QAAQ,KAAK,KAAK,QAAQ;IAChC,MAAM,SAAS,KAAK,KAAK,OAAO;AAChC,QAAI,CAAC,GAAG,WAAW,SAAS;AAC1B,QAAG,UAAU,OAAO,EAAE,WAAW;AACjC,QAAG,cAAc,QAAQ,uBAAuB,cAAc;AAC9D,aAAQ,IAAI,oBAAoB,KAAK,MAAM,KAAK,KAAK,WAAW,cAAc;;IAIhF,MAAM,QAAQ,KAAK,KAAK,QAAQ;IAChC,MAAM,SAAS,KAAK,KAAK,OAAO;AAChC,QAAI,CAAC,GAAG,WAAW,SAAS;AAC1B,QAAG,UAAU,OAAO,EAAE,WAAW;AACjC,QAAG,cAAc,QAAQ,sBAAsB,cAAc;AAC7D,aAAQ,IAAI;;AAId,QAAI;KACF,MAAM,cAAc;AACpB,6BAAwB;MAAE;MAAQ;MAAa;;aACxC,GAAG;AACV,aAAQ,KAAK,kDAAkD;;YAE1D,GAAG;AACV,YAAQ,KAAK,qCAAqC;;;;AAKxD,QAAO;;AAIT,SAAgB,4BAA4B,eAAkC;AAC5E,QAAO,uBAAuB;;AAGhC,SAAgB,oBAAoB,OAAgC,UAAkB;AACpF,QAAO,eAAe,EAAE;;AAG1B,SAAgB,mBAAmB,UAA6C,IAAgB;AAC9F,QAAO,gBAAgB;EAAE,GAAG;EAAS,MAAM;;;AAG7C,SAAgB,gBAAgB,UAA6C,IAAgB;AAC3F,QAAO,gBAAgB;EAAE,GAAG;EAAS,MAAM;;;;;;;;;;;;;;;;;;;AAmB7C,SAAgB,UAAU,UAAyE,IAA+B;CAChI,MAAM,EAAE,YAAa,GAAG,YAAY;CACpC,MAAM,gBAAgB,uBACpB,QAAQ,iBAAiB,sBAAsB,QAAQ,IAAI;CAE7D,MAAM,MAAM,gBAAgB;CAE5B,MAAM,MAAM,cACR,mBAAmB;EAAE;EAAe,UAAU,QAAQ;EAAU,UAAU,QAAQ;MAClF;AACJ,QAAO,CAAC,KAAK,KAAK,OAAO;;;;;;;;;;;;;;;;;AAkB3B,SAAgB,aAAa,UAAyE,IAA+B;CACnI,MAAM,EAAE,YAAa,GAAG,YAAY;CACpC,MAAM,gBAAgB,uBACpB,QAAQ,iBAAiB,sBAAsB,QAAQ,IAAI;CAE7D,MAAM,SAAS,mBAAmB;CAElC,MAAM,MAAM,cACR,mBAAmB;EAAE;EAAe,UAAU,QAAQ;EAAU,UAAU,QAAQ;MAClF;AACJ,QAAO,CAAC,QAAQ,KAAK,OAAO"}
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
|
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
|
|
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":"AA2BA,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IACzB,OAAO,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACxD,CAAA;AACD,MAAM,MAAM,cAAc,GAAG,UAAU,CAAA;AAEvC,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,gBAAgB,GAAG,YAAY,GAAG,aAAa,CAAA;IACtD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAA;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;CAC5B,CAAA;
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../../../../src/plugins/vite.ts"],"names":[],"mappings":"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"}
|
|
Binary file
|
|
Binary file
|