punchout-simulator 0.1.5 → 0.3.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.
Files changed (23) hide show
  1. package/README.md +95 -12
  2. package/dist/server/cli.js +931 -297
  3. package/dist/web/assets/{cssMode-WA7HerFP.js → cssMode-UKotGf5X.js} +1 -1
  4. package/dist/web/assets/{freemarker2-BTOdUHiQ.js → freemarker2-0DRATxLT.js} +1 -1
  5. package/dist/web/assets/{handlebars-DdTiW10M.js → handlebars-U7ip3Hjn.js} +1 -1
  6. package/dist/web/assets/{html-CP7qpuUD.js → html-pMwW-Db1.js} +1 -1
  7. package/dist/web/assets/{htmlMode-BG3HQ1Sh.js → htmlMode-BZiR_DER.js} +1 -1
  8. package/dist/web/assets/{index-DQ_OSoxK.js → index-fwAo3vG0.js} +204 -204
  9. package/dist/web/assets/{index-CRWJsM13.css → index-sN4D-IAg.css} +1 -1
  10. package/dist/web/assets/{javascript-IQKq-LZB.js → javascript-BNQzFVRF.js} +1 -1
  11. package/dist/web/assets/{jsonMode-B1p3z-UY.js → jsonMode-CSAIHDlB.js} +1 -1
  12. package/dist/web/assets/{liquid-4Fxw7q97.js → liquid--vvS9GUJ.js} +1 -1
  13. package/dist/web/assets/{mdx-00dxYvhf.js → mdx-BJDQflEF.js} +1 -1
  14. package/dist/web/assets/{python-BI6CPDlf.js → python-CepodNht.js} +1 -1
  15. package/dist/web/assets/{razor-DGRBM6nC.js → razor-BQksENSs.js} +1 -1
  16. package/dist/web/assets/{tsMode-BVtwLDYC.js → tsMode-BRKq1Rx4.js} +1 -1
  17. package/dist/web/assets/{typescript-Dgh1yWP4.js → typescript-V-bP8GlZ.js} +1 -1
  18. package/dist/web/assets/{xml-BOb15_Cq.js → xml-Bgme81_M.js} +1 -1
  19. package/dist/web/assets/{yaml-Dv2aUhkS.js → yaml-CkpLYd3y.js} +1 -1
  20. package/dist/web/favicon.svg +8 -0
  21. package/dist/web/index.html +12 -2
  22. package/package.json +1 -1
  23. package/dist/server/cli.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import{conf as t,language as e}from"./typescript-Dgh1yWP4.js";import"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{conf as t,language as e}from"./typescript-V-bP8GlZ.js";import"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m as Et}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m as Et}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m as l}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m as l}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m as s}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m as s}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m as o}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m as o}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{t as O,m as I}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{t as O,m as I}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m as s}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m as s}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m as r}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m as r}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -1,4 +1,4 @@
1
- import{m as l}from"./index-DQ_OSoxK.js";/*!-----------------------------------------------------------------------------
1
+ import{m as l}from"./index-fwAo3vG0.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <rect width="32" height="32" rx="7" fill="#0f172a"/>
3
+ <!-- OUT ↑ (magenta) and IN ↓ (cyan): the bidirectional PunchOut exchange. -->
4
+ <g fill="none" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round">
5
+ <path d="M11 22 V11 M7.5 14.5 L11 11 L14.5 14.5" stroke="#f0abfc"/>
6
+ <path d="M21 10 V21 M17.5 17.5 L21 21 L24.5 17.5" stroke="#67e8f9"/>
7
+ </g>
8
+ </svg>
@@ -3,9 +3,19 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="icon" type="image/svg+xml" href="./favicon.svg" />
7
+ <script>
8
+ // Apply the saved (or OS-preferred) theme before first paint to avoid a flash.
9
+ try {
10
+ var t = localStorage.getItem("pos-theme");
11
+ if (t !== "dark" && t !== "light")
12
+ t = matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
13
+ document.documentElement.dataset.theme = t;
14
+ } catch (e) {}
15
+ </script>
6
16
  <title>punchout-simulator</title>
7
- <script type="module" crossorigin src="./assets/index-DQ_OSoxK.js"></script>
8
- <link rel="stylesheet" crossorigin href="./assets/index-CRWJsM13.css">
17
+ <script type="module" crossorigin src="./assets/index-fwAo3vG0.js"></script>
18
+ <link rel="stylesheet" crossorigin href="./assets/index-sN4D-IAg.css">
9
19
  </head>
10
20
  <body>
11
21
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "punchout-simulator",
3
- "version": "0.1.5",
3
+ "version": "0.3.0",
4
4
  "description": "A developer tool for testing cXML PunchOut integrations by acting as a virtual counterparty (virtual buyer or virtual supplier).",
5
5
  "keywords": [
6
6
  "punchout",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/server/cli.ts","../../src/server/app.ts","../../src/server/routes/connections.ts","../../src/server/store/config.ts","../../src/server/store/paths.ts","../../src/server/routes/flow.ts","../../src/server/store/log.ts","../../src/server/bus.ts","../../src/server/store/attachments.ts","../../src/server/cxml/multipart.ts","../../src/server/cart-store.ts","../../src/server/http.ts","../../src/server/runtime.ts","../../src/server/cxml/build.ts","../../src/server/cxml/parse.ts","../../src/server/cxml/validate.ts","../../src/server/routes/punchout-return.ts","../../src/server/routes/stream.ts","../../src/server/routes/data.ts","../../src/server/routes/sim.ts","../../src/server/seed.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { serve } from \"@hono/node-server\";\nimport { createApp } from \"./app.js\";\nimport { initConfig } from \"./store/config.js\";\nimport { setDataDir } from \"./store/paths.js\";\nimport { setRuntime, getPublicUrl } from \"./runtime.js\";\nimport { seedDemoIfEmpty } from \"./seed.js\";\n\n// CLI entry (spec section 9): boot Hono, serve the built SPA, open the browser.\n// Flags: --port, --data-dir, --public-url, --no-open, --dev, --no-seed.\n\ninterface Flags {\n port: number;\n dataDir: string;\n publicUrl?: string;\n open: boolean;\n dev: boolean;\n seed: boolean;\n}\n\nfunction parseFlags(argv: string[]): Flags {\n const flags: Flags = {\n port: Number(process.env.PORT ?? 8080),\n dataDir: process.env.DATA_DIR ?? \"./data\",\n open: true,\n dev: false,\n seed: true,\n };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n const next = () => argv[++i];\n switch (a) {\n case \"--port\":\n case \"-p\":\n flags.port = Number(next());\n break;\n case \"--data-dir\":\n case \"-d\":\n flags.dataDir = next();\n break;\n case \"--public-url\":\n flags.publicUrl = next();\n break;\n case \"--no-open\":\n flags.open = false;\n break;\n case \"--dev\":\n flags.dev = true;\n flags.open = false;\n break;\n case \"--no-seed\":\n flags.seed = false;\n break;\n case \"--help\":\n case \"-h\":\n printHelp();\n process.exit(0);\n }\n }\n return flags;\n}\n\nfunction printHelp(): void {\n console.log(`punchout-simulator — test cXML PunchOut integrations as a virtual counterparty\n\nUsage: punchout-simulator [options]\n\nOptions:\n -p, --port <n> Port to listen on (default 8080)\n -d, --data-dir <path> Where to store config + logs (default ./data)\n --public-url <url> Externally reachable base URL (default http://localhost:<port>)\n Set this when fronting the tool with ngrok/cloudflared.\n --no-open Do not open a browser on start\n --no-seed Do not seed the built-in demo connections on first run\n --dev Dev mode (do not serve SPA, do not open browser)\n -h, --help Show this help\n`);\n}\n\nasync function main() {\n const flags = parseFlags(process.argv.slice(2));\n const publicUrl = flags.publicUrl ?? `http://localhost:${flags.port}`;\n\n setDataDir(flags.dataDir);\n setRuntime({ port: flags.port, publicUrl });\n await initConfig();\n if (flags.seed) await seedDemoIfEmpty();\n\n const webRoot = flags.dev\n ? undefined\n : fileURLToPath(new URL(\"../web\", import.meta.url));\n\n const app = createApp({ webRoot, quiet: false });\n\n serve({ fetch: app.fetch, port: flags.port }, (info) => {\n const url = `http://localhost:${info.port}`;\n console.log(`\\n punchout-simulator listening on ${url}`);\n if (getPublicUrl() !== url) console.log(` public URL: ${getPublicUrl()}`);\n console.log(` data dir: ${flags.dataDir}`);\n console.log(` callback: ${getPublicUrl()}/punchout/return\\n`);\n\n if (flags.open) {\n import(\"open\")\n .then((m) => m.default(url))\n .catch(() => {\n /* opening a browser is best-effort */\n });\n }\n });\n}\n\nmain().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n","import { existsSync } from \"node:fs\";\nimport { Hono } from \"hono\";\nimport { logger } from \"hono/logger\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { connectionsRoute } from \"./routes/connections.js\";\nimport { flowRoute } from \"./routes/flow.js\";\nimport { punchoutReturnRoute } from \"./routes/punchout-return.js\";\nimport { streamRoute } from \"./routes/stream.js\";\nimport { dataRoute } from \"./routes/data.js\";\nimport { simRoute } from \"./routes/sim.js\";\n\nexport interface AppOptions {\n /** Absolute path to the built SPA (dist/web). Omit in dev (Vite serves it). */\n webRoot?: string;\n quiet?: boolean;\n}\n\nexport function createApp(opts: AppOptions = {}): Hono {\n const app = new Hono();\n if (!opts.quiet) app.use(\"*\", logger());\n\n // The SPA and its own API share a single origin, so there is no CORS between\n // them (spec section 5).\n app.route(\"/api/connections\", connectionsRoute);\n app.route(\"/api/connections\", flowRoute); // /:id/setup, /:id/order\n app.route(\"/api\", dataRoute);\n app.route(\"/api\", streamRoute);\n app.route(\"/punchout\", punchoutReturnRoute); // Mode A callback\n app.route(\"/sim\", simRoute); // Mode B mock supplier\n\n // Serve the built SPA from the same server. serveStatic needs a path relative\n // to cwd, so we expose it via the `root` option when a build is present.\n if (opts.webRoot && existsSync(opts.webRoot)) {\n app.use(\n \"/*\",\n serveStatic({\n root: relativeToCwd(opts.webRoot),\n // SPA fallback: unknown non-API routes return index.html.\n rewriteRequestPath: (path) => path,\n }),\n );\n app.get(\"/*\", serveStatic({ root: relativeToCwd(opts.webRoot), path: \"index.html\" }));\n }\n\n return app;\n}\n\nimport { relative } from \"node:path\";\nfunction relativeToCwd(abs: string): string {\n const rel = relative(process.cwd(), abs);\n return rel === \"\" ? \".\" : rel;\n}\n","import { Hono } from \"hono\";\nimport {\n createConnection,\n deleteConnection,\n getConnection,\n listConnections,\n updateConnection,\n type ConnectionInput,\n} from \"../store/config.js\";\nimport type { Connection, Credential } from \"../cxml/types.js\";\n\n// CRUD for connection configs (spec section 10). Role-neutral: each connection\n// carries a `mode` so virtual-buyer (phase 1) and virtual-supplier (phase 2)\n// share the same storage.\n\nexport const connectionsRoute = new Hono();\n\nconst emptyCredential = (): Credential => ({ domain: \"\", identity: \"\" });\n\nfunction normalize(body: any): ConnectionInput {\n const cred = (c: any): Credential =>\n c && typeof c === \"object\"\n ? { domain: String(c.domain ?? \"\"), identity: String(c.identity ?? \"\") }\n : emptyCredential();\n return {\n name: String(body?.name ?? \"Untitled connection\"),\n mode: body?.mode === \"virtual-supplier\" ? \"virtual-supplier\" : \"virtual-buyer\",\n from: cred(body?.from),\n to: cred(body?.to),\n sender: cred(body?.sender),\n sharedSecret: String(body?.sharedSecret ?? \"\"),\n deploymentMode: body?.deploymentMode === \"production\" ? \"production\" : \"test\",\n authStyle: body?.authStyle === \"MAC\" ? \"MAC\" : \"SharedSecret\",\n punchoutUrl: body?.punchoutUrl ? String(body.punchoutUrl) : undefined,\n orderUrl: body?.orderUrl ? String(body.orderUrl) : undefined,\n catalog: Array.isArray(body?.catalog) ? body.catalog : undefined,\n };\n}\n\nfunction validateConnection(input: ConnectionInput): string[] {\n const errors: string[] = [];\n if (!input.name.trim()) errors.push(\"name is required\");\n if (input.mode === \"virtual-buyer\") {\n if (!input.punchoutUrl) errors.push(\"punchoutUrl is required for virtual-buyer\");\n if (!input.orderUrl) errors.push(\"orderUrl is required for virtual-buyer\");\n }\n return errors;\n}\n\nconnectionsRoute.get(\"/\", (c) => c.json(listConnections()));\n\nconnectionsRoute.post(\"/\", async (c) => {\n const input = normalize(await c.req.json().catch(() => ({})));\n const errors = validateConnection(input);\n if (errors.length) return c.json({ errors }, 400);\n const created = await createConnection(input);\n return c.json(created, 201);\n});\n\nconnectionsRoute.get(\"/:id\", (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n return conn ? c.json(conn) : c.json({ error: \"not found\" }, 404);\n});\n\nconnectionsRoute.put(\"/:id\", async (c) => {\n const id = c.req.param(\"id\");\n const existing = getConnection(id);\n if (!existing) return c.json({ error: \"not found\" }, 404);\n const merged: Connection = { ...existing, ...(await c.req.json().catch(() => ({}))) };\n const input = normalize(merged);\n const errors = validateConnection(input);\n if (errors.length) return c.json({ errors }, 400);\n const updated = await updateConnection(id, input);\n return c.json(updated);\n});\n\nconnectionsRoute.delete(\"/:id\", async (c) => {\n const ok = await deleteConnection(c.req.param(\"id\"));\n return ok ? c.json({ ok: true }) : c.json({ error: \"not found\" }, 404);\n});\n","import { Low } from \"lowdb\";\nimport { JSONFile } from \"lowdb/node\";\nimport { nanoid } from \"nanoid\";\nimport type { Connection } from \"../cxml/types.js\";\nimport { configPath, ensureDirs } from \"./paths.js\";\n\n// Connection configs live in a single config.json via lowdb (a JSON document\n// store, not relational) — mutable and tiny. The collection is role-neutral\n// (`connections`, each with a `mode`) so Mode B slots in without a rewrite.\n// See spec section 7.\n\ninterface Schema {\n connections: Connection[];\n}\n\nlet db: Low<Schema> | null = null;\n\nexport async function initConfig(): Promise<void> {\n ensureDirs();\n const adapter = new JSONFile<Schema>(configPath());\n db = new Low<Schema>(adapter, { connections: [] });\n await db.read();\n db.data ||= { connections: [] };\n await db.write();\n}\n\nfunction requireDb(): Low<Schema> {\n if (!db) throw new Error(\"config store not initialized — call initConfig() first\");\n return db;\n}\n\nexport function listConnections(): Connection[] {\n return requireDb().data.connections;\n}\n\nexport function getConnection(id: string): Connection | undefined {\n return requireDb().data.connections.find((c) => c.id === id);\n}\n\nexport type ConnectionInput = Omit<Connection, \"id\" | \"createdAt\" | \"updatedAt\"> &\n Partial<Pick<Connection, \"id\">>;\n\nexport async function createConnection(input: ConnectionInput): Promise<Connection> {\n const now = new Date().toISOString();\n const conn: Connection = {\n ...input,\n id: input.id ?? nanoid(8),\n createdAt: now,\n updatedAt: now,\n };\n const d = requireDb();\n d.data.connections.push(conn);\n await d.write();\n return conn;\n}\n\nexport async function updateConnection(\n id: string,\n patch: Partial<ConnectionInput>,\n): Promise<Connection | undefined> {\n const d = requireDb();\n const existing = d.data.connections.find((c) => c.id === id);\n if (!existing) return undefined;\n Object.assign(existing, patch, { id, updatedAt: new Date().toISOString() });\n await d.write();\n return existing;\n}\n\nexport async function deleteConnection(id: string): Promise<boolean> {\n const d = requireDb();\n const before = d.data.connections.length;\n d.data.connections = d.data.connections.filter((c) => c.id !== id);\n const removed = d.data.connections.length < before;\n if (removed) await d.write();\n return removed;\n}\n","import { mkdirSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\n// Resolves and owns the data directory layout. The CLI sets this once at boot\n// (--data-dir, default ./data). See spec section 7.\n\nlet dataDir = resolve(process.cwd(), \"data\");\n\nexport function setDataDir(dir: string): void {\n dataDir = resolve(dir);\n ensureDirs();\n}\n\nexport function getDataDir(): string {\n return dataDir;\n}\n\nexport function sessionsDir(): string {\n return resolve(dataDir, \"sessions\");\n}\n\nexport function attachmentsDir(): string {\n return resolve(dataDir, \"attachments\");\n}\n\nexport function configPath(): string {\n return resolve(dataDir, \"config.json\");\n}\n\nexport function sessionFile(sessionId: string): string {\n // Sanitize so a hostile/odd BuyerCookie cannot escape the sessions dir.\n const safe = sessionId.replace(/[^a-zA-Z0-9._-]/g, \"_\").slice(0, 200) || \"unknown\";\n return resolve(sessionsDir(), `${safe}.jsonl`);\n}\n\nexport function ensureDirs(): void {\n mkdirSync(dataDir, { recursive: true });\n mkdirSync(sessionsDir(), { recursive: true });\n mkdirSync(attachmentsDir(), { recursive: true });\n}\n","import { Hono } from \"hono\";\nimport { nanoid } from \"nanoid\";\nimport { getConnection } from \"../store/config.js\";\nimport { appendLog } from \"../store/log.js\";\nimport { saveAttachment } from \"../store/attachments.js\";\nimport { rememberSessionConnection } from \"../cart-store.js\";\nimport { sendCxml } from \"../http.js\";\nimport { browserFormPostUrl, getPublicUrl } from \"../runtime.js\";\nimport {\n buildOrderRequest,\n buildSetupRequest,\n makePayloadId,\n type OrderAttachmentMeta,\n} from \"../cxml/build.js\";\nimport { buildMultipartRelated, type MultipartAttachment } from \"../cxml/multipart.js\";\nimport { getStartPage, getStatus, parseXml } from \"../cxml/parse.js\";\nimport { validateDocument } from \"../cxml/validate.js\";\nimport type { AttachmentRef, CartItem, Connection } from \"../cxml/types.js\";\n\n// Mode A (virtual-buyer): drive the SetupRequest and OrderRequest server-to-server,\n// validate + log every document in both directions (spec sections 8, 10).\n\nexport const flowRoute = new Hono();\n\nfunction host(): string {\n try {\n return new URL(getPublicUrl()).host;\n } catch {\n return \"punchout-simulator\";\n }\n}\n\nfunction requireVirtualBuyer(conn: Connection | undefined): string | null {\n if (!conn) return \"connection not found\";\n if (conn.mode !== \"virtual-buyer\") return \"connection is not in virtual-buyer mode\";\n return null;\n}\n\n// --- SetupRequest preview -----------------------------------------------------\n\nflowRoute.get(\"/:id/setup/preview\", (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireVirtualBuyer(conn);\n if (err) return c.json({ error: err }, 400);\n const buyerCookie = c.req.query(\"buyerCookie\") || `pos-${nanoid(16)}`;\n const xml = buildSetupRequest({\n from: conn!.from,\n to: conn!.to,\n sender: conn!.sender,\n sharedSecret: conn!.sharedSecret,\n buyerCookie,\n browserFormPostUrl: browserFormPostUrl(),\n payloadId: makePayloadId(host(), new Date().toISOString()),\n timestamp: new Date().toISOString(),\n deploymentMode: conn!.deploymentMode,\n });\n return c.json({ buyerCookie, xml, browserFormPostUrl: browserFormPostUrl() });\n});\n\n// --- SetupRequest send --------------------------------------------------------\n\nflowRoute.post(\"/:id/setup\", async (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireVirtualBuyer(conn);\n if (err) return c.json({ error: err }, 400);\n\n const body = await c.req.json().catch(() => ({}));\n const buyerCookie: string = body.buyerCookie || `pos-${nanoid(16)}`;\n const xml: string =\n body.xml ||\n buildSetupRequest({\n from: conn!.from,\n to: conn!.to,\n sender: conn!.sender,\n sharedSecret: conn!.sharedSecret,\n buyerCookie,\n browserFormPostUrl: browserFormPostUrl(),\n payloadId: makePayloadId(host(), new Date().toISOString()),\n timestamp: new Date().toISOString(),\n deploymentMode: conn!.deploymentMode,\n });\n\n rememberSessionConnection(buyerCookie, conn!.id);\n\n const reqValidation = validateDocument(xml, {\n connection: conn,\n forceDocType: \"SetupRequest\",\n });\n const reqLog = appendLog({\n sessionId: buyerCookie,\n connectionId: conn!.id,\n direction: \"out\",\n docType: \"SetupRequest\",\n headers: { \"Content-Type\": \"text/xml; charset=UTF-8\" },\n body: xml,\n contentType: \"text/xml\",\n validation: reqValidation,\n });\n\n const res = await sendCxml(conn!.punchoutUrl!, xml);\n const respValidation = res.error\n ? undefined\n : validateDocument(res.body, { connection: conn, forceDocType: \"SetupResponse\" });\n const respLog = appendLog({\n sessionId: buyerCookie,\n connectionId: conn!.id,\n direction: \"in\",\n docType: \"SetupResponse\",\n status: res.status,\n headers: res.headers,\n body: res.error ? `<!-- transport error: ${res.error} -->` : res.body,\n contentType: res.contentType,\n validation: respValidation,\n });\n\n const startPage = res.error ? undefined : getStartPage(parseXml(res.body));\n const status = res.error ? undefined : getStatus(parseXml(res.body));\n\n return c.json({\n buyerCookie,\n transportError: res.error,\n httpStatus: res.status,\n startPage,\n statusCode: status?.code,\n request: reqLog,\n response: respLog,\n });\n});\n\n// --- OrderRequest send --------------------------------------------------------\n\ninterface OrderBody {\n sessionId: string;\n xml?: string;\n items?: CartItem[];\n orderId?: string;\n currency?: string;\n total?: number;\n danglingCid?: boolean;\n attachments?: Array<{\n contentId: string;\n filename?: string;\n contentType?: string;\n dataBase64: string;\n scope?: \"order\" | number; // number => 1-based item index\n }>;\n shipTo?: any;\n billTo?: any;\n}\n\n// Build the OrderRequest cXML from a request body. Shared by the preview and\n// send endpoints so the document you edit in the UI is exactly what gets sent.\nfunction buildOrderXml(conn: Connection, body: OrderBody): { xml: string; orderId: string } {\n const items = body.items ?? [];\n const currency = body.currency || items[0]?.currency || \"USD\";\n const total =\n body.total ?? items.reduce((s, it) => s + (it.unitPriceAmount ?? 0) * it.quantity, 0);\n const orderId = body.orderId || `PO-${nanoid(8)}`;\n const attMeta: OrderAttachmentMeta[] = (body.attachments ?? []).map((a) => ({\n contentId: a.contentId,\n scope: a.scope === \"order\" || a.scope == null ? \"order\" : { itemIndex: Number(a.scope) },\n }));\n const xml = buildOrderRequest({\n from: conn.from,\n to: conn.to,\n sender: conn.sender,\n sharedSecret: conn.sharedSecret,\n orderId,\n orderDate: new Date().toISOString(),\n payloadId: makePayloadId(host(), new Date().toISOString()),\n timestamp: new Date().toISOString(),\n deploymentMode: conn.deploymentMode,\n currency,\n total,\n items,\n shipTo: body.shipTo,\n billTo: body.billTo,\n attachments: attMeta,\n });\n return { xml, orderId };\n}\n\n// Preview the OrderRequest cXML (built from the cart + attachment plan) without\n// sending it, so the user can edit Comments/anything before dispatch.\nflowRoute.post(\"/:id/order/preview\", async (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireVirtualBuyer(conn);\n if (err) return c.json({ error: err }, 400);\n const body = (await c.req.json().catch(() => ({}))) as OrderBody;\n const { xml, orderId } = buildOrderXml(conn!, body);\n return c.json({ xml, orderId });\n});\n\nflowRoute.post(\"/:id/order\", async (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireVirtualBuyer(conn);\n if (err) return c.json({ error: err }, 400);\n\n const body = (await c.req.json().catch(() => ({}))) as OrderBody;\n const sessionId = body.sessionId || `pos-${nanoid(16)}`;\n const dangling = !!body.danglingCid;\n\n // In dangling-cid test mode the XML still references cid:<id> but the actual\n // part carries a DIFFERENT Content-ID, so a correct receiver must report the\n // attachment as missing (spec section 11).\n const inputAtts = body.attachments ?? [];\n\n // Use the (possibly edited) XML the client sent, otherwise build it fresh.\n const xml = body.xml || buildOrderXml(conn!, body).xml;\n\n // Assemble the wire body: multipart/related when there are attachments.\n let wireBody: string | Buffer = xml;\n let wireContentType = \"text/xml; charset=UTF-8\";\n const availableContentIds = new Set<string>();\n const savedRefs: AttachmentRef[] = [];\n\n if (inputAtts.length > 0) {\n const parts: MultipartAttachment[] = inputAtts.map((a) => {\n const actualCid = dangling ? `${a.contentId}-MISSING` : a.contentId;\n availableContentIds.add(actualCid);\n const data = Buffer.from(a.dataBase64, \"base64\");\n savedRefs.push(\n saveAttachment(data, {\n contentId: actualCid,\n filename: a.filename,\n contentType: a.contentType || \"application/octet-stream\",\n }),\n );\n return {\n contentId: actualCid,\n filename: a.filename,\n contentType: a.contentType || \"application/octet-stream\",\n data,\n };\n });\n const built = buildMultipartRelated(xml, parts);\n wireBody = built.body;\n wireContentType = built.contentType;\n }\n\n const reqValidation = validateDocument(xml, {\n connection: conn,\n forceDocType: \"OrderRequest\",\n availableContentIds: inputAtts.length > 0 ? availableContentIds : undefined,\n });\n\n const reqLog = appendLog({\n sessionId,\n connectionId: conn!.id,\n direction: \"out\",\n docType: \"OrderRequest\",\n headers: { \"Content-Type\": wireContentType },\n body: xml,\n contentType: wireContentType,\n validation: reqValidation,\n attachments: savedRefs,\n note: dangling ? \"dangling-cid test\" : undefined,\n });\n\n const res = await sendCxml(conn!.orderUrl!, wireBody, wireContentType);\n const respValidation = res.error\n ? undefined\n : validateDocument(res.body, { connection: conn, forceDocType: \"OrderResponse\" });\n const respLog = appendLog({\n sessionId,\n connectionId: conn!.id,\n direction: \"in\",\n docType: \"OrderResponse\",\n status: res.status,\n headers: res.headers,\n body: res.error ? `<!-- transport error: ${res.error} -->` : res.body,\n contentType: res.contentType,\n validation: respValidation,\n });\n\n const status = res.error ? undefined : getStatus(parseXml(res.body));\n return c.json({\n transportError: res.error,\n httpStatus: res.status,\n statusCode: status?.code,\n statusText: status?.text,\n request: reqLog,\n response: respLog,\n });\n});\n","import { appendFileSync, existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { nanoid } from \"nanoid\";\nimport { bus } from \"../bus.js\";\nimport type { LogRecord } from \"../cxml/types.js\";\nimport { ensureDirs, sessionFile, sessionsDir } from \"./paths.js\";\n\n// Request/response log: JSONL, append-only, partitioned per session\n// (data/sessions/<sessionId>.jsonl). Appending one line is O(1); the filename\n// is the session index. The server is the sole writer, so it emits the SSE\n// event the moment it appends. See spec section 7.\n\nexport type LogInput = Omit<LogRecord, \"id\" | \"ts\"> & Partial<Pick<LogRecord, \"id\" | \"ts\">>;\n\nexport function appendLog(input: LogInput): LogRecord {\n ensureDirs();\n const record: LogRecord = {\n ...input,\n id: input.id ?? nanoid(12),\n ts: input.ts ?? new Date().toISOString(),\n };\n appendFileSync(sessionFile(record.sessionId), JSON.stringify(record) + \"\\n\", \"utf8\");\n bus.emitLog(record);\n return record;\n}\n\nexport function readSession(sessionId: string): LogRecord[] {\n const file = sessionFile(sessionId);\n if (!existsSync(file)) return [];\n return readFileSync(file, \"utf8\")\n .split(\"\\n\")\n .filter((l) => l.trim().length > 0)\n .map((l) => {\n try {\n return JSON.parse(l) as LogRecord;\n } catch {\n return null;\n }\n })\n .filter((r): r is LogRecord => r !== null);\n}\n\nexport interface SessionSummary {\n sessionId: string;\n connectionId?: string;\n count: number;\n firstTs?: string;\n lastTs?: string;\n docTypes: string[];\n hasErrors: boolean;\n}\n\nexport function listSessions(): SessionSummary[] {\n ensureDirs();\n const files = readdirSync(sessionsDir()).filter((f) => f.endsWith(\".jsonl\"));\n const summaries: SessionSummary[] = [];\n for (const file of files) {\n const sessionId = file.replace(/\\.jsonl$/, \"\");\n const records = readSession(sessionId);\n if (records.length === 0) continue;\n summaries.push({\n sessionId: records[0].sessionId ?? sessionId,\n connectionId: records[0].connectionId,\n count: records.length,\n firstTs: records[0].ts,\n lastTs: records[records.length - 1].ts,\n docTypes: [...new Set(records.map((r) => r.docType))],\n hasErrors: records.some((r) => r.validation && !r.validation.ok),\n });\n }\n return summaries.sort((a, b) => (b.lastTs ?? \"\").localeCompare(a.lastTs ?? \"\"));\n}\n\nexport function readAllRecent(limit = 200): LogRecord[] {\n return listSessions()\n .flatMap((s) => readSession(s.sessionId))\n .sort((a, b) => a.ts.localeCompare(b.ts))\n .slice(-limit);\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Cart, LogRecord } from \"./cxml/types.js\";\n\n// In-process event bus. The server is the sole writer of the log, so it emits\n// the SSE event at the exact moment it appends the line — no file watching\n// needed (spec section 7).\n\nexport interface CartEvent {\n type: \"cart\";\n connectionId: string;\n cart: Cart;\n}\n\nexport interface LogEvent {\n type: \"log\";\n record: LogRecord;\n}\n\nexport type BusEvent = LogEvent | CartEvent;\n\nclass Bus extends EventEmitter {\n emitLog(record: LogRecord) {\n this.emit(\"event\", { type: \"log\", record } satisfies LogEvent);\n }\n emitCart(connectionId: string, cart: Cart) {\n this.emit(\"event\", { type: \"cart\", connectionId, cart } satisfies CartEvent);\n }\n onEvent(fn: (e: BusEvent) => void) {\n this.on(\"event\", fn);\n return () => this.off(\"event\", fn);\n }\n}\n\nexport const bus = new Bus();\n// SSE fan-out can exceed the default 10 listeners when several tabs are open.\nbus.setMaxListeners(0);\n","import { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { AttachmentRef } from \"../cxml/types.js\";\nimport { normalizeContentId } from \"../cxml/multipart.js\";\nimport { attachmentsDir, ensureDirs } from \"./paths.js\";\n\n// Attachments are stored as separate files data/attachments/<hash>, referenced\n// from the JSON log record (hash + Content-ID). We never inline base64 into the\n// JSONL. See spec section 7.\n\nexport function saveAttachment(\n data: Buffer,\n meta: { contentId: string; filename?: string; contentType: string; referenced?: boolean },\n): AttachmentRef {\n ensureDirs();\n const hash = createHash(\"sha256\").update(data).digest(\"hex\");\n const path = resolve(attachmentsDir(), hash);\n if (!existsSync(path)) writeFileSync(path, data);\n return {\n contentId: normalizeContentId(meta.contentId),\n filename: meta.filename,\n contentType: meta.contentType,\n hash,\n size: data.length,\n referenced: meta.referenced,\n };\n}\n\nexport function readAttachment(hash: string): Buffer | undefined {\n const safe = hash.replace(/[^a-f0-9]/gi, \"\");\n if (!safe) return undefined;\n const path = resolve(attachmentsDir(), safe);\n if (!existsSync(path)) return undefined;\n return readFileSync(path);\n}\n","import { nanoid } from \"nanoid\";\n\n// Hand-assembled multipart/related per spec sections 6 and 11. Part 1 is the\n// cXML document; parts 2..n are files, each carrying a Content-ID that the XML\n// references via <Attachment><URL>cid:XXX</URL>.\n\nexport interface MultipartAttachment {\n contentId: string; // without angle brackets\n filename?: string;\n contentType: string;\n data: Buffer;\n}\n\nexport interface BuiltMultipart {\n body: Buffer;\n contentType: string;\n boundary: string;\n}\n\n/** Strip angle brackets and surrounding whitespace from a Content-ID. */\nexport function normalizeContentId(cid: string | undefined): string {\n if (!cid) return \"\";\n return cid.trim().replace(/^<+/, \"\").replace(/>+$/, \"\").trim();\n}\n\n/** Strip the `cid:` scheme prefix from an Attachment URL (case-insensitive). */\nexport function stripCidScheme(url: string | undefined): string {\n if (!url) return \"\";\n return url.trim().replace(/^cid:/i, \"\").trim();\n}\n\nexport function buildMultipartRelated(\n cxml: string,\n attachments: MultipartAttachment[],\n opts: { mainContentId?: string } = {},\n): BuiltMultipart {\n const boundary = `cxml-${nanoid(20)}`;\n const mainCid = opts.mainContentId ?? `cxml-main@punchout-simulator`;\n const CRLF = \"\\r\\n\";\n const parts: Buffer[] = [];\n\n const pushPart = (headers: string[], data: Buffer) => {\n parts.push(Buffer.from(`--${boundary}${CRLF}`, \"utf8\"));\n parts.push(Buffer.from(headers.join(CRLF) + CRLF + CRLF, \"utf8\"));\n parts.push(data);\n parts.push(Buffer.from(CRLF, \"utf8\"));\n };\n\n pushPart(\n [\n `Content-Type: application/xml; charset=UTF-8`,\n `Content-Transfer-Encoding: binary`,\n `Content-ID: <${mainCid}>`,\n ],\n Buffer.from(cxml, \"utf8\"),\n );\n\n for (const att of attachments) {\n const disposition = att.filename\n ? `Content-Disposition: attachment; filename=\"${att.filename}\"`\n : `Content-Disposition: attachment`;\n pushPart(\n [\n `Content-Type: ${att.contentType}`,\n `Content-Transfer-Encoding: binary`,\n `Content-ID: <${normalizeContentId(att.contentId)}>`,\n disposition,\n ],\n att.data,\n );\n }\n\n parts.push(Buffer.from(`--${boundary}--${CRLF}`, \"utf8\"));\n\n return {\n body: Buffer.concat(parts),\n boundary,\n contentType: `multipart/related; boundary=\"${boundary}\"; type=\"application/xml\"; start=\"<${mainCid}>\"`,\n };\n}\n\nexport interface ParsedPart {\n headers: Record<string, string>;\n contentId: string; // normalized\n contentType?: string;\n body: Buffer;\n}\n\nexport interface ParsedMultipart {\n parts: ParsedPart[];\n /** The first part (or the one matching `start`) — the cXML document. */\n root?: ParsedPart;\n byContentId: Map<string, ParsedPart>;\n}\n\nexport function getBoundary(contentType: string): string | undefined {\n const m = /boundary=\"?([^\";]+)\"?/i.exec(contentType);\n return m?.[1];\n}\n\nexport function isMultipart(contentType: string | undefined): boolean {\n return !!contentType && /^multipart\\//i.test(contentType.trim());\n}\n\nexport function parseMultipartRelated(\n body: Buffer,\n contentType: string,\n): ParsedMultipart {\n const boundary = getBoundary(contentType);\n if (!boundary) {\n return { parts: [], byContentId: new Map() };\n }\n const delimiter = Buffer.from(`--${boundary}`, \"utf8\");\n const segments = splitBuffer(body, delimiter);\n const parts: ParsedPart[] = [];\n\n for (const seg of segments) {\n // Skip the preamble, the closing \"--\" marker and empty segments.\n const trimmed = trimLeadingCrlf(seg);\n if (trimmed.length === 0) continue;\n if (trimmed.length >= 2 && trimmed[0] === 0x2d && trimmed[1] === 0x2d) {\n continue; // closing boundary \"--boundary--\"\n }\n const splitIdx = findHeaderBodySplit(trimmed);\n if (splitIdx < 0) continue;\n const headerText = trimmed.subarray(0, splitIdx).toString(\"utf8\");\n let bodyBuf = trimmed.subarray(splitIdx);\n bodyBuf = stripBoundaryTrailingCrlf(bodyBuf);\n\n const headers: Record<string, string> = {};\n for (const line of headerText.split(/\\r?\\n/)) {\n const idx = line.indexOf(\":\");\n if (idx > 0) {\n headers[line.slice(0, idx).trim().toLowerCase()] = line\n .slice(idx + 1)\n .trim();\n }\n }\n parts.push({\n headers,\n contentId: normalizeContentId(headers[\"content-id\"]),\n contentType: headers[\"content-type\"],\n body: bodyBuf,\n });\n }\n\n const start = normalizeContentId(/start=\"?<?([^\">]+)>?\"?/i.exec(contentType)?.[1]);\n const byContentId = new Map<string, ParsedPart>();\n for (const p of parts) if (p.contentId) byContentId.set(p.contentId, p);\n const root =\n (start && byContentId.get(start)) ||\n parts.find((p) => /xml/i.test(p.contentType ?? \"\")) ||\n parts[0];\n\n return { parts, root, byContentId };\n}\n\n// --- buffer helpers -----------------------------------------------------------\n\nfunction splitBuffer(buf: Buffer, delimiter: Buffer): Buffer[] {\n const out: Buffer[] = [];\n let start = 0;\n let idx = buf.indexOf(delimiter, start);\n while (idx !== -1) {\n out.push(buf.subarray(start, idx));\n start = idx + delimiter.length;\n idx = buf.indexOf(delimiter, start);\n }\n out.push(buf.subarray(start));\n return out;\n}\n\nfunction trimLeadingCrlf(buf: Buffer): Buffer {\n let i = 0;\n while (i < buf.length && (buf[i] === 0x0d || buf[i] === 0x0a)) i++;\n return buf.subarray(i);\n}\n\nfunction stripBoundaryTrailingCrlf(buf: Buffer): Buffer {\n let end = buf.length;\n while (end > 0 && (buf[end - 1] === 0x0d || buf[end - 1] === 0x0a)) end--;\n return buf.subarray(0, end);\n}\n\n/** Index of the start of the body (just after the blank line). */\nfunction findHeaderBodySplit(buf: Buffer): number {\n const crlfcrlf = buf.indexOf(\"\\r\\n\\r\\n\");\n const lflf = buf.indexOf(\"\\n\\n\");\n if (crlfcrlf !== -1 && (lflf === -1 || crlfcrlf < lflf)) return crlfcrlf + 4;\n if (lflf !== -1) return lflf + 2;\n return -1;\n}\n","import type { Cart } from \"./cxml/types.js\";\n\n// The most recent cart per session (BuyerCookie), held in memory so the SPA can\n// fetch it after the punchback auto-submit lands on /punchout/return. The log\n// remains the durable record; this is just a fast lookup for the active flow.\n\nconst carts = new Map<string, Cart>();\nconst connectionBySession = new Map<string, string>();\n\nexport function setCart(cart: Cart): void {\n carts.set(cart.sessionId, cart);\n}\n\nexport function getCart(sessionId: string): Cart | undefined {\n return carts.get(sessionId);\n}\n\nexport function rememberSessionConnection(sessionId: string, connectionId: string): void {\n connectionBySession.set(sessionId, connectionId);\n}\n\nexport function connectionForSession(sessionId: string): string | undefined {\n return connectionBySession.get(sessionId);\n}\n","// Server-to-server cXML transport. SetupRequest and OrderRequest go out from\n// the tool here (no CORS, unlike a browser) — spec section 5.\n\nexport interface CxmlResponse {\n status: number;\n headers: Record<string, string>;\n body: string;\n rawBody: Buffer;\n contentType?: string;\n error?: string;\n}\n\nexport async function sendCxml(\n url: string,\n body: string | Buffer,\n contentType = \"text/xml; charset=UTF-8\",\n timeoutMs = 30000,\n): Promise<CxmlResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": contentType },\n body: body as any,\n signal: controller.signal,\n });\n const headers: Record<string, string> = {};\n res.headers.forEach((v, k) => (headers[k] = v));\n const buf = Buffer.from(await res.arrayBuffer());\n return {\n status: res.status,\n headers,\n body: buf.toString(\"utf8\"),\n rawBody: buf,\n contentType: res.headers.get(\"content-type\") ?? undefined,\n };\n } catch (e) {\n return {\n status: 0,\n headers: {},\n body: \"\",\n rawBody: Buffer.alloc(0),\n error: e instanceof Error ? e.message : String(e),\n };\n } finally {\n clearTimeout(timer);\n }\n}\n","// Runtime configuration set once at boot by the CLI. The public URL is what the\n// outside world (the user's browser, a remote buyer system in Mode B) uses to\n// reach this tool — defaults to http://localhost:<port> but can be overridden\n// with --public-url when fronting the tool with ngrok/cloudflared (spec\n// sections 4 and 12).\n\ninterface Runtime {\n port: number;\n publicUrl: string;\n}\n\nconst runtime: Runtime = {\n port: 8080,\n publicUrl: \"http://localhost:8080\",\n};\n\nexport function setRuntime(r: Partial<Runtime>): void {\n Object.assign(runtime, r);\n}\n\nexport function getPort(): number {\n return runtime.port;\n}\n\nexport function getPublicUrl(): string {\n return runtime.publicUrl.replace(/\\/$/, \"\");\n}\n\n/** The tool's own punchback callback URL (Mode A). */\nexport function browserFormPostUrl(): string {\n return `${getPublicUrl()}/punchout/return`;\n}\n","import { nanoid } from \"nanoid\";\nimport type { CartItem, Credential } from \"./types.js\";\n\n// cXML document builders. We use template literals (not an XML library) so we\n// keep full control over element order, attributes and xml:lang — see spec\n// section 6. Everything user-supplied is escaped.\n\nexport function escapeXml(value: string | number | undefined | null): string {\n if (value == null) return \"\";\n return String(value)\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\n/** Build a cXML payloadID of the form `<timestamp>.<random>@<host>`. */\nexport function makePayloadId(host: string, nowIso: string): string {\n return `${nowIso}.${nanoid(10)}@${host}`;\n}\n\nexport interface HeaderParts {\n from: Credential;\n to: Credential;\n sender: Credential;\n /** Included only when present (responses and the punchback omit it). */\n sharedSecret?: string;\n userAgent?: string;\n}\n\nfunction credentialBlock(tag: string, c: Credential): string {\n return ` <${tag}>\n <Credential domain=\"${escapeXml(c.domain)}\">\n <Identity>${escapeXml(c.identity)}</Identity>\n </Credential>\n </${tag}>`;\n}\n\nfunction senderBlock(c: Credential, sharedSecret?: string, userAgent?: string): string {\n const secret =\n sharedSecret != null && sharedSecret !== \"\"\n ? `\\n <SharedSecret>${escapeXml(sharedSecret)}</SharedSecret>`\n : \"\";\n return ` <Sender>\n <Credential domain=\"${escapeXml(c.domain)}\">\n <Identity>${escapeXml(c.identity)}</Identity>${secret}\n </Credential>\n <UserAgent>${escapeXml(userAgent ?? \"punchout-simulator\")}</UserAgent>\n </Sender>`;\n}\n\nfunction header(p: HeaderParts): string {\n return ` <Header>\n${credentialBlock(\"From\", p.from)}\n${credentialBlock(\"To\", p.to)}\n${senderBlock(p.sender, p.sharedSecret, p.userAgent)}\n </Header>`;\n}\n\nconst DECLARATION = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE cXML SYSTEM \"http://xml.cxml.org/schemas/cXML/1.2.045/cXML.dtd\">`;\n\nfunction envelope(payloadId: string, timestamp: string, lang: string, inner: string): string {\n return `${DECLARATION}\n<cXML payloadID=\"${escapeXml(payloadId)}\" timestamp=\"${escapeXml(timestamp)}\" xml:lang=\"${escapeXml(lang)}\">\n${inner}\n</cXML>`;\n}\n\n// --- SetupRequest (Mode A: buyer -> supplier) --------------------------------\n\nexport interface SetupRequestOptions {\n from: Credential;\n to: Credential;\n sender: Credential;\n sharedSecret?: string;\n buyerCookie: string;\n /** The tool's own callback URL the punchback should POST to. */\n browserFormPostUrl: string;\n payloadId: string;\n timestamp: string;\n lang?: string;\n deploymentMode?: string;\n operation?: string; // create | edit | inspect\n}\n\nexport function buildSetupRequest(o: SetupRequestOptions): string {\n const lang = o.lang ?? \"en-US\";\n const deployment = o.deploymentMode\n ? ` deploymentMode=\"${escapeXml(o.deploymentMode)}\"`\n : \"\";\n const inner = `${header({\n from: o.from,\n to: o.to,\n sender: o.sender,\n sharedSecret: o.sharedSecret,\n })}\n <Request${deployment}>\n <PunchOutSetupRequest operation=\"${escapeXml(o.operation ?? \"create\")}\">\n <BuyerCookie>${escapeXml(o.buyerCookie)}</BuyerCookie>\n <BrowserFormPost>\n <URL>${escapeXml(o.browserFormPostUrl)}</URL>\n </BrowserFormPost>\n </PunchOutSetupRequest>\n </Request>`;\n return envelope(o.payloadId, o.timestamp, lang, inner);\n}\n\n// --- OrderRequest (Mode A: buyer -> supplier) --------------------------------\n\nexport interface OrderRequestItem extends CartItem {}\n\nexport interface OrderAttachmentMeta {\n /** Content-ID to reference via <Attachment><URL>cid:...</URL>. */\n contentId: string;\n /** Where the attachment is attached: the whole order, or a 1-based item index. */\n scope: \"order\" | { itemIndex: number };\n}\n\nexport interface OrderRequestOptions {\n from: Credential;\n to: Credential;\n sender: Credential;\n sharedSecret?: string;\n orderId: string;\n orderDate: string;\n payloadId: string;\n timestamp: string;\n lang?: string;\n deploymentMode?: string;\n currency: string;\n total: number;\n items: OrderRequestItem[];\n shipTo?: AddressParts;\n billTo?: AddressParts;\n attachments?: OrderAttachmentMeta[];\n}\n\nexport interface AddressParts {\n addressId?: string;\n name?: string;\n deliverTo?: string;\n street?: string;\n city?: string;\n state?: string;\n postalCode?: string;\n countryIsoCode?: string;\n countryName?: string;\n}\n\nfunction addressBlock(tag: \"ShipTo\" | \"BillTo\", a: AddressParts): string {\n return ` <${tag}>\n <Address${a.addressId ? ` addressID=\"${escapeXml(a.addressId)}\"` : \"\"}>\n <Name xml:lang=\"en\">${escapeXml(a.name ?? \"\")}</Name>\n <PostalAddress>\n${a.deliverTo ? ` <DeliverTo>${escapeXml(a.deliverTo)}</DeliverTo>\\n` : \"\"} <Street>${escapeXml(a.street ?? \"\")}</Street>\n <City>${escapeXml(a.city ?? \"\")}</City>\n <State>${escapeXml(a.state ?? \"\")}</State>\n <PostalCode>${escapeXml(a.postalCode ?? \"\")}</PostalCode>\n <Country isoCountryCode=\"${escapeXml(a.countryIsoCode ?? \"US\")}\">${escapeXml(a.countryName ?? \"United States\")}</Country>\n </PostalAddress>\n </Address>\n </${tag}>`;\n}\n\nfunction commentsWithAttachments(cids: string[], indent: string): string {\n if (cids.length === 0) return \"\";\n const atts = cids\n .map(\n (cid) =>\n `${indent} <Attachment>\\n${indent} <URL>cid:${escapeXml(cid)}</URL>\\n${indent} </Attachment>`,\n )\n .join(\"\\n\");\n return `\\n${indent}<Comments>\\n${atts}\\n${indent}</Comments>`;\n}\n\nexport function buildOrderRequest(o: OrderRequestOptions): string {\n const lang = o.lang ?? \"en-US\";\n const deployment = o.deploymentMode\n ? ` deploymentMode=\"${escapeXml(o.deploymentMode)}\"`\n : \"\";\n\n const orderLevelCids = (o.attachments ?? [])\n .filter((a) => a.scope === \"order\")\n .map((a) => a.contentId);\n const itemCids = (idx: number) =>\n (o.attachments ?? [])\n .filter((a) => typeof a.scope === \"object\" && a.scope.itemIndex === idx)\n .map((a) => a.contentId);\n\n const items = o.items\n .map((it, i) => {\n const idx = i + 1;\n const cids = itemCids(idx);\n return ` <ItemOut quantity=\"${escapeXml(it.quantity)}\" lineNumber=\"${idx}\">\n <ItemID>\n <SupplierPartID>${escapeXml(it.supplierPartId ?? \"\")}</SupplierPartID>${\n it.supplierPartAuxiliaryId\n ? `\\n <SupplierPartAuxiliaryID>${escapeXml(it.supplierPartAuxiliaryId)}</SupplierPartAuxiliaryID>`\n : \"\"\n }\n </ItemID>\n <ItemDetail>\n <UnitPrice>\n <Money currency=\"${escapeXml(it.currency ?? o.currency)}\">${escapeXml(\n it.unitPriceAmount ?? 0,\n )}</Money>\n </UnitPrice>\n <Description xml:lang=\"en\">${escapeXml(it.description ?? \"\")}</Description>\n <UnitOfMeasure>${escapeXml(it.uom ?? \"EA\")}</UnitOfMeasure>\n <Classification domain=\"${escapeXml(it.classificationDomain ?? \"UNSPSC\")}\">${escapeXml(\n it.classification ?? \"\",\n )}</Classification>${\n it.manufacturerPartId\n ? `\\n <ManufacturerPartID>${escapeXml(it.manufacturerPartId)}</ManufacturerPartID>`\n : \"\"\n }${\n it.manufacturerName\n ? `\\n <ManufacturerName>${escapeXml(it.manufacturerName)}</ManufacturerName>`\n : \"\"\n }${commentsWithAttachments(cids, \" \")}\n </ItemDetail>\n </ItemOut>`;\n })\n .join(\"\\n\");\n\n const inner = `${header({\n from: o.from,\n to: o.to,\n sender: o.sender,\n sharedSecret: o.sharedSecret,\n })}\n <Request${deployment}>\n <OrderRequest>\n <OrderRequestHeader orderID=\"${escapeXml(o.orderId)}\" orderDate=\"${escapeXml(\n o.orderDate,\n )}\" type=\"new\">\n <Total>\n <Money currency=\"${escapeXml(o.currency)}\">${escapeXml(o.total)}</Money>\n </Total>\n${addressBlock(\"ShipTo\", o.shipTo ?? {})}\n${addressBlock(\"BillTo\", o.billTo ?? {})}${commentsWithAttachments(orderLevelCids, \" \")}\n </OrderRequestHeader>\n${items}\n </OrderRequest>\n </Request>`;\n return envelope(o.payloadId, o.timestamp, lang, inner);\n}\n\n// --- Responses & punchback (Mode B / mock supplier) --------------------------\n\nfunction optionalHeader(p?: { from: Credential; to: Credential; sender: Credential }): string {\n return p ? `${header({ from: p.from, to: p.to, sender: p.sender })}\\n` : \"\";\n}\n\nexport function buildSetupResponse(o: {\n payloadId: string;\n timestamp: string;\n startPageUrl: string;\n statusCode?: string;\n statusText?: string;\n lang?: string;\n from?: Credential;\n to?: Credential;\n sender?: Credential;\n}): string {\n const head =\n o.from && o.to && o.sender\n ? optionalHeader({ from: o.from, to: o.to, sender: o.sender })\n : \"\";\n const inner = `${head} <Response>\n <Status code=\"${escapeXml(o.statusCode ?? \"200\")}\" text=\"${escapeXml(\n o.statusText ?? \"OK\",\n )}\"/>\n <PunchOutSetupResponse>\n <StartPage>\n <URL>${escapeXml(o.startPageUrl)}</URL>\n </StartPage>\n </PunchOutSetupResponse>\n </Response>`;\n return envelope(o.payloadId, o.timestamp, o.lang ?? \"en-US\", inner);\n}\n\nexport function buildResponseStatus(o: {\n payloadId: string;\n timestamp: string;\n statusCode?: string;\n statusText?: string;\n lang?: string;\n from?: Credential;\n to?: Credential;\n sender?: Credential;\n}): string {\n const head =\n o.from && o.to && o.sender\n ? optionalHeader({ from: o.from, to: o.to, sender: o.sender })\n : \"\";\n const inner = `${head} <Response>\n <Status code=\"${escapeXml(o.statusCode ?? \"200\")}\" text=\"${escapeXml(\n o.statusText ?? \"OK\",\n )}\">${escapeXml(o.statusText === \"OK\" || !o.statusText ? \"\" : o.statusText)}</Status>\n </Response>`;\n return envelope(o.payloadId, o.timestamp, o.lang ?? \"en-US\", inner);\n}\n\nexport interface PunchbackOptions {\n from: Credential;\n to: Credential;\n sender: Credential;\n buyerCookie: string;\n payloadId: string;\n timestamp: string;\n lang?: string;\n currency: string;\n items: CartItem[];\n}\n\nexport function buildPunchOutOrderMessage(o: PunchbackOptions): string {\n const total = o.items.reduce(\n (sum, it) => sum + (it.unitPriceAmount ?? 0) * it.quantity,\n 0,\n );\n const items = o.items\n .map(\n (it) => ` <ItemIn quantity=\"${escapeXml(it.quantity)}\">\n <ItemID>\n <SupplierPartID>${escapeXml(it.supplierPartId ?? \"\")}</SupplierPartID>${\n it.supplierPartAuxiliaryId\n ? `\\n <SupplierPartAuxiliaryID>${escapeXml(it.supplierPartAuxiliaryId)}</SupplierPartAuxiliaryID>`\n : \"\"\n }\n </ItemID>\n <ItemDetail>\n <UnitPrice>\n <Money currency=\"${escapeXml(it.currency ?? o.currency)}\">${escapeXml(\n it.unitPriceAmount ?? 0,\n )}</Money>\n </UnitPrice>\n <Description xml:lang=\"en\">${escapeXml(it.description ?? \"\")}</Description>\n <UnitOfMeasure>${escapeXml(it.uom ?? \"EA\")}</UnitOfMeasure>\n <Classification domain=\"${escapeXml(it.classificationDomain ?? \"UNSPSC\")}\">${escapeXml(\n it.classification ?? \"\",\n )}</Classification>${\n it.manufacturerPartId\n ? `\\n <ManufacturerPartID>${escapeXml(it.manufacturerPartId)}</ManufacturerPartID>`\n : \"\"\n }\n </ItemDetail>\n </ItemIn>`,\n )\n .join(\"\\n\");\n\n const inner = `${header({ from: o.from, to: o.to, sender: o.sender })}\n <Message>\n <PunchOutOrderMessage>\n <BuyerCookie>${escapeXml(o.buyerCookie)}</BuyerCookie>\n <PunchOutOrderMessageHeader operationAllowed=\"create\">\n <Total>\n <Money currency=\"${escapeXml(o.currency)}\">${escapeXml(total.toFixed(2))}</Money>\n </Total>\n </PunchOutOrderMessageHeader>\n${items}\n </PunchOutOrderMessage>\n </Message>`;\n return envelope(o.payloadId, o.timestamp, o.lang ?? \"en-US\", inner);\n}\n","import { XMLParser, XMLValidator } from \"fast-xml-parser\";\nimport type { Cart, CartItem, Credential, DocType } from \"./types.js\";\n\n// fast-xml-parser configuration. We keep all tag/attribute values as raw\n// strings (no number coercion) so money amounts like \"100.00\" survive intact;\n// numeric conversion happens explicitly where we need it.\nconst ATTR = \"@_\";\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: ATTR,\n parseTagValue: false,\n parseAttributeValue: false,\n trimValues: true,\n // Always treat the repeated cXML containers as arrays so callers don't have\n // to special-case \"one item vs many\".\n isArray: (name) =>\n [\"ItemIn\", \"ItemOut\", \"Attachment\", \"Comments\", \"Extrinsic\"].includes(name),\n});\n\nexport interface ParsedDoc {\n raw: string;\n /** Parsed object tree, or null when not well-formed. */\n tree: any | null;\n wellFormed: boolean;\n wellFormedError?: string;\n}\n\nexport function parseXml(raw: string): ParsedDoc {\n const check = XMLValidator.validate(raw, { allowBooleanAttributes: true });\n if (check !== true) {\n return {\n raw,\n tree: null,\n wellFormed: false,\n wellFormedError: check?.err?.msg ?? \"not well-formed\",\n };\n }\n try {\n return { raw, tree: parser.parse(raw), wellFormed: true };\n } catch (e) {\n return {\n raw,\n tree: null,\n wellFormed: false,\n wellFormedError: e instanceof Error ? e.message : String(e),\n };\n }\n}\n\n// --- small navigation helpers -------------------------------------------------\n\n/** Extract text content of a node whether it is a bare string or {#text}. */\nexport function text(node: any): string | undefined {\n if (node == null) return undefined;\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\" || typeof node === \"boolean\") return String(node);\n if (typeof node === \"object\" && \"#text\" in node) {\n const t = node[\"#text\"];\n return t == null ? undefined : String(t);\n }\n return undefined;\n}\n\nexport function attr(node: any, name: string): string | undefined {\n if (node == null || typeof node !== \"object\") return undefined;\n const v = node[ATTR + name];\n return v == null ? undefined : String(v);\n}\n\nexport function asArray<T = any>(node: any): T[] {\n if (node == null) return [];\n return Array.isArray(node) ? node : [node];\n}\n\n/** The cXML root element ({@code <cXML>}). */\nexport function root(doc: ParsedDoc): any | undefined {\n return doc.tree?.cXML;\n}\n\n// --- document classification --------------------------------------------------\n\nexport function getDocType(doc: ParsedDoc): DocType {\n const r = root(doc);\n if (!r) return \"Unknown\";\n const req = r.Request;\n const resp = r.Response;\n const msg = r.Message;\n // Use key presence, not truthiness: an empty element (e.g.\n // `<PunchOutSetupResponse/>`) parses to \"\" which is falsy.\n if (req && typeof req === \"object\") {\n if (\"PunchOutSetupRequest\" in req) return \"SetupRequest\";\n if (\"OrderRequest\" in req) return \"OrderRequest\";\n }\n if (resp && typeof resp === \"object\") {\n // SetupResponse and OrderResponse both live under <Response>; distinguish\n // by the presence of the PunchOut payload.\n if (\"PunchOutSetupResponse\" in resp) return \"SetupResponse\";\n return \"OrderResponse\";\n }\n if (msg && typeof msg === \"object\" && \"PunchOutOrderMessage\" in msg) {\n return \"PunchOutOrderMessage\";\n }\n return \"Unknown\";\n}\n\n// --- credential extraction ----------------------------------------------------\n\nfunction credentialOf(node: any): Credential | undefined {\n const cred = node?.Credential;\n if (!cred) return undefined;\n const first = Array.isArray(cred) ? cred[0] : cred;\n return {\n domain: attr(first, \"domain\") ?? \"\",\n identity: text(first?.Identity) ?? \"\",\n };\n}\n\nexport interface HeaderCredentials {\n from?: Credential;\n to?: Credential;\n sender?: Credential;\n sharedSecret?: string;\n}\n\nexport function getHeaderCredentials(doc: ParsedDoc): HeaderCredentials {\n const header = root(doc)?.Header;\n if (!header) return {};\n const senderCred = header.Sender?.Credential;\n const senderFirst = Array.isArray(senderCred) ? senderCred[0] : senderCred;\n return {\n from: credentialOf(header.From),\n to: credentialOf(header.To),\n sender: credentialOf(header.Sender),\n sharedSecret: text(senderFirst?.SharedSecret),\n };\n}\n\nexport function getPayloadId(doc: ParsedDoc): string | undefined {\n return attr(root(doc), \"payloadID\");\n}\n\nexport function getTimestamp(doc: ParsedDoc): string | undefined {\n return attr(root(doc), \"timestamp\");\n}\n\n// --- response helpers ---------------------------------------------------------\n\nexport interface StatusInfo {\n code?: string;\n text?: string;\n}\n\nexport function getStatus(doc: ParsedDoc): StatusInfo {\n const status = root(doc)?.Response?.Status;\n if (!status) return {};\n return { code: attr(status, \"code\"), text: attr(status, \"text\") };\n}\n\nexport function getStartPage(doc: ParsedDoc): string | undefined {\n const sr = root(doc)?.Response?.PunchOutSetupResponse;\n return text(sr?.StartPage?.URL);\n}\n\n// --- punchback -> cart --------------------------------------------------------\n\nfunction money(node: any): { amount?: number; currency?: string } {\n const m = node?.Money;\n if (!m) return {};\n const raw = text(m);\n const amount = raw != null && raw !== \"\" ? Number(raw) : undefined;\n return {\n amount: Number.isFinite(amount) ? amount : undefined,\n currency: attr(m, \"currency\"),\n };\n}\n\n// --- attachment cid references (OrderRequest) --------------------------------\n\nexport interface CidReference {\n cid: string; // normalized, cid: scheme stripped\n rawUrl: string;\n level: \"order\" | \"item\";\n itemIndex?: number; // 1-based, for item-level\n /** A plain https:// URL rather than a cid: reference. */\n external: boolean;\n}\n\nfunction stripCid(url: string): { cid: string; external: boolean } {\n const trimmed = url.trim();\n if (/^cid:/i.test(trimmed)) {\n const cid = trimmed.replace(/^cid:/i, \"\").trim().replace(/^<+/, \"\").replace(/>+$/, \"\");\n return { cid, external: false };\n }\n return { cid: trimmed, external: true };\n}\n\nfunction attachmentsInComments(commentsNode: any): string[] {\n const urls: string[] = [];\n for (const comments of asArray(commentsNode)) {\n for (const att of asArray(comments?.Attachment)) {\n const url = text(att?.URL);\n if (url) urls.push(url);\n }\n }\n return urls;\n}\n\n/**\n * Scan an OrderRequest for every <Attachment><URL> at both levels:\n * OrderRequestHeader/Comments (whole-order) and each ItemOut/Comments\n * (per line item). See spec section 11 — Comments appears at two levels.\n */\nexport function collectCidReferences(doc: ParsedDoc): CidReference[] {\n const orderReq = root(doc)?.Request?.OrderRequest;\n if (!orderReq) return [];\n const refs: CidReference[] = [];\n\n for (const rawUrl of attachmentsInComments(orderReq?.OrderRequestHeader?.Comments)) {\n const { cid, external } = stripCid(rawUrl);\n refs.push({ cid, rawUrl, level: \"order\", external });\n }\n\n asArray(orderReq?.ItemOut).forEach((item, i) => {\n for (const rawUrl of attachmentsInComments(item?.ItemDetail?.Comments)) {\n const { cid, external } = stripCid(rawUrl);\n refs.push({ cid, rawUrl, level: \"item\", itemIndex: i + 1, external });\n }\n // Comments may also appear directly under ItemOut (not just ItemDetail).\n for (const rawUrl of attachmentsInComments(item?.Comments)) {\n const { cid, external } = stripCid(rawUrl);\n refs.push({ cid, rawUrl, level: \"item\", itemIndex: i + 1, external });\n }\n });\n\n return refs;\n}\n\nexport function parseCart(doc: ParsedDoc): Cart {\n const pom = root(doc)?.Message?.PunchOutOrderMessage;\n const sessionId = text(pom?.BuyerCookie) ?? \"\";\n const headerNode = pom?.PunchOutOrderMessageHeader;\n const total = money(headerNode?.Total);\n const items: CartItem[] = asArray(pom?.ItemIn).map((it) => {\n const detail = it?.ItemDetail;\n const up = money(detail?.UnitPrice);\n const classification = detail?.Classification;\n const classFirst = Array.isArray(classification)\n ? classification[0]\n : classification;\n return {\n quantity: Number(attr(it, \"quantity\") ?? \"1\") || 1,\n supplierPartId: text(it?.ItemID?.SupplierPartID),\n supplierPartAuxiliaryId: text(it?.ItemID?.SupplierPartAuxiliaryID),\n description: text(detail?.Description),\n uom: text(detail?.UnitOfMeasure),\n unitPriceAmount: up.amount,\n currency: up.currency,\n classificationDomain: attr(classFirst, \"domain\"),\n classification: text(classFirst),\n manufacturerPartId: text(detail?.ManufacturerPartID),\n manufacturerName: text(detail?.ManufacturerName),\n };\n });\n return {\n sessionId,\n operationAllowed: attr(headerNode, \"operationAllowed\"),\n total:\n total.amount != null && total.currency\n ? { amount: total.amount, currency: total.currency }\n : undefined,\n items,\n };\n}\n","import {\n asArray,\n attr,\n collectCidReferences,\n getDocType,\n getHeaderCredentials,\n getPayloadId,\n getStartPage,\n getStatus,\n getTimestamp,\n parseXml,\n root,\n text,\n type ParsedDoc,\n} from \"./parse.js\";\nimport type {\n Connection,\n Credential,\n DocType,\n ValidationIssue,\n ValidationResult,\n} from \"./types.js\";\n\n// Bidirectional cXML validation (spec section 8). Runs on every document,\n// inbound and outbound. Full DTD validation would require a native validating\n// parser (which would hurt `npx` portability — spec section 6), so we do\n// well-formedness via fast-xml-parser plus thorough field-level rules, which\n// is the high-value half of the linter for sellers checking their own output.\n\nexport interface ValidationContext {\n connection?: Connection;\n /** Expected BuyerCookie for the session (punchback correlation). */\n expectedBuyerCookie?: string;\n /** Normalized Content-IDs present in a multipart envelope, for cid resolution. */\n availableContentIds?: Set<string>;\n /** Force the doc type rather than inferring it (e.g. when shape is ambiguous). */\n forceDocType?: DocType;\n}\n\nclass Issues {\n list: ValidationIssue[] = [];\n error(code: string, message: string, path?: string) {\n this.list.push({ severity: \"error\", code, message, path });\n }\n warn(code: string, message: string, path?: string) {\n this.list.push({ severity: \"warning\", code, message, path });\n }\n info(code: string, message: string, path?: string) {\n this.list.push({ severity: \"info\", code, message, path });\n }\n}\n\nfunction isValidUrl(s: string | undefined): boolean {\n if (!s) return false;\n try {\n const u = new URL(s);\n return u.protocol === \"http:\" || u.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nfunction credEq(a: Credential | undefined, b: Credential | undefined): boolean {\n if (!a || !b) return false;\n return a.domain === b.domain && a.identity === b.identity;\n}\n\nfunction credKnown(c: Credential | undefined, conn: Connection): boolean {\n if (!c) return false;\n return [conn.from, conn.to, conn.sender].some((k) => credEq(c, k));\n}\n\n// --- general checks ----------------------------------------------------------\n\nfunction checkGeneral(doc: ParsedDoc, ctx: ValidationContext, issues: Issues) {\n const payloadId = getPayloadId(doc);\n if (!payloadId) {\n issues.error(\"missing-payloadID\", \"cXML/@payloadID is missing\", \"cXML/@payloadID\");\n } else if (!payloadId.includes(\"@\")) {\n issues.warn(\n \"payloadID-format\",\n \"payloadID should have the form <unique>@<host>\",\n \"cXML/@payloadID\",\n );\n }\n\n if (!getTimestamp(doc)) {\n issues.error(\"missing-timestamp\", \"cXML/@timestamp is missing\", \"cXML/@timestamp\");\n }\n\n if (!ctx.connection) return;\n const conn = ctx.connection;\n const creds = getHeaderCredentials(doc);\n\n for (const [name, c] of [\n [\"From\", creds.from],\n [\"To\", creds.to],\n [\"Sender\", creds.sender],\n ] as const) {\n if (!c) {\n issues.warn(\"missing-credential\", `Header/${name} credential is missing`, `cXML/Header/${name}`);\n continue;\n }\n if (!c.domain) {\n issues.warn(\"credential-domain\", `Header/${name}/Credential/@domain is empty`, `cXML/Header/${name}`);\n }\n if (!c.identity) {\n issues.warn(\"credential-identity\", `Header/${name}/Credential/Identity is empty`, `cXML/Header/${name}`);\n }\n if (c.domain && c.identity && !credKnown(c, conn)) {\n issues.warn(\n \"credential-mismatch\",\n `Header/${name} (${c.domain}/${c.identity}) does not match any identity configured on the connection`,\n `cXML/Header/${name}`,\n );\n }\n }\n}\n\nfunction checkSharedSecret(doc: ParsedDoc, ctx: ValidationContext, issues: Issues) {\n if (!ctx.connection) return;\n const conn = ctx.connection;\n if (conn.authStyle !== \"SharedSecret\") return;\n const creds = getHeaderCredentials(doc);\n if (!creds.sharedSecret) {\n issues.warn(\n \"missing-sharedsecret\",\n \"Sender/Credential/SharedSecret is absent (required for SharedSecret auth)\",\n \"cXML/Header/Sender/Credential/SharedSecret\",\n );\n } else if (conn.sharedSecret && creds.sharedSecret !== conn.sharedSecret) {\n issues.error(\n \"sharedsecret-mismatch\",\n \"Sender SharedSecret does not match the connection's configured shared secret\",\n \"cXML/Header/Sender/Credential/SharedSecret\",\n );\n }\n}\n\n// --- document-specific checks ------------------------------------------------\n\nfunction checkSetupResponse(doc: ParsedDoc, issues: Issues) {\n const status = getStatus(doc);\n if (!status.code) {\n issues.error(\"missing-status\", \"Response/Status/@code is missing\", \"cXML/Response/Status\");\n } else if (status.code !== \"200\") {\n issues.error(\n \"status-not-200\",\n `PunchOutSetupResponse Status is ${status.code} (expected 200)`,\n \"cXML/Response/Status\",\n );\n }\n const startPage = getStartPage(doc);\n if (!startPage) {\n issues.error(\n \"missing-startpage\",\n \"PunchOutSetupResponse/StartPage/URL is missing\",\n \"cXML/Response/PunchOutSetupResponse/StartPage/URL\",\n );\n } else if (!isValidUrl(startPage)) {\n issues.error(\n \"invalid-startpage-url\",\n `StartPage/URL is not a valid http(s) URL: ${startPage}`,\n \"cXML/Response/PunchOutSetupResponse/StartPage/URL\",\n );\n }\n}\n\nfunction num(s: string | undefined): number | undefined {\n if (s == null || s === \"\") return undefined;\n const n = Number(s);\n return Number.isFinite(n) ? n : undefined;\n}\n\nfunction checkPunchback(doc: ParsedDoc, ctx: ValidationContext, issues: Issues) {\n const pom = root(doc)?.Message?.PunchOutOrderMessage;\n if (!pom) {\n issues.error(\"missing-pom\", \"Message/PunchOutOrderMessage is missing\", \"cXML/Message\");\n return;\n }\n const buyerCookie = text(pom.BuyerCookie);\n if (!buyerCookie) {\n issues.error(\"missing-buyercookie\", \"BuyerCookie is missing\", \"cXML/Message/PunchOutOrderMessage/BuyerCookie\");\n } else if (ctx.expectedBuyerCookie && buyerCookie !== ctx.expectedBuyerCookie) {\n issues.error(\n \"buyercookie-mismatch\",\n `BuyerCookie \"${buyerCookie}\" does not match the session \"${ctx.expectedBuyerCookie}\"`,\n \"cXML/Message/PunchOutOrderMessage/BuyerCookie\",\n );\n }\n\n const headerNode = pom.PunchOutOrderMessageHeader;\n const totalMoney = headerNode?.Total?.Money;\n const totalAmount = num(text(totalMoney));\n const totalCurrency = attr(totalMoney, \"currency\");\n if (totalMoney == null) {\n issues.error(\"missing-total\", \"PunchOutOrderMessageHeader/Total/Money is missing\", \"cXML/.../PunchOutOrderMessageHeader/Total\");\n } else if (!totalCurrency) {\n issues.error(\"missing-total-currency\", \"Total/Money/@currency is missing\", \"cXML/.../Total/Money\");\n }\n\n const items = asArray(pom.ItemIn);\n if (items.length === 0) {\n issues.warn(\"empty-cart\", \"PunchOutOrderMessage contains no ItemIn elements\", \"cXML/.../PunchOutOrderMessage\");\n }\n\n let lineSum = 0;\n items.forEach((it, i) => {\n const base = `cXML/.../ItemIn[${i + 1}]`;\n const qty = num(attr(it, \"quantity\"));\n if (qty == null) {\n issues.error(\"item-missing-quantity\", `ItemIn[${i + 1}] is missing @quantity`, base);\n }\n if (!text(it?.ItemID?.SupplierPartID)) {\n issues.error(\"item-missing-supplierpartid\", `ItemIn[${i + 1}] is missing ItemID/SupplierPartID`, `${base}/ItemID`);\n }\n const detail = it?.ItemDetail;\n if (!detail) {\n issues.error(\"item-missing-detail\", `ItemIn[${i + 1}] is missing ItemDetail`, base);\n return;\n }\n const up = detail.UnitPrice?.Money;\n const upAmount = num(text(up));\n if (up == null) {\n issues.error(\"item-missing-unitprice\", `ItemIn[${i + 1}] is missing ItemDetail/UnitPrice/Money`, `${base}/ItemDetail/UnitPrice`);\n } else if (!attr(up, \"currency\")) {\n issues.error(\"item-missing-currency\", `ItemIn[${i + 1}] UnitPrice/Money is missing @currency`, `${base}/ItemDetail/UnitPrice/Money`);\n }\n if (!text(detail.Description)) {\n issues.error(\"item-missing-description\", `ItemIn[${i + 1}] is missing ItemDetail/Description`, `${base}/ItemDetail/Description`);\n }\n if (!text(detail.UnitOfMeasure)) {\n issues.error(\"item-missing-uom\", `ItemIn[${i + 1}] is missing ItemDetail/UnitOfMeasure`, `${base}/ItemDetail/UnitOfMeasure`);\n }\n const classification = Array.isArray(detail.Classification)\n ? detail.Classification[0]\n : detail.Classification;\n if (classification == null) {\n issues.error(\"item-missing-classification\", `ItemIn[${i + 1}] is missing ItemDetail/Classification`, `${base}/ItemDetail/Classification`);\n } else if (!attr(classification, \"domain\")) {\n issues.error(\"item-classification-domain\", `ItemIn[${i + 1}] Classification is missing @domain`, `${base}/ItemDetail/Classification`);\n }\n if (qty != null && upAmount != null) lineSum += qty * upAmount;\n });\n\n // Total consistency: sum of (quantity * unit price) vs the header Total.\n if (totalAmount != null && items.length > 0) {\n const diff = Math.abs(totalAmount - lineSum);\n if (diff > 0.01) {\n issues.warn(\n \"total-mismatch\",\n `Header Total (${totalAmount.toFixed(2)}) does not equal the sum of line totals (${lineSum.toFixed(2)})`,\n \"cXML/.../PunchOutOrderMessageHeader/Total\",\n );\n }\n }\n}\n\nfunction checkOrderRequest(doc: ParsedDoc, ctx: ValidationContext, issues: Issues) {\n const orderReq = root(doc)?.Request?.OrderRequest;\n if (!orderReq) {\n issues.error(\"missing-orderrequest\", \"Request/OrderRequest is missing\", \"cXML/Request\");\n return;\n }\n const header = orderReq.OrderRequestHeader;\n if (!attr(header, \"orderID\")) {\n issues.error(\"missing-orderid\", \"OrderRequestHeader/@orderID is missing\", \"cXML/.../OrderRequestHeader\");\n }\n if (!attr(header, \"orderDate\")) {\n issues.error(\"missing-orderdate\", \"OrderRequestHeader/@orderDate is missing\", \"cXML/.../OrderRequestHeader\");\n }\n if (header?.Total?.Money == null) {\n issues.error(\"missing-order-total\", \"OrderRequestHeader/Total/Money is missing\", \"cXML/.../OrderRequestHeader/Total\");\n }\n if (!header?.ShipTo) {\n issues.warn(\"missing-shipto\", \"OrderRequestHeader/ShipTo is missing\", \"cXML/.../OrderRequestHeader/ShipTo\");\n }\n if (!header?.BillTo) {\n issues.warn(\"missing-billto\", \"OrderRequestHeader/BillTo is missing\", \"cXML/.../OrderRequestHeader/BillTo\");\n }\n\n const items = asArray(orderReq.ItemOut);\n if (items.length === 0) {\n issues.error(\"no-itemout\", \"OrderRequest contains no ItemOut elements\", \"cXML/.../OrderRequest\");\n }\n items.forEach((it, i) => {\n const base = `cXML/.../ItemOut[${i + 1}]`;\n if (!text(it?.ItemID?.SupplierPartID)) {\n issues.error(\"itemout-missing-id\", `ItemOut[${i + 1}] is missing ItemID/SupplierPartID`, `${base}/ItemID`);\n }\n if (it?.ItemDetail?.UnitPrice?.Money == null) {\n issues.error(\"itemout-missing-unitprice\", `ItemOut[${i + 1}] is missing ItemDetail/UnitPrice/Money`, `${base}/ItemDetail/UnitPrice`);\n }\n if (num(attr(it, \"quantity\")) == null) {\n issues.error(\"itemout-missing-quantity\", `ItemOut[${i + 1}] is missing @quantity`, base);\n }\n });\n\n // Attachment cid resolution (spec section 11). Scan Comments at both levels.\n const refs = collectCidReferences(doc);\n const available = ctx.availableContentIds;\n const referenced = new Set<string>();\n for (const ref of refs) {\n if (ref.external) {\n issues.info(\n \"external-attachment\",\n `Attachment URL is an external reference (not a cid:): ${ref.rawUrl}`,\n ref.level === \"item\" ? `cXML/.../ItemOut[${ref.itemIndex}]` : \"cXML/.../OrderRequestHeader/Comments\",\n );\n continue;\n }\n referenced.add(ref.cid);\n if (available && !available.has(ref.cid)) {\n issues.error(\n \"dangling-cid\",\n `Attachment references cid:\"${ref.cid}\" but no multipart part has that Content-ID (dangling attachment)`,\n ref.level === \"item\" ? `cXML/.../ItemOut[${ref.itemIndex}]/Comments/Attachment` : \"cXML/.../OrderRequestHeader/Comments/Attachment\",\n );\n }\n }\n // Parts present in the envelope but never referenced by any Attachment.\n if (available) {\n for (const cid of available) {\n if (!referenced.has(cid)) {\n issues.warn(\n \"unreferenced-attachment\",\n `Multipart part Content-ID \"${cid}\" is not referenced by any <Attachment><URL>cid:...`,\n \"multipart\",\n );\n }\n }\n }\n}\n\nfunction checkOrderResponse(doc: ParsedDoc, issues: Issues) {\n const status = getStatus(doc);\n if (!status.code) {\n issues.error(\"missing-status\", \"Response/Status/@code is missing\", \"cXML/Response/Status\");\n } else {\n const code = Number(status.code);\n if (Number.isFinite(code) && code >= 400) {\n issues.error(\"status-error\", `Response Status is ${status.code} ${status.text ?? \"\"}`.trim(), \"cXML/Response/Status\");\n }\n }\n}\n\n// --- entry point -------------------------------------------------------------\n\nexport function validateDocument(raw: string, ctx: ValidationContext = {}): ValidationResult {\n const doc = parseXml(raw);\n const issues = new Issues();\n\n if (!doc.wellFormed) {\n issues.error(\"not-well-formed\", `XML is not well-formed: ${doc.wellFormedError}`);\n return { docType: \"Unknown\", wellFormed: false, ok: false, issues: issues.list };\n }\n\n const docType = ctx.forceDocType ?? getDocType(doc);\n checkGeneral(doc, ctx, issues);\n\n switch (docType) {\n case \"SetupRequest\":\n checkSharedSecret(doc, ctx, issues);\n if (!root(doc)?.Request?.PunchOutSetupRequest?.BrowserFormPost?.URL) {\n issues.warn(\"missing-browserformpost\", \"PunchOutSetupRequest/BrowserFormPost/URL is missing\", \"cXML/.../PunchOutSetupRequest/BrowserFormPost/URL\");\n }\n break;\n case \"SetupResponse\":\n checkSetupResponse(doc, issues);\n break;\n case \"PunchOutOrderMessage\":\n checkPunchback(doc, ctx, issues);\n break;\n case \"OrderRequest\":\n checkSharedSecret(doc, ctx, issues);\n checkOrderRequest(doc, ctx, issues);\n break;\n case \"OrderResponse\":\n checkOrderResponse(doc, issues);\n break;\n default:\n issues.warn(\"unknown-doctype\", \"Could not classify the cXML document type\");\n }\n\n const hasError = issues.list.some((i) => i.severity === \"error\");\n return { docType, wellFormed: true, ok: !hasError, issues: issues.list };\n}\n","import { Hono } from \"hono\";\nimport { bus } from \"../bus.js\";\nimport {\n connectionForSession,\n rememberSessionConnection,\n setCart,\n} from \"../cart-store.js\";\nimport { getConnection } from \"../store/config.js\";\nimport { appendLog } from \"../store/log.js\";\nimport { parseCart, parseXml, text, root } from \"../cxml/parse.js\";\nimport { validateDocument } from \"../cxml/validate.js\";\n\n// Mode A callback: receives the punchback (PunchOutOrderMessage) auto-submitted\n// by the user's browser. It arrives either as a `cxml-urlencoded` form field\n// (Ariba style), a `cxml-base64` field, or a raw cXML body — handle all three\n// (spec section 11). Correlate by BuyerCookie.\n\nexport const punchoutReturnRoute = new Hono();\n\nasync function extractCxml(c: any): Promise<string> {\n const ct = (c.req.header(\"content-type\") ?? \"\").toLowerCase();\n if (ct.includes(\"application/x-www-form-urlencoded\") || ct.includes(\"multipart/form-data\")) {\n const form = await c.req.parseBody();\n if (typeof form[\"cxml-urlencoded\"] === \"string\") return form[\"cxml-urlencoded\"] as string;\n if (typeof form[\"cxml-base64\"] === \"string\") {\n return Buffer.from(form[\"cxml-base64\"] as string, \"base64\").toString(\"utf8\");\n }\n // Some buyers post the cXML under a differently-named single field.\n const firstString = Object.values(form).find((v) => typeof v === \"string\");\n if (typeof firstString === \"string\" && firstString.includes(\"<cXML\")) return firstString;\n }\n return c.req.text();\n}\n\nfunction htmlReceipt(ok: boolean, itemCount: number): string {\n return `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">\n<title>punchout-simulator — cart received</title>\n<style>\n body{font-family:system-ui,sans-serif;background:#0f172a;color:#e2e8f0;display:flex;\n min-height:100vh;align-items:center;justify-content:center;margin:0}\n .card{background:#1e293b;padding:2.5rem 3rem;border-radius:14px;text-align:center;\n box-shadow:0 10px 40px rgba(0,0,0,.4);max-width:420px}\n .icon{font-size:3rem}\n h1{font-size:1.25rem;margin:.5rem 0}\n p{color:#94a3b8;line-height:1.5}\n .ok{color:#34d399}.bad{color:#f87171}\n</style></head><body><div class=\"card\">\n <div class=\"icon ${ok ? \"ok\" : \"bad\"}\">${ok ? \"✓\" : \"⚠\"}</div>\n <h1>Cart returned to punchout-simulator</h1>\n <p>${ok ? `Received ${itemCount} item(s).` : \"The punchback had validation issues.\"}\n Switch back to the punchout-simulator tab to inspect the cart and build the OrderRequest.\n You can close this tab.</p>\n</div><script>setTimeout(()=>{try{window.close()}catch(e){}},1500)</script></body></html>`;\n}\n\npunchoutReturnRoute.post(\"/return\", async (c) => {\n const xml = await extractCxml(c);\n const doc = parseXml(xml);\n const cart = parseCart(doc);\n const sessionId =\n cart.sessionId || text(root(doc)?.Message?.PunchOutOrderMessage?.BuyerCookie) || \"unknown\";\n\n const connectionId = connectionForSession(sessionId);\n const conn = connectionId ? getConnection(connectionId) : undefined;\n\n const validation = validateDocument(xml, {\n connection: conn,\n expectedBuyerCookie: sessionId,\n forceDocType: \"PunchOutOrderMessage\",\n });\n\n if (connectionId) rememberSessionConnection(sessionId, connectionId);\n appendLog({\n sessionId,\n connectionId: connectionId ?? \"\",\n direction: \"in\",\n docType: \"PunchOutOrderMessage\",\n headers: { \"Content-Type\": c.req.header(\"content-type\") ?? \"\" },\n body: xml,\n contentType: c.req.header(\"content-type\") ?? undefined,\n validation,\n });\n\n setCart(cart);\n bus.emitCart(connectionId ?? \"\", cart);\n\n return c.html(htmlReceipt(validation.ok, cart.items.length));\n});\n","import { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport { bus } from \"../bus.js\";\n\n// Live log to the SPA via Server-Sent Events. Log traffic is server->client\n// only, so SSE (not WebSocket) is the right tool — spec sections 6 and 7.\n\nexport const streamRoute = new Hono();\n\nstreamRoute.get(\"/stream\", (c) => {\n return streamSSE(c, async (stream) => {\n let open = true;\n let id = 0;\n\n const unsubscribe = bus.onEvent((event) => {\n if (!open) return;\n void stream.writeSSE({\n id: String(id++),\n event: event.type,\n data: JSON.stringify(event),\n });\n });\n\n stream.onAbort(() => {\n open = false;\n unsubscribe();\n });\n\n await stream.writeSSE({ event: \"ready\", data: JSON.stringify({ ts: Date.now() }) });\n\n // Keep the connection alive through proxies with a periodic comment ping.\n while (open) {\n await stream.sleep(15000);\n if (!open) break;\n await stream.writeSSE({ event: \"ping\", data: JSON.stringify({ ts: Date.now() }) });\n }\n });\n});\n","import { Hono } from \"hono\";\nimport { getCart } from \"../cart-store.js\";\nimport { readAttachment } from \"../store/attachments.js\";\nimport { listSessions, readAllRecent, readSession } from \"../store/log.js\";\nimport { getPublicUrl } from \"../runtime.js\";\n\n// Read-only endpoints backing the SPA: sessions, log records, the active cart,\n// attachment downloads, and runtime info.\n\nexport const dataRoute = new Hono();\n\ndataRoute.get(\"/health\", (c) => c.json({ ok: true }));\n\ndataRoute.get(\"/runtime\", (c) =>\n c.json({ publicUrl: getPublicUrl(), callbackUrl: `${getPublicUrl()}/punchout/return` }),\n);\n\ndataRoute.get(\"/sessions\", (c) => c.json(listSessions()));\n\ndataRoute.get(\"/sessions/:id\", (c) => c.json(readSession(c.req.param(\"id\"))));\n\ndataRoute.get(\"/recent\", (c) => {\n const limit = Number(c.req.query(\"limit\") ?? \"200\");\n return c.json(readAllRecent(Number.isFinite(limit) ? limit : 200));\n});\n\ndataRoute.get(\"/cart/:sessionId\", (c) => {\n const cart = getCart(c.req.param(\"sessionId\"));\n return cart ? c.json(cart) : c.json({ error: \"no cart for session\" }, 404);\n});\n\ndataRoute.get(\"/attachments/:hash\", (c) => {\n const data = readAttachment(c.req.param(\"hash\"));\n if (!data) return c.json({ error: \"not found\" }, 404);\n c.header(\"Content-Type\", \"application/octet-stream\");\n return c.body(data as any);\n});\n","import { Hono } from \"hono\";\nimport { nanoid } from \"nanoid\";\nimport { getConnection } from \"../store/config.js\";\nimport { appendLog } from \"../store/log.js\";\nimport { saveAttachment } from \"../store/attachments.js\";\nimport { getPublicUrl } from \"../runtime.js\";\nimport {\n buildPunchOutOrderMessage,\n buildResponseStatus,\n buildSetupResponse,\n escapeXml,\n makePayloadId,\n} from \"../cxml/build.js\";\nimport { parseXml, root, text } from \"../cxml/parse.js\";\nimport {\n isMultipart,\n normalizeContentId,\n parseMultipartRelated,\n} from \"../cxml/multipart.js\";\nimport { validateDocument } from \"../cxml/validate.js\";\nimport type { AttachmentRef, CartItem, CatalogItem, Connection } from \"../cxml/types.js\";\n\n// Mode B (virtual-supplier / mock catalog) — spec sections 4, 10, 14. The tool\n// plays the supplier: it answers a buyer's SetupRequest, serves a mock catalog,\n// auto-submits a punchback, and ingests the buyer's OrderRequest. This is also\n// the built-in counterparty that lets Mode A be exercised end-to-end with no\n// external partner.\n\nexport const simRoute = new Hono();\n\nconst DEMO_CATALOG: CatalogItem[] = [\n {\n supplierPartId: \"WIDGET-001\",\n description: \"Premium Steel Widget\",\n unitPrice: 12.5,\n currency: \"USD\",\n uom: \"EA\",\n unspsc: \"31161500\",\n manufacturerPartId: \"MFR-W001\",\n manufacturerName: \"Acme Manufacturing\",\n },\n {\n supplierPartId: \"BOLT-250\",\n description: \"M8 Hex Bolt (pack of 250)\",\n unitPrice: 34.0,\n currency: \"USD\",\n uom: \"PK\",\n unspsc: \"31161600\",\n manufacturerPartId: \"MFR-B250\",\n manufacturerName: \"Acme Manufacturing\",\n },\n {\n supplierPartId: \"TAPE-RED\",\n description: \"Industrial Marking Tape, Red\",\n unitPrice: 5.75,\n currency: \"USD\",\n uom: \"RL\",\n unspsc: \"31201500\",\n },\n];\n\nfunction host(): string {\n try {\n return new URL(getPublicUrl()).host;\n } catch {\n return \"punchout-simulator\";\n }\n}\n\n// The BrowserFormPost URL is buyer-supplied (from the SetupRequest). It is later\n// rendered as an auto-submitted <form action>, so a non-http(s) scheme such as\n// `javascript:` would be an XSS vector — escaping HTML entities does not\n// neutralize the scheme. Allow only http(s); otherwise drop it.\nfunction safeHttpUrl(u: string | undefined): string {\n if (!u) return \"\";\n try {\n const parsed = new URL(u.trim());\n return parsed.protocol === \"http:\" || parsed.protocol === \"https:\" ? u.trim() : \"\";\n } catch {\n return \"\";\n }\n}\n\nfunction catalogOf(conn: Connection): CatalogItem[] {\n return conn.catalog && conn.catalog.length > 0 ? conn.catalog : DEMO_CATALOG;\n}\n\nfunction requireSupplier(conn: Connection | undefined): string | null {\n if (!conn) return \"connection not found\";\n if (conn.mode !== \"virtual-supplier\") return \"connection is not in virtual-supplier mode\";\n return null;\n}\n\n// --- 1. PunchOutSetupRequest in -> PunchOutSetupResponse out ------------------\n\nsimRoute.post(\"/:id/punchout\", async (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireSupplier(conn);\n if (err) return c.text(err, 400);\n\n const reqXml = await c.req.text();\n const doc = parseXml(reqXml);\n const reqRoot = root(doc)?.Request?.PunchOutSetupRequest;\n const buyerCookie = text(reqRoot?.BuyerCookie) || `pos-${nanoid(16)}`;\n const formPost = safeHttpUrl(text(reqRoot?.BrowserFormPost?.URL));\n\n const reqValidation = validateDocument(reqXml, {\n connection: conn,\n forceDocType: \"SetupRequest\",\n });\n appendLog({\n sessionId: buyerCookie,\n connectionId: conn!.id,\n direction: \"in\",\n docType: \"SetupRequest\",\n headers: { \"Content-Type\": c.req.header(\"content-type\") ?? \"\" },\n body: reqXml,\n validation: reqValidation,\n });\n\n const startPageUrl = `${getPublicUrl()}/sim/${conn!.id}/catalog?cookie=${encodeURIComponent(\n buyerCookie,\n )}&formpost=${encodeURIComponent(formPost)}`;\n\n const respXml = buildSetupResponse({\n payloadId: makePayloadId(host(), new Date().toISOString()),\n timestamp: new Date().toISOString(),\n startPageUrl,\n from: conn!.from,\n to: conn!.to,\n sender: conn!.sender,\n });\n appendLog({\n sessionId: buyerCookie,\n connectionId: conn!.id,\n direction: \"out\",\n docType: \"SetupResponse\",\n headers: { \"Content-Type\": \"text/xml; charset=UTF-8\" },\n body: respXml,\n validation: validateDocument(respXml, { forceDocType: \"SetupResponse\" }),\n });\n\n c.header(\"Content-Type\", \"text/xml; charset=UTF-8\");\n return c.body(respXml);\n});\n\n// --- 2. Catalog UI ------------------------------------------------------------\n\nsimRoute.get(\"/:id/catalog\", (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireSupplier(conn);\n if (err) return c.text(err, 400);\n const cookie = c.req.query(\"cookie\") ?? \"\";\n const formpost = c.req.query(\"formpost\") ?? \"\";\n const items = catalogOf(conn!);\n\n const rows = items\n .map(\n (it, i) => `<tr>\n <td><strong>${escapeHtml(it.description)}</strong><br><small>${escapeHtml(\n it.supplierPartId,\n )} · ${escapeHtml(it.uom)} · UNSPSC ${escapeHtml(it.unspsc)}</small></td>\n <td class=\"price\">${it.currency} ${it.unitPrice.toFixed(2)}</td>\n <td><input type=\"number\" name=\"q_${i}\" value=\"0\" min=\"0\" step=\"1\" inputmode=\"numeric\"></td>\n </tr>`,\n )\n .join(\"\\n\");\n\n return c.html(`<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeHtml(conn!.name)} — mock catalog</title>\n<style>\n body{font-family:system-ui,sans-serif;background:#0f172a;color:#e2e8f0;margin:0;padding:2rem}\n .wrap{max-width:720px;margin:0 auto}\n h1{font-size:1.4rem}.sub{color:#94a3b8;margin-bottom:1.5rem}\n table{width:100%;border-collapse:collapse;background:#1e293b;border-radius:12px;overflow:hidden}\n th,td{padding:.75rem 1rem;text-align:left;border-bottom:1px solid #334155}\n th{background:#0b1220;font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;color:#94a3b8}\n .price{white-space:nowrap;color:#fbbf24}\n input[type=number]{width:5rem;background:#0b1220;border:1px solid #334155;color:#e2e8f0;\n border-radius:6px;padding:.35rem .5rem}\n button{margin-top:1.5rem;background:#6366f1;color:#fff;border:0;border-radius:8px;\n padding:.7rem 1.4rem;font-size:1rem;cursor:pointer}\n button:hover{background:#4f46e5}\n</style></head><body><div class=\"wrap\">\n <h1>${escapeHtml(conn!.name)} <small>(virtual supplier)</small></h1>\n <div class=\"sub\">Mock catalog served by punchout-simulator. Set quantities and return the cart.</div>\n <form method=\"post\" action=\"${getPublicUrl()}/sim/${conn!.id}/checkout\">\n <input type=\"hidden\" name=\"cookie\" value=\"${escapeHtml(cookie)}\">\n <input type=\"hidden\" name=\"formpost\" value=\"${escapeHtml(formpost)}\">\n <table><thead><tr><th>Item</th><th>Price</th><th>Qty</th></tr></thead>\n <tbody>${rows}</tbody></table>\n <button type=\"submit\">Return cart to buyer →</button>\n </form>\n</div></body></html>`);\n});\n\n// --- 3. Checkout -> auto-submit punchback ------------------------------------\n\nsimRoute.post(\"/:id/checkout\", async (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireSupplier(conn);\n if (err) return c.text(err, 400);\n\n const form = await c.req.parseBody();\n const cookie = String(form.cookie ?? `pos-${nanoid(16)}`);\n // Re-validate the scheme here too: this value round-trips through the catalog\n // page, so never trust it blind when rendering the auto-submitted form action.\n const formpost = safeHttpUrl(String(form.formpost ?? \"\"));\n const catalog = catalogOf(conn!);\n\n const items: CartItem[] = [];\n catalog.forEach((it, i) => {\n const qty = Number(form[`q_${i}`] ?? 0);\n if (qty > 0) {\n items.push({\n quantity: qty,\n supplierPartId: it.supplierPartId,\n description: it.description,\n uom: it.uom,\n unitPriceAmount: it.unitPrice,\n currency: it.currency,\n classificationDomain: \"UNSPSC\",\n classification: it.unspsc,\n manufacturerPartId: it.manufacturerPartId,\n manufacturerName: it.manufacturerName,\n });\n }\n });\n\n const currency = items[0]?.currency ?? \"USD\";\n const xml = buildPunchOutOrderMessage({\n from: conn!.from,\n to: conn!.to,\n sender: conn!.sender,\n buyerCookie: cookie,\n payloadId: makePayloadId(host(), new Date().toISOString()),\n timestamp: new Date().toISOString(),\n currency,\n items,\n });\n\n appendLog({\n sessionId: cookie,\n connectionId: conn!.id,\n direction: \"out\",\n docType: \"PunchOutOrderMessage\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: xml,\n validation: validateDocument(xml, { connection: conn, forceDocType: \"PunchOutOrderMessage\" }),\n });\n\n // Browser-driven auto-submit form POST of cxml-urlencoded to the buyer's\n // BrowserFormPost URL (spec sections 3 and 11).\n return c.html(`<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">\n<title>Returning cart…</title></head>\n<body onload=\"document.forms[0].submit()\" style=\"font-family:system-ui;background:#0f172a;color:#e2e8f0\">\n <p style=\"padding:2rem\">Returning cart to the buyer…</p>\n <form method=\"post\" action=\"${escapeHtml(formpost)}\">\n <input type=\"hidden\" name=\"cxml-urlencoded\" value=\"${escapeHtml(xml)}\">\n <noscript><button type=\"submit\">Continue</button></noscript>\n </form>\n</body></html>`);\n});\n\n// --- 4. OrderRequest in -> OrderResponse out ----------------------------------\n\nsimRoute.post(\"/:id/order\", async (c) => {\n const conn = getConnection(c.req.param(\"id\"));\n const err = requireSupplier(conn);\n if (err) return c.text(err, 400);\n\n const ct = c.req.header(\"content-type\") ?? \"\";\n const raw = Buffer.from(await c.req.arrayBuffer());\n\n let xml: string;\n const availableContentIds = new Set<string>();\n const savedRefs: AttachmentRef[] = [];\n\n if (isMultipart(ct)) {\n const mp = parseMultipartRelated(raw, ct);\n xml = mp.root?.body.toString(\"utf8\") ?? \"\";\n for (const part of mp.parts) {\n if (part === mp.root) continue;\n const cid = normalizeContentId(part.contentId);\n if (cid) availableContentIds.add(cid);\n savedRefs.push(\n saveAttachment(part.body, {\n contentId: cid,\n contentType: part.contentType ?? \"application/octet-stream\",\n }),\n );\n }\n } else {\n xml = raw.toString(\"utf8\");\n }\n\n const doc = parseXml(xml);\n const sessionId = findSessionForOrder(doc) ?? `order-${nanoid(8)}`;\n\n const validation = validateDocument(xml, {\n connection: conn,\n forceDocType: \"OrderRequest\",\n availableContentIds: isMultipart(ct) ? availableContentIds : undefined,\n });\n\n appendLog({\n sessionId,\n connectionId: conn!.id,\n direction: \"in\",\n docType: \"OrderRequest\",\n headers: { \"Content-Type\": ct },\n body: xml,\n contentType: ct,\n validation,\n attachments: savedRefs,\n });\n\n const ok = validation.ok;\n const respXml = buildResponseStatus({\n payloadId: makePayloadId(host(), new Date().toISOString()),\n timestamp: new Date().toISOString(),\n statusCode: ok ? \"200\" : \"400\",\n statusText: ok ? \"OK\" : \"Bad Request\",\n from: conn!.from,\n to: conn!.to,\n sender: conn!.sender,\n });\n appendLog({\n sessionId,\n connectionId: conn!.id,\n direction: \"out\",\n docType: \"OrderResponse\",\n headers: { \"Content-Type\": \"text/xml; charset=UTF-8\" },\n body: respXml,\n validation: validateDocument(respXml, { forceDocType: \"OrderResponse\" }),\n });\n\n c.header(\"Content-Type\", \"text/xml; charset=UTF-8\");\n return c.body(respXml, ok ? 200 : 400);\n});\n\n// Best-effort: correlate an inbound OrderRequest back to a known session. cXML\n// OrderRequest has no BuyerCookie, so we cannot strictly correlate — group it\n// under the order's payloadID host as a stable key.\nfunction findSessionForOrder(doc: ReturnType<typeof parseXml>): string | undefined {\n const header = root(doc)?.Request?.OrderRequest?.OrderRequestHeader;\n const orderId = header ? attrOf(header, \"orderID\") : undefined;\n return orderId ? `order-${orderId}` : undefined;\n}\n\nfunction attrOf(node: any, name: string): string | undefined {\n const v = node?.[`@_${name}`];\n return v == null ? undefined : String(v);\n}\n\nfunction escapeHtml(s: string): string {\n return escapeXml(s);\n}\n","import { createConnection, listConnections } from \"./store/config.js\";\nimport { getPublicUrl } from \"./runtime.js\";\n\n// On first run (empty config), seed a self-contained demo pair: a built-in\n// virtual-supplier and a virtual-buyer pointed at it. This makes the full Mode A\n// roundtrip runnable immediately with no external partner.\nexport async function seedDemoIfEmpty(): Promise<void> {\n if (listConnections().length > 0) return;\n\n const supplier = await createConnection({\n id: \"demo-supplier\",\n name: \"Demo Supplier (built-in mock)\",\n mode: \"virtual-supplier\",\n from: { domain: \"DUNS\", identity: \"987654321\" }, // supplier identity (the tool)\n to: { domain: \"DUNS\", identity: \"123456789\" }, // buyer identity (counterparty)\n sender: { domain: \"DUNS\", identity: \"987654321\" },\n sharedSecret: \"demo-secret\",\n deploymentMode: \"test\",\n authStyle: \"SharedSecret\",\n catalog: [],\n });\n\n await createConnection({\n id: \"demo-buyer\",\n name: \"Demo Buyer → built-in supplier\",\n mode: \"virtual-buyer\",\n from: { domain: \"DUNS\", identity: \"123456789\" }, // buyer identity (the tool)\n to: { domain: \"DUNS\", identity: \"987654321\" }, // supplier identity (counterparty)\n sender: { domain: \"DUNS\", identity: \"123456789\" },\n sharedSecret: \"demo-secret\",\n deploymentMode: \"test\",\n authStyle: \"SharedSecret\",\n punchoutUrl: `${getPublicUrl()}/sim/${supplier.id}/punchout`,\n orderUrl: `${getPublicUrl()}/sim/${supplier.id}/order`,\n });\n}\n"],"mappings":"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","names":["existsSync","Hono","Hono","nanoid","nanoid","nanoid","existsSync","readFileSync","resolve","nanoid","nanoid","root","resolve","existsSync","readFileSync","nanoid","host","header","header","Hono","nanoid","Hono","Hono","Hono","Hono","Hono","Hono","Hono","nanoid","Hono","host","nanoid","header","Hono","existsSync"]}