punchout-simulator 0.8.0 → 0.8.2

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/README.md CHANGED
@@ -187,6 +187,26 @@ them up there, then run them from **Sessions**.
187
187
  - **Mode B may need the tool publicly reachable.** A real buyer system sends
188
188
  SetupRequest/OrderRequest *inbound* to the tool. If that system is remote, run
189
189
  behind ngrok/cloudflared and pass `--public-url <https://...>`.
190
+ - **Behind a corporate proxy?** Node's `fetch` ignores the system proxy by
191
+ default, so on a locked-down network an outbound SetupRequest/OrderRequest can
192
+ hang until it times out and shows **`HTTP 0` / "operation was aborted"** even
193
+ though the endpoint works in Postman. The tool honours the standard
194
+ `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` environment variables — set them and
195
+ it routes outbound cXML through the proxy (loopback/`localhost` always bypasses
196
+ it, so the built-in mock still works). Works on Windows and Linux:
197
+
198
+ ```bash
199
+ # Linux/macOS
200
+ HTTPS_PROXY=http://proxy.corp:8080 npx punchout-simulator
201
+ ```
202
+ ```powershell
203
+ # Windows PowerShell
204
+ $env:HTTPS_PROXY="http://proxy.corp:8080"; npx punchout-simulator
205
+ ```
206
+
207
+ > Note: a Windows *system* proxy (set in Windows/Edge settings, or via a PAC
208
+ > file) is not an environment variable — set `HTTPS_PROXY` explicitly to the
209
+ > proxy URL your IT uses.
190
210
 
191
211
  ---
192
212
 
@@ -3041,6 +3041,50 @@ async function seedDemoIfEmpty() {
3041
3041
  });
3042
3042
  }
3043
3043
 
3044
+ // src/server/proxy.ts
3045
+ import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
3046
+ var LOOPBACK = ["localhost", "127.0.0.1", "::1"];
3047
+ function redactProxyUrl(url) {
3048
+ try {
3049
+ const u = new URL(url);
3050
+ if (u.username || u.password) {
3051
+ u.username = "";
3052
+ u.password = "";
3053
+ return u.toString();
3054
+ }
3055
+ return url;
3056
+ } catch {
3057
+ return url;
3058
+ }
3059
+ }
3060
+ function mergeNoProxy(existing) {
3061
+ const have = (existing ?? "").split(",").map((s) => s.trim()).filter(Boolean);
3062
+ const lower = new Set(have.map((s) => s.toLowerCase()));
3063
+ const merged = [...have];
3064
+ for (const h of LOOPBACK) if (!lower.has(h)) merged.push(h);
3065
+ return merged.join(",");
3066
+ }
3067
+ function detectProxy(env = process.env) {
3068
+ const httpProxy = env.HTTP_PROXY || env.http_proxy || void 0;
3069
+ const httpsProxy = env.HTTPS_PROXY || env.https_proxy || void 0;
3070
+ return {
3071
+ httpProxy,
3072
+ httpsProxy,
3073
+ noProxy: mergeNoProxy(env.NO_PROXY || env.no_proxy),
3074
+ enabled: !!(httpProxy || httpsProxy)
3075
+ };
3076
+ }
3077
+ function setupProxy(env = process.env, log = (m) => console.log(m)) {
3078
+ const s = detectProxy(env);
3079
+ if (!s.enabled) return null;
3080
+ env.NO_PROXY = s.noProxy;
3081
+ env.no_proxy = s.noProxy;
3082
+ setGlobalDispatcher(new EnvHttpProxyAgent());
3083
+ const via = s.httpsProxy ? redactProxyUrl(s.httpsProxy) : redactProxyUrl(s.httpProxy ?? "");
3084
+ log(` proxy: outbound cXML via ${via} (NO_PROXY=${s.noProxy})`);
3085
+ return s;
3086
+ }
3087
+
3044
3088
  // src/server/cli.ts
3045
3089
  function parseFlags(argv) {
3046
3090
  const flags = {
@@ -3091,7 +3135,7 @@ function parseFlags(argv) {
3091
3135
  }
3092
3136
  return flags;
3093
3137
  }
3094
- var LOOPBACK = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "[::1]", ""]);
3138
+ var LOOPBACK2 = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "[::1]", ""]);
3095
3139
  function hostnameOf(url) {
3096
3140
  try {
3097
3141
  return new URL(url).hostname;
@@ -3127,9 +3171,10 @@ Options:
3127
3171
  }
3128
3172
  async function main() {
3129
3173
  const flags = parseFlags(process.argv.slice(2));
3174
+ setupProxy();
3130
3175
  const publicUrl = flags.publicUrl ?? `http://localhost:${flags.port}`;
3131
3176
  const bindHost = flags.host ?? "127.0.0.1";
3132
- const exposed = !LOOPBACK.has(hostnameOf(publicUrl)) || !LOOPBACK.has(bindHost);
3177
+ const exposed = !LOOPBACK2.has(hostnameOf(publicUrl)) || !LOOPBACK2.has(bindHost);
3133
3178
  const token = flags.token || (exposed ? nanoid7(24) : void 0);
3134
3179
  setDataDir(flags.dataDir);
3135
3180
  setRuntime({ port: flags.port, publicUrl, token, version: readVersion() });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "punchout-simulator",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
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",
@@ -52,7 +52,8 @@
52
52
  "hono": "^4.6.14",
53
53
  "lowdb": "^7.0.1",
54
54
  "nanoid": "^5.0.9",
55
- "open": "^10.1.0"
55
+ "open": "^10.1.0",
56
+ "undici": "^6.26.0"
56
57
  },
57
58
  "devDependencies": {
58
59
  "@monaco-editor/react": "^4.6.0",