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.
- package/LICENSE +21 -0
- package/README.md +163 -0
- package/dist/server/cli.js +1889 -0
- package/dist/server/cli.js.map +1 -0
- package/dist/web/assets/abap-BrgZPUOV.js +6 -0
- package/dist/web/assets/apex-DyP6w7ZV.js +6 -0
- package/dist/web/assets/azcli-BaLxmfj-.js +6 -0
- package/dist/web/assets/bat-CFOPXBzS.js +6 -0
- package/dist/web/assets/bicep-BfEKNvv3.js +7 -0
- package/dist/web/assets/cameligo-BFG1Mk7z.js +6 -0
- package/dist/web/assets/clojure-DTECt2xU.js +6 -0
- package/dist/web/assets/codicon-DCmgc-ay.ttf +0 -0
- package/dist/web/assets/coffee-CDGzqUPQ.js +6 -0
- package/dist/web/assets/cpp-CLLBncYj.js +6 -0
- package/dist/web/assets/csharp-dUCx_-0o.js +6 -0
- package/dist/web/assets/csp-5Rap-vPy.js +6 -0
- package/dist/web/assets/css-D3h14YRZ.js +8 -0
- package/dist/web/assets/cssMode-DLffFuN6.js +9 -0
- package/dist/web/assets/cypher-DrQuvNYM.js +6 -0
- package/dist/web/assets/dart-CFKIUWau.js +6 -0
- package/dist/web/assets/dockerfile-Zznr-cwX.js +6 -0
- package/dist/web/assets/ecl-Ce3n6wWz.js +6 -0
- package/dist/web/assets/editor.worker-BCzxt1at.js +12 -0
- package/dist/web/assets/elixir-deUWdS0T.js +6 -0
- package/dist/web/assets/flow9-i9-g7ZhI.js +6 -0
- package/dist/web/assets/freemarker2-zfr9jUGh.js +8 -0
- package/dist/web/assets/fsharp-CzKuDChf.js +6 -0
- package/dist/web/assets/go-Cphgjts3.js +6 -0
- package/dist/web/assets/graphql-Cg7bfA9N.js +6 -0
- package/dist/web/assets/handlebars-M_QseyaG.js +6 -0
- package/dist/web/assets/hcl-0cvrggvQ.js +6 -0
- package/dist/web/assets/html-BRMBHmCq.js +6 -0
- package/dist/web/assets/htmlMode-CicmEJMR.js +9 -0
- package/dist/web/assets/index-Cm4lvUlh.js +800 -0
- package/dist/web/assets/index-sxaLM6ld.css +1 -0
- package/dist/web/assets/ini-Drc7WvVn.js +6 -0
- package/dist/web/assets/java-B_fMsGYe.js +6 -0
- package/dist/web/assets/javascript-D6_vZEGx.js +6 -0
- package/dist/web/assets/jsonMode-CTxq7vAq.js +15 -0
- package/dist/web/assets/julia-Bqgm2twL.js +6 -0
- package/dist/web/assets/kotlin-BSkB5QuD.js +6 -0
- package/dist/web/assets/less-BsTHnhdd.js +7 -0
- package/dist/web/assets/lexon-YWi4-JPR.js +6 -0
- package/dist/web/assets/liquid-BUpPE-Wb.js +6 -0
- package/dist/web/assets/lua-nf6ki56Z.js +6 -0
- package/dist/web/assets/m3-Cpb6xl2v.js +6 -0
- package/dist/web/assets/markdown-DSZPf7rp.js +6 -0
- package/dist/web/assets/mdx-ymOE7fzM.js +6 -0
- package/dist/web/assets/mips-B_c3zf-v.js +6 -0
- package/dist/web/assets/msdax-rUNN04Wq.js +6 -0
- package/dist/web/assets/mysql-DDwshQtU.js +6 -0
- package/dist/web/assets/objective-c-B5zXfXm9.js +6 -0
- package/dist/web/assets/pascal-CXOwvkN_.js +6 -0
- package/dist/web/assets/pascaligo-Bc-ZgV77.js +6 -0
- package/dist/web/assets/perl-CwNk8-XU.js +6 -0
- package/dist/web/assets/pgsql-tGk8EFnU.js +6 -0
- package/dist/web/assets/php-CpIb_Oan.js +6 -0
- package/dist/web/assets/pla-B03wrqEc.js +6 -0
- package/dist/web/assets/postiats-BKlk5iyT.js +6 -0
- package/dist/web/assets/powerquery-Bhzvs7bI.js +6 -0
- package/dist/web/assets/powershell-Dd3NCNK9.js +6 -0
- package/dist/web/assets/protobuf-COyEY5Pt.js +7 -0
- package/dist/web/assets/pug-BaJupSGV.js +6 -0
- package/dist/web/assets/python-Db74sog5.js +6 -0
- package/dist/web/assets/qsharp-DXyYeYxl.js +6 -0
- package/dist/web/assets/r-CdQndTaG.js +6 -0
- package/dist/web/assets/razor-BxQoOni_.js +6 -0
- package/dist/web/assets/redis-CVwtpugi.js +6 -0
- package/dist/web/assets/redshift-25W9uPmb.js +6 -0
- package/dist/web/assets/restructuredtext-DfzH4Xui.js +6 -0
- package/dist/web/assets/ruby-Cp1zYvxS.js +6 -0
- package/dist/web/assets/rust-D5C2fndG.js +6 -0
- package/dist/web/assets/sb-CDntyWJ8.js +6 -0
- package/dist/web/assets/scala-BoFRg7Ot.js +6 -0
- package/dist/web/assets/scheme-Bio4gycK.js +6 -0
- package/dist/web/assets/scss-4Ik7cdeQ.js +8 -0
- package/dist/web/assets/shell-CX-rkNHf.js +6 -0
- package/dist/web/assets/solidity-Tw7wswEv.js +6 -0
- package/dist/web/assets/sophia-C5WLch3f.js +6 -0
- package/dist/web/assets/sparql-DHaeiCBh.js +6 -0
- package/dist/web/assets/sql-CCSDG5nI.js +6 -0
- package/dist/web/assets/st-pnP8ivHi.js +6 -0
- package/dist/web/assets/swift-DwJ7jVG9.js +8 -0
- package/dist/web/assets/systemverilog-B9Xyijhd.js +6 -0
- package/dist/web/assets/tcl-DnHyzjbg.js +6 -0
- package/dist/web/assets/tsMode-C9sm5xMG.js +16 -0
- package/dist/web/assets/twig-CPajHgWi.js +6 -0
- package/dist/web/assets/typescript-Ctr2X0xG.js +6 -0
- package/dist/web/assets/typespec-D-MeaMDU.js +6 -0
- package/dist/web/assets/vb-DgyLZaXg.js +6 -0
- package/dist/web/assets/wgsl-BIv9DU6q.js +303 -0
- package/dist/web/assets/xml-DGpUXjuk.js +6 -0
- package/dist/web/assets/yaml-6Dpo9WGU.js +6 -0
- package/dist/web/index.html +13 -0
- 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
|