integration-tour 1.0.7 → 1.0.9

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 (2) hide show
  1. package/dist/cli.js +65 -16
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -5281,7 +5281,38 @@ function secretName(name) {
5281
5281
  if (/idempotency/i.test(name)) return false;
5282
5282
  return /secret|passw(or)?d|pwd|token|api[-_]?key|apikey|credential|signature|session|cookie|bearer|jwt|^auth(orization)?$/i.test(name) || /(^|[_-])key$|[a-z0-9]Key$|^key$/i.test(name);
5283
5283
  }
5284
- var SECRET_VALUE = /^(sk|rk)_(live|test)_|^gh[pousr]_|^github_pat_|^xox[abposr]-|^AKIA[0-9A-Z]{12,}|^eyJ[\w-]+\.[\w-]+|^(bearer|basic)\s/i;
5284
+ var SECRET_VALUE = /^(sk|rk)_(live|test)_|^whsec_|^gh[pousr]_|^github_pat_|^xox[abposr]-|^(AKIA|ASIA)[0-9A-Z]{12,}|^eyJ[\w-]+\.[\w-]+|^(bearer|basic)\s|^sk-[\w-]{20,}|^AIza[\w-]{30,}|^ya29\.[\w-]{20,}|^SG\.[\w-]{16,}\.[\w-]{16,}|^npm_[A-Za-z0-9]{30,}|^glpat-[\w-]{20,}|^hf_[A-Za-z0-9]{30,}|^shp(at|ss|ca|pa)_[a-fA-F0-9]{32}|^sq0(atp|csp)-[\w-]{20,}|^-----BEGIN [A-Z ]*PRIVATE KEY-----/i;
5285
+ function credentialName(name) {
5286
+ if (/^key$/i.test(name.trim()) || /(type|kind|url|uri|endpoint|expires?(_?(in|at))?|name|count|length|hint|prefix)$/i.test(name)) return false;
5287
+ return secretName(name) || /(^|[^a-z])auth([^a-z]|$)/i.test(name);
5288
+ }
5289
+ var BOT_TOKEN = /^bot\d{5,}:[\w-]{30,}$/;
5290
+ var PREFIXED_ID = /^[a-z]{1,10}_/;
5291
+ function pathSecret(segment) {
5292
+ const s = segment.trim();
5293
+ if (BOT_TOKEN.test(s)) return "bot_token";
5294
+ if (SECRET_VALUE.test(s)) return "token";
5295
+ const random = s.length >= 24 && /^[A-Za-z0-9_\-.~:]+$/.test(s) && /[a-z]/.test(s) && /[A-Z]/.test(s) && /\d/.test(s);
5296
+ return random && !PREFIXED_ID.test(s) ? "token" : void 0;
5297
+ }
5298
+ function withoutUserinfo(address) {
5299
+ return address.replace(/^([a-z][a-z\d+.-]*:\/\/)?[^/@\s]*@/i, (_, scheme) => scheme ?? "");
5300
+ }
5301
+ function hiddenAs(name) {
5302
+ return /passw(or)?d|pwd/i.test(name) ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : placeholder(name || "secret");
5303
+ }
5304
+ function withoutCredential(name, value, hid) {
5305
+ if (!given(value) || !(credentialName(name) || SECRET_VALUE.test(value.trim()))) return value;
5306
+ hid.add(name || "a value");
5307
+ return hiddenAs(name);
5308
+ }
5309
+ function withoutCredentials(value, hid, name = "", depth = 0) {
5310
+ if (depth > 40) return value;
5311
+ if (typeof value === "string") return withoutCredential(name, value, hid);
5312
+ if (Array.isArray(value)) return value.map((v) => withoutCredentials(v, hid, name, depth + 1));
5313
+ if (isObj(value)) return Object.fromEntries(Object.entries(value).map(([key, v]) => [key, withoutCredentials(v, hid, key, depth + 1)]));
5314
+ return value;
5315
+ }
5285
5316
  function readVariables(list7, into) {
5286
5317
  if (!Array.isArray(list7)) return;
5287
5318
  for (const v of list7) {
@@ -5403,7 +5434,7 @@ function decoded(text3) {
5403
5434
  }
5404
5435
  var LOCAL_HOST = /^(localhost|127\.\d+\.\d+\.\d+|0\.0\.0\.0|\[::1\])(:|\/|$)/i;
5405
5436
  function serverOf(url, vars, unset) {
5406
- let host = vars.fill(url.host, false).trim();
5437
+ let host = withoutUserinfo(vars.fill(url.host, false).trim());
5407
5438
  const left = [...host.matchAll(VARIABLE)].map((m) => m[1].trim());
5408
5439
  for (const name of left) unset.add(name);
5409
5440
  if (left.length) {
@@ -5419,7 +5450,7 @@ function serverOf(url, vars, unset) {
5419
5450
  return `${protocol}://${host}${url.port ? `:${vars.fill(url.port, false)}` : ""}`.replace(/\/+$/, "");
5420
5451
  }
5421
5452
  var VERSION = /^(v\d+(\.\d+)*|\d{4}-\d{2}-\d{2})$/i;
5422
- function pathOf(url, vars, params) {
5453
+ function pathOf(url, vars, params, hid) {
5423
5454
  const segments = url.path.map((s) => s.trim()).filter(Boolean);
5424
5455
  const out = segments.map((segment) => {
5425
5456
  const colon = segment.match(/^:([A-Za-z_][\w-]*)(.*)$/);
@@ -5428,6 +5459,14 @@ function pathOf(url, vars, params) {
5428
5459
  if (!params.has(name)) params.set(name, colonParam(name, url.variables, vars));
5429
5460
  return `{${name}}${vars.fill(rest, false)}`;
5430
5461
  }
5462
+ const secret = segment.includes("{{") ? void 0 : pathSecret(decoded(segment));
5463
+ if (secret) {
5464
+ let param = secret;
5465
+ for (let n = 2; params.has(param); n++) param = `${secret}_${n}`;
5466
+ params.set(param, { name: param, in: "path", required: true, schema: { type: "string" }, example: placeholder(param) });
5467
+ hid.add(param);
5468
+ return `{${param}}`;
5469
+ }
5431
5470
  return segment.replace(VARIABLE, (whole, raw) => {
5432
5471
  const name = raw.trim();
5433
5472
  const value = vars.value(name, false);
@@ -5662,7 +5701,7 @@ function payloadOf(value, required) {
5662
5701
  if (holdsPlaceholder(value)) return { schema: schemaOf(value, { required, examples: true }) };
5663
5702
  return { schema: schemaOf(value, { required }), example: value };
5664
5703
  }
5665
- function bodyOf(raw, contentType, vars) {
5704
+ function bodyOf(raw, contentType, vars, hid) {
5666
5705
  if (!isObj(raw) || raw.disabled === true) return void 0;
5667
5706
  const mode = typeof raw.mode === "string" ? raw.mode : "";
5668
5707
  switch (mode) {
@@ -5674,7 +5713,7 @@ function bodyOf(raw, contentType, vars) {
5674
5713
  const type2 = contentType ?? RAW_TYPES[language] ?? (looksJson(text3) ? "application/json" : "text/plain");
5675
5714
  if (/json/i.test(type2)) {
5676
5715
  const value = jsonBody(text3, vars);
5677
- if (value !== void 0) return { media: type2, ...payloadOf(value, true) };
5716
+ if (value !== void 0) return { media: type2, ...payloadOf(withoutCredentials(value, hid), true) };
5678
5717
  return { media: "text/plain", schema: { type: "string" }, example: vars.fill(text3) };
5679
5718
  }
5680
5719
  return { media: type2, schema: { type: "string" }, example: vars.fill(text3) };
@@ -5685,7 +5724,10 @@ function bodyOf(raw, contentType, vars) {
5685
5724
  const fields = pairs(raw[mode]);
5686
5725
  if (!fields.length) return void 0;
5687
5726
  const files = new Set(Array.isArray(raw[mode]) ? raw[mode].flatMap((f) => multipart && isObj(f) && f.type === "file" && typeof f.key === "string" ? [f.key.trim()] : []) : []);
5688
- const entries = fields.map((f) => ({ key: vars.fill(f.key, false), file: files.has(f.key), value: vars.fill(f.value, !f.disabled), field: f }));
5727
+ const entries = fields.map((f) => {
5728
+ const key = vars.fill(f.key, false);
5729
+ return { key, file: files.has(f.key), value: withoutCredential(key, vars.fill(f.value, !f.disabled), hid), field: f };
5730
+ });
5689
5731
  const properties = Object.fromEntries(
5690
5732
  entries.map(({ key, file, value, field }) => {
5691
5733
  if (file) return [key, { type: "string", format: "binary" }];
@@ -5706,7 +5748,8 @@ function bodyOf(raw, contentType, vars) {
5706
5748
  const g = isObj(raw.graphql) ? raw.graphql : {};
5707
5749
  const query = typeof g.query === "string" ? vars.fill(g.query) : "";
5708
5750
  if (!query.trim()) return void 0;
5709
- const variables = typeof g.variables === "string" && g.variables.trim() ? jsonBody(g.variables, vars) : isObj(g.variables) ? g.variables : void 0;
5751
+ const sent = typeof g.variables === "string" && g.variables.trim() ? jsonBody(g.variables, vars) : isObj(g.variables) ? g.variables : void 0;
5752
+ const variables = sent === void 0 ? void 0 : withoutCredentials(sent, hid);
5710
5753
  const example = { query, ...variables !== void 0 ? { variables } : {} };
5711
5754
  return { media: "application/json", ...payloadOf(example, true) };
5712
5755
  }
@@ -5714,7 +5757,7 @@ function bodyOf(raw, contentType, vars) {
5714
5757
  return void 0;
5715
5758
  }
5716
5759
  }
5717
- function responsesOf(saved, requestName) {
5760
+ function responsesOf(saved, requestName, hid) {
5718
5761
  const out = {};
5719
5762
  for (const r of saved) {
5720
5763
  if (!isObj(r)) continue;
@@ -5729,7 +5772,7 @@ function responsesOf(saved, requestName) {
5729
5772
  const body = typeof r.body === "string" ? r.body : "";
5730
5773
  if (body.trim()) {
5731
5774
  const value = (type2 ? /json/i.test(type2) : looksJson(body)) ? parseJson(body) : void 0;
5732
- if (value !== void 0) response.content = { [type2 ?? "application/json"]: payloadOf(value, "all") };
5775
+ if (value !== void 0) response.content = { [type2 ?? "application/json"]: payloadOf(withoutCredentials(value, hid), "all") };
5733
5776
  else response.content = { [type2 && !/json/i.test(type2) ? type2 : "text/plain"]: { schema: { type: "string" }, example: body } };
5734
5777
  }
5735
5778
  out[status] = response;
@@ -5807,6 +5850,7 @@ function convertPostman(raw, environments = [], source) {
5807
5850
  collect(collection.item, void 0, ownAuth(collection.auth), saved, counts);
5808
5851
  const schemes = new Schemes();
5809
5852
  const notes = /* @__PURE__ */ new Set();
5853
+ const hid = /* @__PURE__ */ new Set();
5810
5854
  const requirementOf = (auth, headers) => {
5811
5855
  const scheme = auth ? schemeOf(auth, vars, notes) : void 0;
5812
5856
  const parts = [];
@@ -5837,7 +5881,7 @@ function convertPostman(raw, environments = [], source) {
5837
5881
  const method = FIXED_METHODS.has(rawMethod.toLowerCase()) ? rawMethod.toLowerCase() : rawMethod.toUpperCase();
5838
5882
  const server = serverOf(url, vars, unsetHosts);
5839
5883
  const pathParams = /* @__PURE__ */ new Map();
5840
- let path = pathOf(url, vars, pathParams);
5884
+ let path = pathOf(url, vars, pathParams, hid);
5841
5885
  const shape = path.replace(/\{[^}]+\}/g, "{}");
5842
5886
  const known = shapes.get(shape);
5843
5887
  if (known && known !== path) {
@@ -5851,7 +5895,7 @@ function convertPostman(raw, environments = [], source) {
5851
5895
  const item = paths[path] ??= {};
5852
5896
  const slots = FIXED_METHODS.has(method) ? item : item.additionalOperations ??= {};
5853
5897
  const name = bareName(vars.fill(r.name, false));
5854
- const responses = responsesOf(r.responses, r.name);
5898
+ const responses = responsesOf(r.responses, r.name, hid);
5855
5899
  const success = Object.keys(responses).some((s) => /^2/.test(s));
5856
5900
  const existing = slots[method];
5857
5901
  if (isObj(existing)) {
@@ -5876,15 +5920,19 @@ function convertPostman(raw, environments = [], source) {
5876
5920
  else if (/^cookie$/i.test(h.key)) {
5877
5921
  for (const part of h.value.split(";")) {
5878
5922
  const eq = part.indexOf("=");
5879
- if (eq > 0) parameters.push({ name: part.slice(0, eq).trim(), in: "cookie", required: true, schema: { type: "string" }, example: vars.fill(part.slice(eq + 1).trim()) });
5923
+ if (eq <= 0) continue;
5924
+ const cookie = part.slice(0, eq).trim();
5925
+ const value = vars.fill(part.slice(eq + 1).trim());
5926
+ if (given(value)) hid.add(cookie);
5927
+ parameters.push({ name: cookie, in: "cookie", required: true, schema: { type: "string" }, example: given(value) ? hiddenAs(cookie) : value });
5880
5928
  }
5881
- } else parameters.push({ name: h.key, in: "header", required: true, ...valueOf(vars.fill(h.value)), ...h.description ? { description: h.description } : {} });
5929
+ } else parameters.push({ name: h.key, in: "header", required: true, ...valueOf(withoutCredential(h.key, vars.fill(h.value), hid)), ...h.description ? { description: h.description } : {} });
5882
5930
  }
5883
5931
  const query = /* @__PURE__ */ new Map();
5884
5932
  for (const q of url.query) {
5885
5933
  const key = vars.fill(q.key, false).trim();
5886
5934
  if (!key) continue;
5887
- const value = vars.fill(q.value, !q.disabled);
5935
+ const value = withoutCredential(key, vars.fill(q.value, !q.disabled), hid);
5888
5936
  const entry = query.get(key);
5889
5937
  if (!entry) query.set(key, { values: [value], required: !q.disabled, ...q.description ? { description: q.description } : {} });
5890
5938
  else if (!q.disabled) {
@@ -5898,7 +5946,7 @@ function convertPostman(raw, environments = [], source) {
5898
5946
  const value = many ? { schema: { type: "array", items: { type: "string" } }, example: q.values } : valueOf(q.values[0]);
5899
5947
  parameters.push({ name: key, in: "query", required: q.required, ...value, ...q.description ? { description: q.description } : {} });
5900
5948
  }
5901
- const body = bodyOf(r.request.body, contentType, vars);
5949
+ const body = bodyOf(r.request.body, contentType, vars, hid);
5902
5950
  const lowered = method.toLowerCase();
5903
5951
  const operationId = namesUrl(name) ? void 0 : operationIdFor(name, usedIds);
5904
5952
  const op = {
@@ -5937,6 +5985,7 @@ function convertPostman(raw, environments = [], source) {
5937
5985
  else if (unsetHosts.has("")) warnings.push("Some requests give no host, so the video puts them on api.example.com.");
5938
5986
  const unset = [...vars.unset].filter((n) => !unsetHosts.has(n));
5939
5987
  if (unset.length) warnings.push(`Some variables have no value in the collection, so the video shows them as written, or an id an earlier call returned: ${list2(unset.map((n) => `{{${n}}}`))}.`);
5988
+ if (hid.size) warnings.push(`Credentials written out in the requests or their saved responses, rather than kept in variables, show hidden: ${list2([...hid])}.`);
5940
5989
  if (vars.secret.size) warnings.push(`Variables that look like credentials aren't filled in, so the video shows them as written: ${list2([...vars.secret].map((n) => `{{${n}}}`))}.`);
5941
5990
  if (placed.length && unsaved === placed.length && app !== "Postman") warnings.push(`${app}'s exports hold no responses, so the calls show no response body. A design document's spec gives them.`);
5942
5991
  else if (placed.length && unsaved === placed.length) warnings.push("None of the requests has a successful response saved as an example, so the calls show no response body. Save a response as an example in Postman to show it.");
@@ -11022,7 +11071,7 @@ function unknownKeys(raw, known, where, problems) {
11022
11071
  }
11023
11072
 
11024
11073
  // package.json
11025
- var version = "1.0.7";
11074
+ var version = "1.0.9";
11026
11075
 
11027
11076
  // src/files.ts
11028
11077
  var import_node_fs = require("node:fs");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "integration-tour",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Renders integration videos of your API or MCP server from its OpenAPI spec or tools, in your own build, so they stay in step with it.",
5
5
  "keywords": [
6
6
  "openapi",