@mesub/node 0.1.2 → 0.1.4

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 (40) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-4AAPR37Y.js → chunk-EPOLIEGY.js} +2 -2
  3. package/dist/{chunk-4JSJOX35.cjs → chunk-IAYUXSDD.cjs} +49 -23
  4. package/dist/chunk-IAYUXSDD.cjs.map +1 -0
  5. package/dist/{chunk-NOS4FWWQ.js → chunk-IG4QRQSJ.js} +34 -8
  6. package/dist/chunk-IG4QRQSJ.js.map +1 -0
  7. package/dist/{chunk-66VVEXMU.cjs → chunk-K6U6FPTA.cjs} +7 -7
  8. package/dist/{chunk-66VVEXMU.cjs.map → chunk-K6U6FPTA.cjs.map} +1 -1
  9. package/dist/{chunk-J2CE4QWV.js → chunk-PFI3Y32I.js} +2 -2
  10. package/dist/{chunk-SJRQDWTI.cjs → chunk-YCPYBU3R.cjs} +4 -4
  11. package/dist/{chunk-SJRQDWTI.cjs.map → chunk-YCPYBU3R.cjs.map} +1 -1
  12. package/dist/{client-BEuDegEY.d.cts → client-BZB6KIGd.d.cts} +3 -2
  13. package/dist/{client-CXQLkSAJ.d.ts → client-Q5QhXphp.d.ts} +3 -2
  14. package/dist/express.cjs +21 -21
  15. package/dist/express.d.cts +3 -3
  16. package/dist/express.d.ts +3 -3
  17. package/dist/express.js +3 -3
  18. package/dist/index.cjs +2 -2
  19. package/dist/index.d.cts +3 -3
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +1 -1
  22. package/dist/nest.cjs +13 -13
  23. package/dist/nest.d.cts +1 -1
  24. package/dist/nest.d.ts +1 -1
  25. package/dist/nest.js +2 -2
  26. package/dist/next.cjs +20 -20
  27. package/dist/next.d.cts +3 -3
  28. package/dist/next.d.ts +3 -3
  29. package/dist/next.js +3 -3
  30. package/dist/{routes-CMzB52P6.d.cts → routes-DT8EFWSl.d.cts} +1 -1
  31. package/dist/{routes-B7wN4sby.d.ts → routes-KoaD1Xsk.d.ts} +1 -1
  32. package/dist/testing.cjs +13 -13
  33. package/dist/testing.d.cts +1 -1
  34. package/dist/testing.d.ts +1 -1
  35. package/dist/testing.js +1 -1
  36. package/package.json +1 -1
  37. package/dist/chunk-4JSJOX35.cjs.map +0 -1
  38. package/dist/chunk-NOS4FWWQ.js.map +0 -1
  39. /package/dist/{chunk-4AAPR37Y.js.map → chunk-EPOLIEGY.js.map} +0 -0
  40. /package/dist/{chunk-J2CE4QWV.js.map → chunk-PFI3Y32I.js.map} +0 -0
package/README.md CHANGED
@@ -684,7 +684,7 @@ Guards, webhooks, subscribing and managing against it:
684
684
  ```ts
685
685
  new Mesub({
686
686
  apiKey, // default: process.env.MESUB_API_KEY
687
- baseUrl, // default: https://api.mesub.io, may carry a path
687
+ baseUrl, // default: process.env.MESUB_BASE_URL, then https://api.mesub.io; may carry a path
688
688
  headers, // extra headers on every call, e.g. for a proxy
689
689
  timeout, // per attempt, ms, default 5000
690
690
  maxRetries, // default 2
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Mesub,
3
3
  customerOf
4
- } from "./chunk-NOS4FWWQ.js";
4
+ } from "./chunk-IG4QRQSJ.js";
5
5
 
6
6
  // src/guard.ts
7
7
  var DENIAL_STATUS = {
@@ -117,4 +117,4 @@ export {
117
117
  accessOf,
118
118
  denialOf
119
119
  };
120
- //# sourceMappingURL=chunk-4AAPR37Y.js.map
120
+ //# sourceMappingURL=chunk-EPOLIEGY.js.map
@@ -86,7 +86,7 @@ var AccessCache = class _AccessCache {
86
86
  };
87
87
 
88
88
  // src/version.ts
89
- var VERSION = "0.1.2";
89
+ var VERSION = "0.1.4";
90
90
  var API_VERSION = "2026-10-02";
91
91
  var API_VERSION_HEADER = "Mesub-Version";
92
92
 
@@ -109,23 +109,30 @@ function envKey() {
109
109
  return typeof process === "undefined" ? void 0 : _optionalChain([process, 'access', _ => _.env, 'optionalAccess', _2 => _2["MESUB_API_KEY"]]);
110
110
  }
111
111
  function baseUrlOf(given, fallback) {
112
- if (given === void 0) return fallback;
113
- if (typeof given !== "string") throw new TypeError("baseUrl must be a string.");
112
+ if (given !== void 0) return checkedBaseUrl("baseUrl", given);
113
+ const fromEnv = envBaseUrl();
114
+ return fromEnv ? checkedBaseUrl("MESUB_BASE_URL", fromEnv) : fallback;
115
+ }
116
+ function envBaseUrl() {
117
+ return typeof process === "undefined" ? void 0 : _optionalChain([process, 'access', _3 => _3.env, 'optionalAccess', _4 => _4["MESUB_BASE_URL"]]);
118
+ }
119
+ function checkedBaseUrl(name, given) {
120
+ if (typeof given !== "string") throw new TypeError(`${name} must be a string.`);
114
121
  let url;
115
122
  try {
116
123
  url = new URL(given);
117
124
  } catch (e4) {
118
- throw new TypeError(`baseUrl must be an absolute URL, not ${JSON.stringify(given)}.`);
125
+ throw new TypeError(`${name} must be an absolute URL, not ${JSON.stringify(given)}.`);
119
126
  }
120
127
  if (url.search !== "" || url.hash !== "" || given.includes("?") || given.includes("#")) {
121
128
  throw new TypeError(
122
- `baseUrl must have no query nor fragment, not ${JSON.stringify(given)}.`
129
+ `${name} must have no query nor fragment, not ${JSON.stringify(given)}.`
123
130
  );
124
131
  }
125
132
  const local = url.protocol === "http:" && LOOPBACK.has(url.hostname);
126
133
  if (url.protocol !== "https:" && !local) {
127
134
  throw new TypeError(
128
- `baseUrl must be https (http only to localhost or 127.0.0.1), not ${url.protocol}//${url.host}: every call carries the API key.`
135
+ `${name} must be https (http only to localhost or 127.0.0.1), not ${url.protocol}//${url.host}: every call carries the API key.`
129
136
  );
130
137
  }
131
138
  return given.replace(/\/+$/, "");
@@ -218,7 +225,7 @@ var CUSTOMER_KINDS = ["wallet", "external_id", "email"];
218
225
  function customerOf(customer) {
219
226
  if (typeof customer === "string") return { kind: "wallet", value: customer };
220
227
  const named = CUSTOMER_KINDS.filter(
221
- (kind2) => _optionalChain([customer, 'optionalAccess', _3 => _3[kind2]]) !== void 0
228
+ (kind2) => _optionalChain([customer, 'optionalAccess', _5 => _5[kind2]]) !== void 0
222
229
  );
223
230
  const kind = named[0];
224
231
  const value = kind && customer[kind];
@@ -882,7 +889,7 @@ function webhookSecretOf(given) {
882
889
  return secret || void 0;
883
890
  }
884
891
  function envSecret() {
885
- return typeof process === "undefined" ? void 0 : _optionalChain([process, 'access', _4 => _4.env, 'optionalAccess', _5 => _5["MESUB_WEBHOOK_SECRET"]]);
892
+ return typeof process === "undefined" ? void 0 : _optionalChain([process, 'access', _6 => _6.env, 'optionalAccess', _7 => _7["MESUB_WEBHOOK_SECRET"]]);
886
893
  }
887
894
  function headerIn(headers, name) {
888
895
  if (typeof headers.get === "function") {
@@ -984,7 +991,7 @@ var Transport = class {
984
991
  }
985
992
  }
986
993
  async #attempt(method, url, body, { deadline, signal, ...options }) {
987
- _optionalChain([signal, 'optionalAccess', _6 => _6.throwIfAborted, 'call', _7 => _7()]);
994
+ _optionalChain([signal, 'optionalAccess', _8 => _8.throwIfAborted, 'call', _9 => _9()]);
988
995
  const perAttempt = _nullishCoalesce(options.timeout, () => ( this.#config.timeout));
989
996
  const left = deadline === void 0 ? Infinity : deadline - Date.now();
990
997
  if (left <= 0) {
@@ -998,8 +1005,8 @@ var Transport = class {
998
1005
  const cutByDeadline = timeout < perAttempt;
999
1006
  const controller = new AbortController();
1000
1007
  const timer = setTimeout(() => controller.abort(), timeout);
1001
- const stop = () => controller.abort(_optionalChain([signal, 'optionalAccess', _8 => _8.reason]));
1002
- _optionalChain([signal, 'optionalAccess', _9 => _9.addEventListener, 'call', _10 => _10("abort", stop, { once: true })]);
1008
+ const stop = () => controller.abort(_optionalChain([signal, 'optionalAccess', _10 => _10.reason]));
1009
+ _optionalChain([signal, 'optionalAccess', _11 => _11.addEventListener, 'call', _12 => _12("abort", stop, { once: true })]);
1003
1010
  try {
1004
1011
  const response = await this.#config.fetch(url, {
1005
1012
  method,
@@ -1012,8 +1019,24 @@ var Transport = class {
1012
1019
  ...body !== void 0 && { "Content-Type": "application/json" }
1013
1020
  },
1014
1021
  ...body !== void 0 && { body: JSON.stringify(body) },
1015
- signal: controller.signal
1022
+ signal: controller.signal,
1023
+ // Every call carries the key, and Mesub never redirects: a
1024
+ // redirect is never followed, so the key is never sent on (#171).
1025
+ redirect: "manual"
1016
1026
  });
1027
+ if (isRedirect(response)) {
1028
+ await _optionalChain([response, 'access', _13 => _13.body, 'optionalAccess', _14 => _14.cancel, 'call', _15 => _15()]);
1029
+ const to = response.headers.get("location");
1030
+ const error2 = new MesubError(
1031
+ `${url.pathname} answered a redirect${to ? ` to ${to}` : ""}, and Mesub never redirects: is baseUrl (${this.#config.baseUrl}) the Mesub API?`,
1032
+ {
1033
+ status: response.status || null,
1034
+ code: "unexpected",
1035
+ requestId: response.headers.get(REQUEST_ID_HEADER)
1036
+ }
1037
+ );
1038
+ return { ok: false, error: error2, retry: false, retryAfter: null };
1039
+ }
1017
1040
  const text = await response.text();
1018
1041
  const requestId = response.headers.get(REQUEST_ID_HEADER);
1019
1042
  if (response.ok) {
@@ -1051,7 +1074,7 @@ var Transport = class {
1051
1074
  retryAfter: asked === null ? null : Math.min(asked, MAX_RETRY_AFTER)
1052
1075
  };
1053
1076
  } catch (cause) {
1054
- if (_optionalChain([signal, 'optionalAccess', _11 => _11.aborted])) throw signal.reason;
1077
+ if (_optionalChain([signal, 'optionalAccess', _16 => _16.aborted])) throw signal.reason;
1055
1078
  if (controller.signal.aborted && cutByDeadline) {
1056
1079
  const error2 = new MesubError(
1057
1080
  `Mesub did not answer within the ${Math.round(timeout)} ms left before the deadline.`,
@@ -1064,10 +1087,13 @@ var Transport = class {
1064
1087
  return { ok: false, error, retry: true, retryAfter: null };
1065
1088
  } finally {
1066
1089
  clearTimeout(timer);
1067
- _optionalChain([signal, 'optionalAccess', _12 => _12.removeEventListener, 'call', _13 => _13("abort", stop)]);
1090
+ _optionalChain([signal, 'optionalAccess', _17 => _17.removeEventListener, 'call', _18 => _18("abort", stop)]);
1068
1091
  }
1069
1092
  }
1070
1093
  };
1094
+ function isRedirect(response) {
1095
+ return response.type === "opaqueredirect" || response.status >= 300 && response.status < 400;
1096
+ }
1071
1097
  function endpoint(baseUrl, path) {
1072
1098
  return new URL(baseUrl + path);
1073
1099
  }
@@ -1132,13 +1158,13 @@ function sleep(ms, signal) {
1132
1158
  return new Promise((resolve, reject) => {
1133
1159
  const stop = () => {
1134
1160
  clearTimeout(timer);
1135
- reject(_optionalChain([signal, 'optionalAccess', _14 => _14.reason]));
1161
+ reject(_optionalChain([signal, 'optionalAccess', _19 => _19.reason]));
1136
1162
  };
1137
1163
  const timer = setTimeout(() => {
1138
- _optionalChain([signal, 'optionalAccess', _15 => _15.removeEventListener, 'call', _16 => _16("abort", stop)]);
1164
+ _optionalChain([signal, 'optionalAccess', _20 => _20.removeEventListener, 'call', _21 => _21("abort", stop)]);
1139
1165
  resolve();
1140
1166
  }, ms);
1141
- _optionalChain([signal, 'optionalAccess', _17 => _17.addEventListener, 'call', _18 => _18("abort", stop, { once: true })]);
1167
+ _optionalChain([signal, 'optionalAccess', _22 => _22.addEventListener, 'call', _23 => _23("abort", stop, { once: true })]);
1142
1168
  });
1143
1169
  }
1144
1170
 
@@ -1327,7 +1353,7 @@ var Subscriptions = class {
1327
1353
  */
1328
1354
  async #settle(id, signal, { sends, cause, from, code, retryable, lead }) {
1329
1355
  const subscription = await this.#readBack(id, signal);
1330
- if (_optionalChain([subscription, 'optionalAccess', _19 => _19.status]) === "active" || _optionalChain([subscription, 'optionalAccess', _20 => _20.status]) === "cancelled") {
1356
+ if (_optionalChain([subscription, 'optionalAccess', _24 => _24.status]) === "active" || _optionalChain([subscription, 'optionalAccess', _25 => _25.status]) === "cancelled") {
1331
1357
  return { subscription };
1332
1358
  }
1333
1359
  const then = subscription === null ? "Reading the subscription back failed too" : `The subscription read back is ${subscription.status}`;
@@ -1364,7 +1390,7 @@ var Subscriptions = class {
1364
1390
  );
1365
1391
  return serverSubscriptionFrom(body);
1366
1392
  } catch (error) {
1367
- if (_optionalChain([signal, 'optionalAccess', _21 => _21.aborted])) throw error;
1393
+ if (_optionalChain([signal, 'optionalAccess', _26 => _26.aborted])) throw error;
1368
1394
  return null;
1369
1395
  }
1370
1396
  }
@@ -1777,7 +1803,7 @@ var Mesub = (_class3 = class {
1777
1803
  if (options.attempts === true) return this.ask(asked, slug, null, boundOf(options));
1778
1804
  const slot = await this.slotOf(asked);
1779
1805
  const cached = await this.cache.read(slot.who, slug, slot.scope);
1780
- if (_optionalChain([cached, 'optionalAccess', _22 => _22.fresh])) return cached.value;
1806
+ if (_optionalChain([cached, 'optionalAccess', _27 => _27.fresh])) return cached.value;
1781
1807
  return this.ask(asked, slug, slot);
1782
1808
  }
1783
1809
  /**
@@ -1793,7 +1819,7 @@ var Mesub = (_class3 = class {
1793
1819
  const slot = attempts ? null : await this.slotOf(asked);
1794
1820
  if (slot) {
1795
1821
  const cached = await this.lists.read(slot.who, null, slot.scope);
1796
- if (_optionalChain([cached, 'optionalAccess', _23 => _23.fresh])) return cached.value;
1822
+ if (_optionalChain([cached, 'optionalAccess', _28 => _28.fresh])) return cached.value;
1797
1823
  }
1798
1824
  const request = async () => accessListFrom(
1799
1825
  await this.transport.get("/v1/access", {
@@ -1954,7 +1980,7 @@ var Mesub = (_class3 = class {
1954
1980
  const slug = planOf(plan);
1955
1981
  const slot = await this.slotOf(asked);
1956
1982
  const cached = await this.cache.read(slot.who, slug, slot.scope, deadline);
1957
- if (_optionalChain([cached, 'optionalAccess', _24 => _24.fresh])) {
1983
+ if (_optionalChain([cached, 'optionalAccess', _29 => _29.fresh])) {
1958
1984
  return { access: cached.value.access, answer: cached.value, stale: false };
1959
1985
  }
1960
1986
  try {
@@ -2037,4 +2063,4 @@ function stillGrants(answer, now = Date.now()) {
2037
2063
 
2038
2064
 
2039
2065
  exports.DEFAULT_MAX_STALE_MS = DEFAULT_MAX_STALE_MS; exports.AccessCache = AccessCache; exports.VERSION = VERSION; exports.API_VERSION = API_VERSION; exports.API_VERSION_HEADER = API_VERSION_HEADER; exports.DEFAULT_MAX_ENTRIES = DEFAULT_MAX_ENTRIES; exports.MemoryStore = MemoryStore; exports.customerOf = customerOf; exports.MesubError = MesubError; exports.MesubSubmitError = MesubSubmitError; exports.verifyWebhook = verifyWebhook; exports.signedHeaders = signedHeaders; exports.Mesub = Mesub;
2040
- //# sourceMappingURL=chunk-4JSJOX35.cjs.map
2066
+ //# sourceMappingURL=chunk-IAYUXSDD.cjs.map