punchout-simulator 0.1.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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/server/cli.js +1889 -0
  4. package/dist/server/cli.js.map +1 -0
  5. package/dist/web/assets/abap-BrgZPUOV.js +6 -0
  6. package/dist/web/assets/apex-DyP6w7ZV.js +6 -0
  7. package/dist/web/assets/azcli-BaLxmfj-.js +6 -0
  8. package/dist/web/assets/bat-CFOPXBzS.js +6 -0
  9. package/dist/web/assets/bicep-BfEKNvv3.js +7 -0
  10. package/dist/web/assets/cameligo-BFG1Mk7z.js +6 -0
  11. package/dist/web/assets/clojure-DTECt2xU.js +6 -0
  12. package/dist/web/assets/codicon-DCmgc-ay.ttf +0 -0
  13. package/dist/web/assets/coffee-CDGzqUPQ.js +6 -0
  14. package/dist/web/assets/cpp-CLLBncYj.js +6 -0
  15. package/dist/web/assets/csharp-dUCx_-0o.js +6 -0
  16. package/dist/web/assets/csp-5Rap-vPy.js +6 -0
  17. package/dist/web/assets/css-D3h14YRZ.js +8 -0
  18. package/dist/web/assets/cssMode-DLffFuN6.js +9 -0
  19. package/dist/web/assets/cypher-DrQuvNYM.js +6 -0
  20. package/dist/web/assets/dart-CFKIUWau.js +6 -0
  21. package/dist/web/assets/dockerfile-Zznr-cwX.js +6 -0
  22. package/dist/web/assets/ecl-Ce3n6wWz.js +6 -0
  23. package/dist/web/assets/editor.worker-BCzxt1at.js +12 -0
  24. package/dist/web/assets/elixir-deUWdS0T.js +6 -0
  25. package/dist/web/assets/flow9-i9-g7ZhI.js +6 -0
  26. package/dist/web/assets/freemarker2-zfr9jUGh.js +8 -0
  27. package/dist/web/assets/fsharp-CzKuDChf.js +6 -0
  28. package/dist/web/assets/go-Cphgjts3.js +6 -0
  29. package/dist/web/assets/graphql-Cg7bfA9N.js +6 -0
  30. package/dist/web/assets/handlebars-M_QseyaG.js +6 -0
  31. package/dist/web/assets/hcl-0cvrggvQ.js +6 -0
  32. package/dist/web/assets/html-BRMBHmCq.js +6 -0
  33. package/dist/web/assets/htmlMode-CicmEJMR.js +9 -0
  34. package/dist/web/assets/index-Cm4lvUlh.js +800 -0
  35. package/dist/web/assets/index-sxaLM6ld.css +1 -0
  36. package/dist/web/assets/ini-Drc7WvVn.js +6 -0
  37. package/dist/web/assets/java-B_fMsGYe.js +6 -0
  38. package/dist/web/assets/javascript-D6_vZEGx.js +6 -0
  39. package/dist/web/assets/jsonMode-CTxq7vAq.js +15 -0
  40. package/dist/web/assets/julia-Bqgm2twL.js +6 -0
  41. package/dist/web/assets/kotlin-BSkB5QuD.js +6 -0
  42. package/dist/web/assets/less-BsTHnhdd.js +7 -0
  43. package/dist/web/assets/lexon-YWi4-JPR.js +6 -0
  44. package/dist/web/assets/liquid-BUpPE-Wb.js +6 -0
  45. package/dist/web/assets/lua-nf6ki56Z.js +6 -0
  46. package/dist/web/assets/m3-Cpb6xl2v.js +6 -0
  47. package/dist/web/assets/markdown-DSZPf7rp.js +6 -0
  48. package/dist/web/assets/mdx-ymOE7fzM.js +6 -0
  49. package/dist/web/assets/mips-B_c3zf-v.js +6 -0
  50. package/dist/web/assets/msdax-rUNN04Wq.js +6 -0
  51. package/dist/web/assets/mysql-DDwshQtU.js +6 -0
  52. package/dist/web/assets/objective-c-B5zXfXm9.js +6 -0
  53. package/dist/web/assets/pascal-CXOwvkN_.js +6 -0
  54. package/dist/web/assets/pascaligo-Bc-ZgV77.js +6 -0
  55. package/dist/web/assets/perl-CwNk8-XU.js +6 -0
  56. package/dist/web/assets/pgsql-tGk8EFnU.js +6 -0
  57. package/dist/web/assets/php-CpIb_Oan.js +6 -0
  58. package/dist/web/assets/pla-B03wrqEc.js +6 -0
  59. package/dist/web/assets/postiats-BKlk5iyT.js +6 -0
  60. package/dist/web/assets/powerquery-Bhzvs7bI.js +6 -0
  61. package/dist/web/assets/powershell-Dd3NCNK9.js +6 -0
  62. package/dist/web/assets/protobuf-COyEY5Pt.js +7 -0
  63. package/dist/web/assets/pug-BaJupSGV.js +6 -0
  64. package/dist/web/assets/python-Db74sog5.js +6 -0
  65. package/dist/web/assets/qsharp-DXyYeYxl.js +6 -0
  66. package/dist/web/assets/r-CdQndTaG.js +6 -0
  67. package/dist/web/assets/razor-BxQoOni_.js +6 -0
  68. package/dist/web/assets/redis-CVwtpugi.js +6 -0
  69. package/dist/web/assets/redshift-25W9uPmb.js +6 -0
  70. package/dist/web/assets/restructuredtext-DfzH4Xui.js +6 -0
  71. package/dist/web/assets/ruby-Cp1zYvxS.js +6 -0
  72. package/dist/web/assets/rust-D5C2fndG.js +6 -0
  73. package/dist/web/assets/sb-CDntyWJ8.js +6 -0
  74. package/dist/web/assets/scala-BoFRg7Ot.js +6 -0
  75. package/dist/web/assets/scheme-Bio4gycK.js +6 -0
  76. package/dist/web/assets/scss-4Ik7cdeQ.js +8 -0
  77. package/dist/web/assets/shell-CX-rkNHf.js +6 -0
  78. package/dist/web/assets/solidity-Tw7wswEv.js +6 -0
  79. package/dist/web/assets/sophia-C5WLch3f.js +6 -0
  80. package/dist/web/assets/sparql-DHaeiCBh.js +6 -0
  81. package/dist/web/assets/sql-CCSDG5nI.js +6 -0
  82. package/dist/web/assets/st-pnP8ivHi.js +6 -0
  83. package/dist/web/assets/swift-DwJ7jVG9.js +8 -0
  84. package/dist/web/assets/systemverilog-B9Xyijhd.js +6 -0
  85. package/dist/web/assets/tcl-DnHyzjbg.js +6 -0
  86. package/dist/web/assets/tsMode-C9sm5xMG.js +16 -0
  87. package/dist/web/assets/twig-CPajHgWi.js +6 -0
  88. package/dist/web/assets/typescript-Ctr2X0xG.js +6 -0
  89. package/dist/web/assets/typespec-D-MeaMDU.js +6 -0
  90. package/dist/web/assets/vb-DgyLZaXg.js +6 -0
  91. package/dist/web/assets/wgsl-BIv9DU6q.js +303 -0
  92. package/dist/web/assets/xml-DGpUXjuk.js +6 -0
  93. package/dist/web/assets/yaml-6Dpo9WGU.js +6 -0
  94. package/dist/web/index.html +13 -0
  95. package/package.json +74 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Slawomir Szostak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # punchout-simulator
2
+
3
+ A developer tool for testing **cXML PunchOut** integrations by acting as a
4
+ **virtual counterparty**. It plays the missing side of the conversation, so you
5
+ can exercise a PunchOut integration end-to-end without finding a cooperative
6
+ real partner to send/receive test traffic.
7
+
8
+ It is role-neutral and runs in two modes (mirror images of each other):
9
+
10
+ - **Mode A — Virtual Buyer** *(primary)*: the tool acts as the procurement
11
+ system. Point it at a supplier's catalog (often `localhost`/staging) to verify
12
+ their PunchOut system without needing a real Ariba/Coupa tenant. Also lets a
13
+ buyer-side developer test against real suppliers.
14
+ - **Mode B — Virtual Supplier / mock catalog**: the tool acts as the supplier —
15
+ receiving a real buyer's requests, serving a mock catalog, returning a
16
+ punchback and accepting an OrderRequest. Lets a buyer-side developer test their
17
+ outbound generation without asking a vendor for a test catalog.
18
+
19
+ Protocol scope: **cXML only**.
20
+
21
+ ---
22
+
23
+ ## Quick start
24
+
25
+ ```bash
26
+ npx punchout-simulator
27
+ ```
28
+
29
+ That's it — no install, no build. It boots a local server, opens your browser,
30
+ and seeds a **built-in demo**: a virtual buyer wired to a built-in mock supplier,
31
+ so you can run the entire roundtrip immediately:
32
+
33
+ 1. Open the **Demo Buyer → built-in supplier** connection.
34
+ 2. **Send SetupRequest** → the mock supplier replies with a StartPage.
35
+ 3. **Open the catalog**, set quantities, **return the cart** — the punchback
36
+ lands back in the app live.
37
+ 4. **Send the OrderRequest** (optionally with attachments, optionally with the
38
+ dangling-`cid` test) and inspect the supplier's response.
39
+
40
+ Every document — inbound and outbound — is validated and logged.
41
+
42
+ ### Other ways to run
43
+
44
+ ```bash
45
+ npm i -g punchout-simulator && punchout-simulator # persistent install
46
+ ```
47
+
48
+ ```bash
49
+ # Docker
50
+ docker run -p 8080:8080 -v "$PWD/data:/data" punchout-simulator
51
+ ```
52
+
53
+ ### CLI options
54
+
55
+ ```
56
+ -p, --port <n> Port to listen on (default 8080)
57
+ -d, --data-dir <path> Where to store config + logs (default ./data)
58
+ --public-url <url> Externally reachable base URL (default http://localhost:<port>)
59
+ Set this when fronting the tool with ngrok/cloudflared.
60
+ --no-open Do not open a browser on start
61
+ --no-seed Do not seed the built-in demo connections on first run
62
+ --dev Dev mode (do not serve the SPA, do not open a browser)
63
+ -h, --help Show help
64
+ ```
65
+
66
+ ---
67
+
68
+ ## What it checks (validation / linting)
69
+
70
+ Validation is a **first-class, bidirectional** feature — it runs on every
71
+ document in both directions, and results are surfaced per message in the UI
72
+ (errors, warnings and info). For a seller, the tool is as much a *"did my catalog
73
+ emit correct cXML?"* linter as a transport driver.
74
+
75
+ General checks: well-formedness, `payloadID`/`timestamp` presence, and
76
+ `From`/`To`/`Sender` credential + `SharedSecret` consistency with the connection.
77
+
78
+ Document-specific:
79
+
80
+ | Document | Checks |
81
+ |---|---|
82
+ | **PunchOutSetupResponse** | `Status` present & `200`; valid `StartPage/URL` |
83
+ | **PunchOutOrderMessage** (punchback) | `BuyerCookie` matches the session; header `Total`/`Money`+currency; each `ItemIn` has quantity, `SupplierPartID`, `UnitPrice`+currency, `Description`, `UnitOfMeasure`, `Classification`@domain; **Total consistency** (sum of line totals) |
84
+ | **OrderRequest** | `orderID`/`orderDate`/`Total`; `ShipTo`/`BillTo`; each `ItemOut`; **attachment `cid:` resolution** (see below) |
85
+ | **OrderResponse** | `Status` code present / not an error |
86
+
87
+ > Note: full cXML DTD validation would require a native validating XML parser,
88
+ > which would hurt `npx` portability. Instead the tool does well-formedness plus
89
+ > the thorough field-level rules above — the high-value half of the linter.
90
+
91
+ ### The dangling-`cid` attachment test
92
+
93
+ `multipart/related` is the fiddly part of cXML order ingestion. The tool can send
94
+ an OrderRequest whose `<Attachment><URL>cid:XXX</URL></Attachment>` references a
95
+ `Content-ID` that is **deliberately absent** from the envelope, to verify the
96
+ receiver detects the missing attachment. `<Comments>` (and therefore
97
+ `<Attachment>`) is scanned at **both** levels: `OrderRequestHeader` and each
98
+ `ItemOut`.
99
+
100
+ ---
101
+
102
+ ## Network reachability
103
+
104
+ - **Mode A rarely needs a tunnel.** The punchback is a browser auto-submit from
105
+ *your own browser*, so it reaches the tool's `localhost` callback even when the
106
+ supplier catalog is remote. SetupRequest/OrderRequest are server-to-server
107
+ *outbound* from the tool.
108
+ - **Mode B may need the tool publicly reachable.** A real buyer system sends
109
+ SetupRequest/OrderRequest *inbound* to the tool. If that system is remote, run
110
+ behind ngrok/cloudflared and pass `--public-url <https://...>`.
111
+
112
+ ---
113
+
114
+ ## Architecture
115
+
116
+ A single npm package, full TypeScript, single origin (the SPA is served by the
117
+ backend, so there is no CORS between them).
118
+
119
+ | Layer | Choice |
120
+ |---|---|
121
+ | Backend | [Hono](https://hono.dev) + `@hono/node-server` (SSE live log, static SPA) |
122
+ | Frontend | React + Vite, [Monaco](https://microsoft.github.io/monaco-editor/) for cXML edit-before-send |
123
+ | Real-time | Server-Sent Events |
124
+ | XML parsing | `fast-xml-parser` |
125
+ | cXML building | template literals (full control over shape/ordering/`xml:lang`) |
126
+ | multipart/related | hand-assembled (`Buffer` + boundary) |
127
+ | Storage | `lowdb` (`config.json`) for connections · append-only JSONL per session for logs · separate files for attachments |
128
+
129
+ ```
130
+ src/
131
+ ├─ web/ React + Vite SPA
132
+ └─ server/ Hono app, routes, cXML engine, storage, CLI
133
+ └─ cxml/ build · parse · validate · multipart · types
134
+ ```
135
+
136
+ ### Endpoints
137
+
138
+ - `*/api/connections` — CRUD for connection configs
139
+ - `POST /api/connections/:id/setup` — send the SetupRequest, capture + validate the response
140
+ - `POST /api/connections/:id/order` — send the OrderRequest (multipart if attachments), capture + validate
141
+ - `POST /punchout/return` — callback receiving the punchback auto-submit
142
+ - `GET /api/stream` — SSE live log
143
+ - `/sim/:id/*` — Mode B mock supplier (punchout · catalog · checkout · order)
144
+
145
+ ---
146
+
147
+ ## Development
148
+
149
+ ```bash
150
+ npm install
151
+ npm run dev # Vite dev server + backend with proxy
152
+ npm run build # vite build -> dist/web ; tsup -> dist/server
153
+ npm test # vitest (unit + integration roundtrip)
154
+ npm run typecheck
155
+ node scripts/smoke.mjs # full roundtrip over HTTP (server must be running)
156
+ node scripts/verify-ui.mjs # headless-browser end-to-end (needs `npx playwright install chromium`)
157
+ ```
158
+
159
+ ---
160
+
161
+ ## License
162
+
163
+ MIT © Slawomir Szostak