@memberstack/dom 2.0.2-beta.0 → 2.0.3

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 (87) hide show
  1. package/lib/index.d.mts +76 -61
  2. package/lib/index.d.ts +76 -61
  3. package/lib/index.js +840 -61
  4. package/lib/index.mjs +840 -61
  5. package/lib/{models-CTRKogoR.d.ts → models-CFT_ABd5.d.ts} +2 -2
  6. package/lib/testing/index.d.mts +25 -2
  7. package/lib/testing/index.d.ts +25 -2
  8. package/lib/testing/index.js +28 -6
  9. package/lib/testing/index.mjs +26 -5
  10. package/package.json +1 -1
  11. package/lib/auth/index.d.mts +0 -63
  12. package/lib/auth/index.d.ts +0 -63
  13. package/lib/auth/index.global.js +0 -244
  14. package/lib/auth/index.js +0 -161
  15. package/lib/auth/index.mjs +0 -123
  16. package/lib/constants/endpoints.d.mts +0 -5
  17. package/lib/constants/endpoints.d.ts +0 -5
  18. package/lib/constants/endpoints.global.js +0 -29
  19. package/lib/constants/endpoints.js +0 -32
  20. package/lib/constants/endpoints.mjs +0 -7
  21. package/lib/methods/dom/index.d.mts +0 -2
  22. package/lib/methods/dom/index.d.ts +0 -2
  23. package/lib/methods/dom/index.global.js +0 -2
  24. package/lib/methods/dom/index.js +0 -1
  25. package/lib/methods/dom/index.mjs +0 -0
  26. package/lib/methods/dom/main-dom.d.mts +0 -2
  27. package/lib/methods/dom/main-dom.d.ts +0 -2
  28. package/lib/methods/dom/main-dom.global.js +0 -30620
  29. package/lib/methods/dom/main-dom.js +0 -15611
  30. package/lib/methods/dom/main-dom.mjs +0 -15593
  31. package/lib/methods/dom/methods.d.mts +0 -100
  32. package/lib/methods/dom/methods.d.ts +0 -100
  33. package/lib/methods/dom/methods.global.js +0 -30827
  34. package/lib/methods/dom/methods.js +0 -335
  35. package/lib/methods/dom/methods.mjs +0 -302
  36. package/lib/methods/index.d.mts +0 -185
  37. package/lib/methods/index.d.ts +0 -185
  38. package/lib/methods/index.global.js +0 -46361
  39. package/lib/methods/index.js +0 -2530
  40. package/lib/methods/index.mjs +0 -2500
  41. package/lib/methods/requests/index.d.mts +0 -912
  42. package/lib/methods/requests/index.d.ts +0 -912
  43. package/lib/methods/requests/index.global.js +0 -15553
  44. package/lib/methods/requests/index.js +0 -2145
  45. package/lib/methods/requests/index.mjs +0 -2110
  46. package/lib/methods/requests/requests.d.mts +0 -43
  47. package/lib/methods/requests/requests.d.ts +0 -43
  48. package/lib/methods/requests/requests.global.js +0 -14528
  49. package/lib/methods/requests/requests.js +0 -244
  50. package/lib/methods/requests/requests.mjs +0 -210
  51. package/lib/models-BmZS-mc4.d.ts +0 -193
  52. package/lib/models-le7xaT4H.d.ts +0 -193
  53. package/lib/types/index.d.mts +0 -5
  54. package/lib/types/index.d.ts +0 -5
  55. package/lib/types/index.global.js +0 -19
  56. package/lib/types/index.js +0 -18
  57. package/lib/types/index.mjs +0 -0
  58. package/lib/types/params.d.mts +0 -946
  59. package/lib/types/params.d.ts +0 -946
  60. package/lib/types/params.global.js +0 -19
  61. package/lib/types/params.js +0 -18
  62. package/lib/types/params.mjs +0 -0
  63. package/lib/types/payloads.d.mts +0 -342
  64. package/lib/types/payloads.d.ts +0 -342
  65. package/lib/types/payloads.global.js +0 -19
  66. package/lib/types/payloads.js +0 -18
  67. package/lib/types/payloads.mjs +0 -0
  68. package/lib/types/translations.d.mts +0 -101
  69. package/lib/types/translations.d.ts +0 -101
  70. package/lib/types/translations.global.js +0 -19
  71. package/lib/types/translations.js +0 -18
  72. package/lib/types/translations.mjs +0 -0
  73. package/lib/types/utils/payloads.d.mts +0 -297
  74. package/lib/types/utils/payloads.d.ts +0 -297
  75. package/lib/types/utils/payloads.global.js +0 -19
  76. package/lib/types/utils/payloads.js +0 -18
  77. package/lib/types/utils/payloads.mjs +0 -0
  78. package/lib/utils/cookies.d.mts +0 -13
  79. package/lib/utils/cookies.d.ts +0 -13
  80. package/lib/utils/cookies.global.js +0 -261
  81. package/lib/utils/cookies.js +0 -190
  82. package/lib/utils/cookies.mjs +0 -148
  83. package/lib/utils/defaultMessageBox.d.mts +0 -5
  84. package/lib/utils/defaultMessageBox.d.ts +0 -5
  85. package/lib/utils/defaultMessageBox.global.js +0 -125
  86. package/lib/utils/defaultMessageBox.js +0 -130
  87. package/lib/utils/defaultMessageBox.mjs +0 -103
@@ -1,2530 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __defProps = Object.defineProperties;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
- var __getProtoOf = Object.getPrototypeOf;
10
- var __hasOwnProp = Object.prototype.hasOwnProperty;
11
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
- var __spreadValues = (a, b) => {
14
- for (var prop in b || (b = {}))
15
- if (__hasOwnProp.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- if (__getOwnPropSymbols)
18
- for (var prop of __getOwnPropSymbols(b)) {
19
- if (__propIsEnum.call(b, prop))
20
- __defNormalProp(a, prop, b[prop]);
21
- }
22
- return a;
23
- };
24
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
- var __export = (target, all) => {
26
- for (var name in all)
27
- __defProp(target, name, { get: all[name], enumerable: true });
28
- };
29
- var __copyProps = (to, from, except, desc) => {
30
- if (from && typeof from === "object" || typeof from === "function") {
31
- for (let key of __getOwnPropNames(from))
32
- if (!__hasOwnProp.call(to, key) && key !== except)
33
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
- }
35
- return to;
36
- };
37
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
- // If the importer is in node compatibility mode or this is not an ESM
39
- // file that has been converted to a CommonJS file using a Babel-
40
- // compatible transform (i.e. "__esModule" has not been set), then set
41
- // "default" to the CommonJS "module.exports" for node compatibility.
42
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
- mod
44
- ));
45
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
- var __async = (__this, __arguments, generator) => {
47
- return new Promise((resolve, reject) => {
48
- var fulfilled = (value) => {
49
- try {
50
- step(generator.next(value));
51
- } catch (e) {
52
- reject(e);
53
- }
54
- };
55
- var rejected = (value) => {
56
- try {
57
- step(generator.throw(value));
58
- } catch (e) {
59
- reject(e);
60
- }
61
- };
62
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
63
- step((generator = generator.apply(__this, __arguments)).next());
64
- });
65
- };
66
-
67
- // src/methods/index.ts
68
- var methods_exports = {};
69
- __export(methods_exports, {
70
- default: () => methods_default
71
- });
72
- module.exports = __toCommonJS(methods_exports);
73
-
74
- // src/utils/defaultMessageBox.ts
75
- var closeIcon;
76
- if (typeof window !== "undefined") {
77
- closeIcon = document.createElement("div");
78
- closeIcon.setAttribute("id", "ms-status-close");
79
- closeIcon.setAttribute("data-ms-message-close", "");
80
- closeIcon.innerHTML = `<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z" fill="white"/></svg>`;
81
- }
82
- var addSuccessBox = () => {
83
- const successStatusIcon = document.createElement("div");
84
- successStatusIcon.setAttribute("id", "ms-status-icon");
85
- successStatusIcon.innerHTML = `<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="10" fill="#62d37f"/><path d="M10 0C4.48 0 0 4.48 0 10s4.48 10 10 10 10-4.48 10-10S15.52 0 10 0Zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8Zm4.59-12.42L8 12.17 5.41 9.59 4 11l4 4 8-8-1.41-1.42Z" fill="#fff"/></svg>`;
86
- const successHTML = `<div data-ms-message class="ms-error-message">
87
- ${successStatusIcon.outerHTML}
88
- <div id="ms-message" data-ms-message-text></div>
89
- ${closeIcon.outerHTML}
90
- </div>`;
91
- const successdiv = document.createElement("div");
92
- successdiv.setAttribute("data-ms-message", "success");
93
- successdiv.innerHTML = successHTML;
94
- successdiv.style.display = "none";
95
- document.body.appendChild(successdiv);
96
- };
97
- var addErrorBox = () => {
98
- const errorStatusIcon = document.createElement("div");
99
- errorStatusIcon.setAttribute("id", "ms-status-icon");
100
- errorStatusIcon.innerHTML = `<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 0C4.48 0 0 4.48 0 10C0 15.52 4.48 20 10 20C15.52 20 20 15.52 20 10C20 4.48 15.52 0 10 0ZM11 15H9V13H11V15ZM11 11H9V5H11V11Z" fill="#E40023"/></svg>`;
101
- const errorHTML = `<div data-ms-message class="ms-error-message">
102
- ${errorStatusIcon.outerHTML}
103
- <div id="ms-message" data-ms-message-text></div>
104
- ${closeIcon.outerHTML}
105
- </div>`;
106
- const errordiv = document.createElement("div");
107
- errordiv.setAttribute("data-ms-message", "error");
108
- errordiv.innerHTML = errorHTML;
109
- errordiv.style.display = "none";
110
- document.body.appendChild(errordiv);
111
- };
112
- var initCSS = () => {
113
- const cssEl = document.createElement("style");
114
- const css = `
115
- @keyframes fadeIn {
116
- 0% {
117
- opacity: 0;
118
- }
119
- 100% {
120
- opacity: 1;
121
- }
122
- }
123
- .ms-error-message {
124
- position: fixed;
125
- left: 50%;
126
- bottom: 3%;
127
- transform: translate(-50%, -50%);
128
- margin: 0 auto;
129
- z-index: 10000000;
130
- display: flex;
131
- align-items: center;
132
- padding: 12px 16px;
133
- border-radius: 8px;
134
- background-color: #0A0A0A;
135
- color: #fff;
136
- font-size: 16.8px;
137
- line-height: 28px;
138
- font-weight: 500;
139
- transform-origin: center;
140
- animation: fadeIn 0.2s ease-in;
141
- -webkit-animation: fadeIn 0.2s ease-in;
142
- -moz-animation: fadeIn 0.2s ease-in;
143
- -o-animation: fadeIn 0.2s ease-in;
144
- -ms-animation: fadeIn 0.2s ease-in;
145
- }
146
- @media screen and (max-width: 768px) {
147
- .ms-error-message {
148
- bottom: 12px;
149
- width: calc(100% - 24px);
150
- max-width: none;
151
- padding: 10px 12px;
152
- font-size: 14px;
153
- line-height: 20px;
154
- }
155
- }
156
- #ms-status-icon {
157
- width: 20px;
158
- height: 20px;
159
- margin-right: 12px;
160
- }
161
- #ms-status-close {
162
- margin-left: 20px;
163
- cursor: pointer;
164
- }
165
- #ms-status-close svg {
166
- height: 12px;
167
- }`;
168
- cssEl.setAttribute("data-ms-style", "");
169
- cssEl.appendChild(document.createTextNode(css));
170
- document.head.appendChild(cssEl);
171
- };
172
-
173
- // src/config/cdn.ts
174
- var MAJOR_VERSION = typeof __PREBUILT_UI_MAJOR_VERSION__ !== "undefined" ? __PREBUILT_UI_MAJOR_VERSION__ : "1";
175
- var isDev = typeof __API_ENDPOINT__ !== "undefined" && __API_ENDPOINT__.includes("dev-client");
176
- var CDN_BASE_URL = "https://static.memberstack.com/scripts/v2";
177
- var getLocalOverride = () => {
178
- if (typeof window !== "undefined" && window.__MS_PREBUILT_UI_URL__) {
179
- return window.__MS_PREBUILT_UI_URL__;
180
- }
181
- return null;
182
- };
183
- var getPrebuiltUIUrl = () => {
184
- const localOverride = getLocalOverride();
185
- if (localOverride) {
186
- return localOverride;
187
- }
188
- return isDev ? `${CDN_BASE_URL}/dev/prebuilt-uis/v${MAJOR_VERSION}.js` : `${CDN_BASE_URL}/prebuilt-uis/v${MAJOR_VERSION}.js`;
189
- };
190
-
191
- // src/methods/dom/methods.ts
192
- if (typeof Node !== "undefined" && !Node.prototype.getRootNode) {
193
- Node.prototype.getRootNode = function() {
194
- let node = this;
195
- while (node.parentNode) {
196
- node = node.parentNode;
197
- }
198
- return node;
199
- };
200
- }
201
- var prebuiltUILoaded = false;
202
- var prebuiltUILoadPromise = null;
203
- var loadPrebuiltUI = (retries = 2) => __async(void 0, null, function* () {
204
- if (prebuiltUILoaded)
205
- return;
206
- if (prebuiltUILoadPromise) {
207
- return prebuiltUILoadPromise;
208
- }
209
- prebuiltUILoadPromise = new Promise((resolve, reject) => {
210
- if (typeof customElements !== "undefined" && customElements.get("memberstack-prebuilt-ui")) {
211
- prebuiltUILoaded = true;
212
- resolve();
213
- return;
214
- }
215
- const script = document.createElement("script");
216
- script.src = getPrebuiltUIUrl();
217
- script.async = true;
218
- script.onload = () => {
219
- prebuiltUILoaded = true;
220
- resolve();
221
- };
222
- script.onerror = () => __async(void 0, null, function* () {
223
- prebuiltUILoadPromise = null;
224
- script.remove();
225
- if (retries > 0) {
226
- yield new Promise((r) => setTimeout(r, 1e3));
227
- try {
228
- yield loadPrebuiltUI(retries - 1);
229
- resolve();
230
- } catch (e) {
231
- reject(e);
232
- }
233
- } else {
234
- reject(new Error(
235
- "Failed to load Memberstack modals after multiple attempts. Please check your internet connection."
236
- ));
237
- }
238
- });
239
- document.head.appendChild(script);
240
- });
241
- return prebuiltUILoadPromise;
242
- });
243
- var preloadModals = () => {
244
- return loadPrebuiltUI();
245
- };
246
- var initDefaultMessageBox = () => {
247
- initCSS();
248
- addSuccessBox();
249
- addErrorBox();
250
- };
251
- var showMessage = (msg, isError) => __async(void 0, null, function* () {
252
- if (!msg)
253
- return;
254
- yield new Promise((resolve) => {
255
- if (document.readyState !== "loading") {
256
- resolve(true);
257
- } else {
258
- document.addEventListener("DOMContentLoaded", function(event) {
259
- resolve(true);
260
- });
261
- }
262
- });
263
- if (!document.querySelector("[data-ms-message='success']")) {
264
- initDefaultMessageBox();
265
- }
266
- let messageBox;
267
- if (isError) {
268
- messageBox = document.querySelector("[data-ms-message='error']");
269
- } else {
270
- messageBox = document.querySelector("[data-ms-message='success']");
271
- }
272
- if (!messageBox)
273
- return;
274
- const messageTextBox = messageBox.querySelector("[data-ms-message-text]");
275
- if (messageTextBox) {
276
- messageTextBox.innerHTML = msg;
277
- }
278
- messageBox.style.display = "block";
279
- const closeBtn = messageBox.querySelector("[data-ms-message-close]");
280
- closeBtn == null ? void 0 : closeBtn.addEventListener("click", () => {
281
- messageBox.style.display = "none";
282
- });
283
- setTimeout(() => {
284
- messageBox.style.display = "none";
285
- }, 7e3);
286
- });
287
- var showLoader = (element) => {
288
- if (element) {
289
- element.style.display = "block";
290
- return;
291
- }
292
- const cssEl = document.createElement("style");
293
- const css = ".ms__loader { width: 100%; height: 100%; overflow: hidden; position: fixed; top: 0; left: 0; display: flex; justify-content: center; align-items: center; z-index: 10000000; } #msLoader path { fill: #007ace; }";
294
- cssEl.appendChild(document.createTextNode(css));
295
- document.head.appendChild(cssEl);
296
- const loaderHTML = '<?xml version="1.0"?><div class="ms__loader"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="msLoader" x="0px" y="0px" width="40px" height="40px" viewBox="0 0 50 50" style="enable-background: new 0 0 50 50; z-index:1000000" xml:space="preserve"><path fill="#000" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z"><animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"/></path></svg></div>';
297
- const div = document.createElement("div");
298
- div.setAttribute("data-ms-loader", "true");
299
- div.innerHTML = loaderHTML;
300
- if (document.readyState !== "loading") {
301
- document.body.appendChild(div);
302
- } else {
303
- document.addEventListener("DOMContentLoaded", function(event) {
304
- document.body.appendChild(div);
305
- });
306
- }
307
- };
308
- var hideLoader = (element) => {
309
- var _a;
310
- if (element) {
311
- element.style.display = "none";
312
- return;
313
- }
314
- (_a = document.querySelector("[data-ms-loader]")) == null ? void 0 : _a.remove();
315
- };
316
- var modal = null;
317
- var openModal = (_0, ..._1) => __async(void 0, [_0, ..._1], function* (type, params = {}) {
318
- yield loadPrebuiltUI();
319
- let resolveModal;
320
- const modalPromise = new Promise((resolve) => {
321
- resolveModal = resolve;
322
- });
323
- const element = document.createElement("memberstack-prebuilt-ui");
324
- element.display = type.toLowerCase();
325
- element.params = params;
326
- element.onSuccess = resolveModal;
327
- modal = element;
328
- document.body.appendChild(modal);
329
- return modalPromise;
330
- });
331
- var hideModal = () => {
332
- try {
333
- modal == null ? void 0 : modal.remove();
334
- } catch (e) {
335
- }
336
- };
337
-
338
- // src/utils/cookies.ts
339
- var import_js_cookie = __toESM(require("js-cookie"));
340
- var memberAuthTokenName = "_ms-mid";
341
- function isLocalStorageAvailable() {
342
- try {
343
- localStorage.setItem("test", "test");
344
- localStorage.removeItem("test");
345
- return true;
346
- } catch (e) {
347
- return false;
348
- }
349
- }
350
- var localStorageAvailable = isLocalStorageAvailable();
351
- var useCookies = false;
352
- var setCookieOnRootDomain = false;
353
- var apiDomain = "";
354
- var setUseCookies = (setCookieOnRoot) => {
355
- useCookies = true;
356
- if (setCookieOnRoot)
357
- setCookieOnRootDomain = true;
358
- };
359
- var setApiDomain = (domain) => {
360
- try {
361
- if (domain.startsWith("http://") || domain.startsWith("https://")) {
362
- const url = new URL(domain);
363
- apiDomain = url.hostname;
364
- } else {
365
- apiDomain = domain;
366
- }
367
- } catch (e) {
368
- apiDomain = domain;
369
- }
370
- };
371
- var extractDomainFromHostname = (hostname) => {
372
- var _a, _b;
373
- const hostnameParts = hostname.split(".");
374
- const isCountryCodeTLD = hostnameParts.length >= 4 && ((_b = (_a = hostnameParts[hostnameParts.length - 2]) == null ? void 0 : _a.length) != null ? _b : 0) <= 3;
375
- if (isCountryCodeTLD) {
376
- return hostnameParts.slice(-3).join(".");
377
- } else {
378
- return hostnameParts.slice(-2).join(".");
379
- }
380
- };
381
- var useCookiesValid = () => {
382
- if (!useCookies)
383
- return false;
384
- if (setCookieOnRootDomain) {
385
- const apiDomainHost = extractDomainFromHostname(apiDomain);
386
- const currentHost = extractDomainFromHostname(window.location.hostname);
387
- return apiDomainHost === currentHost;
388
- }
389
- return true;
390
- };
391
- var setMemberToken = (token, expires) => {
392
- if (localStorageAvailable && useCookiesValid() === false) {
393
- localStorage.setItem(memberAuthTokenName, token);
394
- } else {
395
- const domain = extractDomainFromHostname(window.location.hostname);
396
- import_js_cookie.default.set(memberAuthTokenName, token, __spreadValues({
397
- expires: expires && Number(expires) || 14,
398
- sameSite: "strict"
399
- }, setCookieOnRootDomain && { domain }));
400
- }
401
- };
402
- var removeMemberToken = () => {
403
- if (localStorageAvailable) {
404
- localStorage.removeItem(memberAuthTokenName);
405
- }
406
- const domain = extractDomainFromHostname(window.location.hostname);
407
- import_js_cookie.default.set(memberAuthTokenName, "", __spreadValues({
408
- expires: -1,
409
- sameSite: "strict"
410
- }, setCookieOnRootDomain && { domain }));
411
- import_js_cookie.default.set(memberAuthTokenName, "", {
412
- expires: -1,
413
- sameSite: "strict"
414
- });
415
- };
416
- var getMemberToken = () => {
417
- if (localStorageAvailable) {
418
- const memAuthToken = localStorage.getItem(memberAuthTokenName);
419
- if (memAuthToken)
420
- return memAuthToken;
421
- }
422
- return import_js_cookie.default.get(memberAuthTokenName);
423
- };
424
- var setMemberTokenIfAvailable = () => {
425
- if (typeof window !== "undefined") {
426
- const urlParams = new URLSearchParams(window.location.search);
427
- const memberToken = urlParams.get("memberToken");
428
- if (memberToken)
429
- setMemberToken(memberToken);
430
- }
431
- };
432
- var getSessionId = () => {
433
- if (typeof window === "undefined")
434
- return null;
435
- const sessionId = window.localStorage.getItem("ms_session_id");
436
- if (!sessionId || sessionId.length > 26) {
437
- window.localStorage.removeItem("ms_session_id");
438
- return null;
439
- }
440
- return sessionId;
441
- };
442
- var setSessionId = (sessionId) => {
443
- if (typeof window !== "undefined") {
444
- window.localStorage.setItem("ms_session_id", sessionId);
445
- } else {
446
- console.warn("setSessionId: window is not defined");
447
- }
448
- };
449
- var removeSessionId = () => {
450
- if (typeof window !== "undefined") {
451
- window.localStorage.removeItem("ms_session_id");
452
- } else {
453
- console.warn("removeSessionId: window is not defined");
454
- }
455
- };
456
-
457
- // src/methods/requests/requests.ts
458
- var import_axios = __toESM(require("axios"));
459
-
460
- // src/constants/endpoints.ts
461
- var endpoints = {
462
- API: "http://localhost:3005"
463
- };
464
-
465
- // src/methods/requests/requests.ts
466
- var createRequestHandler = ({
467
- publicKey,
468
- appId,
469
- token,
470
- customEndpoint
471
- }) => {
472
- return {
473
- sendRequest: (data, options) => __async(void 0, null, function* () {
474
- var _a, _b, _c, _d, _e, _f, _g, _h;
475
- try {
476
- const { url } = data;
477
- const memberToken = getMemberToken();
478
- const sessionToken = getSessionId();
479
- const authHeader = [
480
- (_b = (_a = data.headers) == null ? void 0 : _a["Authorization"]) == null ? void 0 : _b.replace("Bearer ", ""),
481
- memberToken,
482
- options == null ? void 0 : options.token
483
- ].find((x) => x);
484
- const formattedUrl = `${customEndpoint || endpoints.API}${url}`;
485
- const res = yield (0, import_axios.default)({
486
- method: data.method,
487
- data: data.data,
488
- url: formattedUrl,
489
- headers: __spreadProps(__spreadValues(__spreadValues(__spreadProps(__spreadValues(__spreadValues(__spreadValues({}, authHeader && { authorization: `Bearer ${authHeader}` }), publicKey && { ["X-API-Key" /* API_KEY */]: publicKey }), appId && { ["X-APP-ID" /* APP_ID */]: appId }), {
490
- ["X-User-Agent" /* USER_AGENT */]: "@memberstack/client@1.2.0"
491
- }), data.contentType && { "Content-Type": data.contentType }), sessionToken && {
492
- ["X-Session-ID" /* SESSION_ID */]: sessionToken
493
- }), {
494
- "referring-path": window.location.pathname
495
- }),
496
- withCredentials: true
497
- });
498
- if ((_c = res == null ? void 0 : res.headers) == null ? void 0 : _c["ms-mid"]) {
499
- token = res.headers["ms-mid"];
500
- }
501
- if ((_d = res == null ? void 0 : res.data) == null ? void 0 : _d.error) {
502
- if (res.data.error.name === "JsonWebTokenError") {
503
- throw {
504
- code: "client/invalid-token",
505
- message: "An invalid token has been provided. Please make sure the token is valid."
506
- };
507
- }
508
- throw (_e = res.data) == null ? void 0 : _e.error;
509
- }
510
- return res == null ? void 0 : res.data;
511
- } catch (e) {
512
- const error = e;
513
- if (!error.response)
514
- throw e;
515
- throw ((_g = (_f = error.response) == null ? void 0 : _f.data) == null ? void 0 : _g.error) || ((_h = error.response) == null ? void 0 : _h.data);
516
- }
517
- }),
518
- sendRequestWithFetch: (data, options) => __async(void 0, null, function* () {
519
- var _a, _b;
520
- try {
521
- const { url, method, data: bodyData, headers, contentType } = data;
522
- const memberToken = getMemberToken();
523
- const authHeader = [
524
- (_a = headers == null ? void 0 : headers["Authorization"]) == null ? void 0 : _a.replace("Bearer ", ""),
525
- memberToken,
526
- options == null ? void 0 : options.token
527
- ].find((x) => x);
528
- const formattedUrl = `${customEndpoint || endpoints.API}${url}`;
529
- const fetchHeaders = __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, authHeader && { Authorization: `Bearer ${authHeader}` }), publicKey && { ["X-API-Key" /* API_KEY */]: publicKey }), appId && { ["X-APP-ID" /* APP_ID */]: appId }), {
530
- ["X-User-Agent" /* USER_AGENT */]: "@memberstack/client@1.2.0",
531
- "Content-Type": "application/json",
532
- Referer: window.location.href
533
- });
534
- const response = yield fetch(formattedUrl, {
535
- method,
536
- headers: fetchHeaders,
537
- body: bodyData ? JSON.stringify(bodyData) : void 0,
538
- credentials: "include",
539
- keepalive: true
540
- // Keeps the connection open for further requests
541
- });
542
- const contentTypeHeader = response.headers.get("content-type");
543
- let result;
544
- if (contentTypeHeader == null ? void 0 : contentTypeHeader.includes("application/json")) {
545
- result = yield response.json();
546
- } else if (contentTypeHeader == null ? void 0 : contentTypeHeader.includes("text")) {
547
- result = yield response.text();
548
- } else if (response.status === 204) {
549
- result = null;
550
- } else {
551
- result = yield response.text();
552
- }
553
- if (response.headers.get("ms-mid")) {
554
- token = response.headers.get("ms-mid");
555
- }
556
- if (!response.ok) {
557
- if (((_b = result == null ? void 0 : result.error) == null ? void 0 : _b.name) === "JsonWebTokenError") {
558
- throw {
559
- code: "client/invalid-token",
560
- message: "An invalid token has been provided. Please make sure the token is valid."
561
- };
562
- }
563
- throw (result == null ? void 0 : result.error) || result;
564
- }
565
- return result;
566
- } catch (e) {
567
- console.error("Error in sendRequestWithFetch:", e);
568
- throw e;
569
- }
570
- })
571
- };
572
- };
573
-
574
- // src/auth/index.ts
575
- var createObservable = () => {
576
- const observer = /* @__PURE__ */ new Map();
577
- return {
578
- subscribe: (key, fn) => {
579
- if (typeof fn !== "function")
580
- return;
581
- return observer.set(key, fn);
582
- },
583
- unsubscribe: (key) => {
584
- return observer.delete(key);
585
- },
586
- notify: (data) => {
587
- return [...observer.values()].forEach((fn) => fn(data));
588
- }
589
- };
590
- };
591
- var observable = createObservable();
592
- var getPersistedMember = () => {
593
- const stored = localStorage == null ? void 0 : localStorage.getItem("_ms-mem");
594
- return stored ? JSON.parse(stored) : null;
595
- };
596
- var setPersistedMember = (member) => {
597
- if (member) {
598
- const data = JSON.stringify(member);
599
- if (data)
600
- localStorage == null ? void 0 : localStorage.setItem("_ms-mem", data);
601
- observable.notify(member);
602
- }
603
- };
604
- var updatePersistedMember = (member) => {
605
- if (member) {
606
- const data = JSON.stringify(member);
607
- if (data)
608
- localStorage == null ? void 0 : localStorage.setItem("_ms-mem", data);
609
- } else {
610
- localStorage == null ? void 0 : localStorage.removeItem("_ms-mem");
611
- removeMemberToken();
612
- }
613
- };
614
- var unsetPersistedMember = () => {
615
- localStorage == null ? void 0 : localStorage.removeItem("_ms-mem");
616
- removeMemberToken();
617
- removeSessionId();
618
- observable.notify(null);
619
- };
620
- var onAuthChange = (cb) => {
621
- const id = Math.floor(Math.random() * 1e3);
622
- observable.subscribe(id, cb);
623
- return {
624
- unsubscribe: () => observable.unsubscribe(id)
625
- };
626
- };
627
-
628
- // src/methods/requests/index.ts
629
- function getSessionDurationDays(unixTimestampMillis) {
630
- const now = Date.now();
631
- const differenceMillis = unixTimestampMillis - now;
632
- return Math.ceil(differenceMillis / (24 * 60 * 60 * 1e3));
633
- }
634
- var addHeaders = (options) => {
635
- const opts = options;
636
- return __spreadValues({}, (opts == null ? void 0 : opts.token) && {
637
- Authorization: `Bearer ${opts.token}`
638
- });
639
- };
640
- var promiseResolve;
641
- var promiseReject;
642
- var receiveMessage = (event) => {
643
- var _a;
644
- const { data, origin } = event;
645
- if (API_ENDPOINT !== origin)
646
- return;
647
- if ((_a = data == null ? void 0 : data.data) == null ? void 0 : _a.member) {
648
- const sessionDurationDays = getSessionDurationDays(data.data.tokens.expires);
649
- setPersistedMember(data.data.member);
650
- setMemberToken(data.data.tokens.accessToken, sessionDurationDays);
651
- }
652
- if (data == null ? void 0 : data.error) {
653
- promiseReject == null ? void 0 : promiseReject(data.error);
654
- }
655
- promiseResolve == null ? void 0 : promiseResolve(data);
656
- };
657
- var windowObjectReference = null;
658
- var previousUrl = null;
659
- var openSignInWindow = (url, name) => __async(void 0, null, function* () {
660
- window.removeEventListener("message", receiveMessage);
661
- const dualScreenLeft = window.screenLeft !== void 0 ? window.screenLeft : window.screenX;
662
- const dualScreenTop = window.screenTop !== void 0 ? window.screenTop : window.screenY;
663
- const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
664
- const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
665
- const systemZoom = width / window.screen.availWidth;
666
- const left = (width - 600) / 2 / systemZoom + dualScreenLeft;
667
- const top = (height - 700) / 2 / systemZoom + dualScreenTop;
668
- const strWindowFeatures = `toolbar=no, menubar=no, width=${600 / systemZoom}, height=${700 / systemZoom}, top=${top}, left=${left}`;
669
- if (windowObjectReference === null || windowObjectReference.closed) {
670
- windowObjectReference = window.open(url, name, strWindowFeatures);
671
- } else if (previousUrl !== url) {
672
- windowObjectReference = window.open(url, name, strWindowFeatures);
673
- windowObjectReference == null ? void 0 : windowObjectReference.focus();
674
- } else {
675
- windowObjectReference == null ? void 0 : windowObjectReference.focus();
676
- }
677
- window.addEventListener("message", (event) => receiveMessage(event), false);
678
- previousUrl = url;
679
- window.addEventListener("beforeunload", () => {
680
- windowObjectReference == null ? void 0 : windowObjectReference.close();
681
- });
682
- return new Promise((resolve, reject) => {
683
- promiseResolve = resolve;
684
- promiseReject = reject;
685
- });
686
- });
687
- function getBrowser() {
688
- const userAgent = navigator.userAgent;
689
- if (/Edg/i.test(userAgent))
690
- return "EDGE";
691
- if (/Trident/i.test(userAgent) || /MSIE/i.test(userAgent))
692
- return "INTERNET_EXPLORER";
693
- if (/Safari/i.test(userAgent) && !/Chrome/i.test(userAgent))
694
- return "SAFARI";
695
- if (/Firefox/i.test(userAgent))
696
- return "FIREFOX";
697
- if (/Chrome/i.test(userAgent) && !/Edg/i.test(userAgent))
698
- return "CHROME";
699
- if (/OPR/i.test(userAgent) || /Opera/i.test(userAgent))
700
- return "OPERA";
701
- return "OTHER";
702
- }
703
- function getOS() {
704
- const userAgent = navigator.userAgent;
705
- if (/Windows/i.test(userAgent))
706
- return "WINDOWS";
707
- if (/Macintosh|Mac OS X/i.test(userAgent))
708
- return "MACOS";
709
- if (/Android/i.test(userAgent))
710
- return "ANDROID";
711
- if (/iPhone|iPad|iPod/i.test(userAgent))
712
- return "IOS";
713
- if (/Linux/i.test(userAgent))
714
- return "LINUX";
715
- return "OTHER";
716
- }
717
- function getScreenSize() {
718
- const width = window.innerWidth;
719
- if (width <= 768)
720
- return "PHONE";
721
- if (width <= 1024)
722
- return "TABLET";
723
- return "DESKTOP";
724
- }
725
- function getUTMParams() {
726
- const params = new URLSearchParams(window.location.search);
727
- const utmParams = {};
728
- const utmKeys = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"];
729
- utmKeys.forEach((key) => {
730
- if (params.has(key)) {
731
- utmParams[key] = params.get(key);
732
- }
733
- });
734
- return utmParams;
735
- }
736
- function getConversionData() {
737
- return {
738
- browser: getBrowser(),
739
- os: getOS(),
740
- screenSize: getScreenSize(),
741
- sessionId: getSessionId(),
742
- utmParams: getUTMParams()
743
- };
744
- }
745
- var API_ENDPOINT;
746
- var initRequest = ({
747
- publicKey,
748
- appId,
749
- token,
750
- domain
751
- //sessionDurationDays
752
- }) => {
753
- const { sendRequest, sendRequestWithFetch } = createRequestHandler({
754
- publicKey,
755
- token,
756
- customEndpoint: domain,
757
- appId
758
- });
759
- API_ENDPOINT = domain;
760
- return {
761
- _Event(params) {
762
- return __async(this, null, function* () {
763
- const payload = __spreadValues(__spreadValues({}, params.data), getConversionData());
764
- return sendRequestWithFetch({
765
- method: "POST" /* POST */,
766
- url: `/event`,
767
- data: payload
768
- });
769
- });
770
- },
771
- /**
772
- * Permanently deletes the current member's account.
773
- * This action cannot be undone. The member will be logged out after deletion.
774
- *
775
- * @returns Promise resolving to deletion confirmation
776
- *
777
- * @example
778
- * ```typescript
779
- * // Confirm with user before calling
780
- * if (confirm('Are you sure? This cannot be undone.')) {
781
- * await memberstack.deleteMember();
782
- * window.location.href = '/goodbye';
783
- * }
784
- * ```
785
- */
786
- deleteMember() {
787
- return __async(this, null, function* () {
788
- const data = yield sendRequest({
789
- method: "DELETE" /* DELETE */,
790
- url: `/member`
791
- });
792
- unsetPersistedMember();
793
- return data;
794
- });
795
- },
796
- postIsTyping(params) {
797
- return __async(this, null, function* () {
798
- return sendRequest({
799
- method: "POST" /* POST */,
800
- url: `/comments/posts/typing`,
801
- data: {
802
- channelKey: params.channelKey
803
- }
804
- });
805
- });
806
- },
807
- getChannelInfo(params) {
808
- return __async(this, null, function* () {
809
- const queryParams = new URLSearchParams({
810
- channelKey: params.channelKey
811
- });
812
- return sendRequest({
813
- method: "GET" /* GET */,
814
- url: `/comments/channels/info?${queryParams}`
815
- });
816
- });
817
- },
818
- subscribeToChannel(params) {
819
- return __async(this, null, function* () {
820
- return sendRequest({
821
- method: "POST" /* POST */,
822
- url: `/comments/channels/manage-subscription`,
823
- data: {
824
- channelKey: params.channelKey,
825
- action: params.action
826
- }
827
- });
828
- });
829
- },
830
- getPosts(params) {
831
- return __async(this, null, function* () {
832
- const queryParams = new URLSearchParams(__spreadValues(__spreadValues(__spreadValues({
833
- channelKey: params.channelKey
834
- }, params.after && {
835
- after: params.after
836
- }), params.order && {
837
- order: params.order
838
- }), params.limit && {
839
- limit: params.limit.toString()
840
- }));
841
- return sendRequest({
842
- method: "GET" /* GET */,
843
- url: `/comments/posts?${queryParams}`
844
- });
845
- });
846
- },
847
- getThreads(params) {
848
- return __async(this, null, function* () {
849
- const queryParams = new URLSearchParams(__spreadValues(__spreadValues(__spreadValues({
850
- postId: params.postId
851
- }, params.after && {
852
- after: params.after
853
- }), params.order && {
854
- order: params.order
855
- }), params.limit && {
856
- limit: params.limit.toString()
857
- }));
858
- return sendRequest({
859
- method: "GET" /* GET */,
860
- url: `/comments/threads?${queryParams}`
861
- });
862
- });
863
- },
864
- createPost(params) {
865
- return __async(this, null, function* () {
866
- return sendRequest({
867
- method: "POST" /* POST */,
868
- url: `/comments/posts`,
869
- data: {
870
- channelKey: params.channelKey,
871
- content: params.content,
872
- _url: window.location.origin + window.location.pathname
873
- }
874
- });
875
- });
876
- },
877
- updatePost(params) {
878
- return __async(this, null, function* () {
879
- return sendRequest({
880
- method: "PATCH" /* PATCH */,
881
- url: `/comments/posts/${params.postId}/update`,
882
- data: {
883
- content: params.content
884
- }
885
- });
886
- });
887
- },
888
- postVote(params) {
889
- return __async(this, null, function* () {
890
- return sendRequest({
891
- method: "POST" /* POST */,
892
- url: `/comments/posts/${params.postId}/vote`,
893
- data: {
894
- vote: params.vote
895
- }
896
- });
897
- });
898
- },
899
- deletePost(params) {
900
- return __async(this, null, function* () {
901
- return sendRequest({
902
- method: "DELETE" /* DELETE */,
903
- url: `/comments/posts/${params.postId}`
904
- });
905
- });
906
- },
907
- createThread(params) {
908
- return __async(this, null, function* () {
909
- return sendRequest({
910
- method: "POST" /* POST */,
911
- url: `/comments/threads`,
912
- data: {
913
- postId: params.postId,
914
- content: params.content
915
- }
916
- });
917
- });
918
- },
919
- updateThread(params) {
920
- return __async(this, null, function* () {
921
- return sendRequest({
922
- method: "PATCH" /* PATCH */,
923
- url: `/comments/threads/${params.threadId}/update`,
924
- data: {
925
- content: params.content
926
- }
927
- });
928
- });
929
- },
930
- // vote thread
931
- threadVote(params) {
932
- return __async(this, null, function* () {
933
- return sendRequest({
934
- method: "POST" /* POST */,
935
- url: `/comments/threads/${params.threadId}/vote`,
936
- data: {
937
- vote: params.vote
938
- }
939
- });
940
- });
941
- },
942
- deleteThread(params) {
943
- return __async(this, null, function* () {
944
- return sendRequest({
945
- method: "DELETE" /* DELETE */,
946
- url: `/comments/threads/${params.threadId}`
947
- });
948
- });
949
- },
950
- /**
951
- * Retrieves gated/secure content by its content ID.
952
- * Use this to fetch content that requires specific plan access.
953
- *
954
- * @param params - Content parameters
955
- * @param params.contentId - The ID of the secure content block to retrieve
956
- * @returns Promise resolving to the secure content data
957
- *
958
- * @example
959
- * ```typescript
960
- * const { data: content } = await memberstack.getSecureContent({
961
- * contentId: 'cnt_abc123'
962
- * });
963
- * document.getElementById('premium-content').innerHTML = content.html;
964
- * ```
965
- */
966
- getSecureContent(params) {
967
- return __async(this, null, function* () {
968
- const data = yield sendRequest({
969
- method: "POST" /* POST */,
970
- url: "/secure-content",
971
- data: {
972
- contentId: params.contentId
973
- }
974
- });
975
- return data;
976
- });
977
- },
978
- /**
979
- * Signs up a new member using an OAuth provider (e.g., Google, Facebook).
980
- * Opens a popup window for the OAuth flow. On success, the member is created and logged in.
981
- *
982
- * @param params - Signup parameters
983
- * @param params.provider - The OAuth provider to use ('google', 'facebook', etc.)
984
- * @param params.customFields - Optional custom field values to set during signup
985
- * @param params.plans - Optional array of plan objects to assign on signup
986
- * @param params.inviteToken - Optional team invite token
987
- * @returns Promise resolving to the authenticated member data
988
- *
989
- * @example Sign up with Google
990
- * ```typescript
991
- * const { data } = await memberstack.signupWithProvider({
992
- * provider: 'google'
993
- * });
994
- * console.log('Signed up:', data.member.auth.email);
995
- * ```
996
- *
997
- * @example Sign up with custom fields
998
- * ```typescript
999
- * await memberstack.signupWithProvider({
1000
- * provider: 'google',
1001
- * customFields: { role: 'developer' },
1002
- * plans: [{ planId: 'pln_free' }]
1003
- * });
1004
- * ```
1005
- */
1006
- signupWithProvider(params) {
1007
- return __async(this, null, function* () {
1008
- const customFields = encodeURIComponent(params.customFields ? JSON.stringify(params.customFields) : "{}");
1009
- const plans = encodeURIComponent(params.plans ? JSON.stringify(params.plans) : "[]");
1010
- const conversionData = getConversionData();
1011
- const queryParams = new URLSearchParams(__spreadProps(__spreadValues(__spreadProps(__spreadValues(__spreadValues({
1012
- provider: params.provider,
1013
- customFields,
1014
- plans,
1015
- appId: appId != null ? appId : ""
1016
- }, publicKey && {
1017
- publicKey
1018
- }), params.inviteToken && {
1019
- inviteToken: params.inviteToken
1020
- }), {
1021
- url: window.location.pathname,
1022
- origin: window.location.hostname
1023
- }), conversionData.sessionId && { sessionId: conversionData.sessionId }), {
1024
- browser: conversionData.browser,
1025
- os: conversionData.os,
1026
- screenSize: conversionData.screenSize
1027
- }));
1028
- return openSignInWindow(`${domain}/auth-provider/signup?${queryParams}`, "signup");
1029
- });
1030
- },
1031
- /**
1032
- * Logs in an existing member using an OAuth provider (e.g., Google, Facebook).
1033
- * Opens a popup window for the OAuth flow. Member must already have an account linked to this provider.
1034
- *
1035
- * @param params - Login parameters
1036
- * @param params.provider - The OAuth provider to use ('google', 'facebook', etc.)
1037
- * @param params.allowSignup - If true, creates a new account if one doesn't exist (default: false)
1038
- * @returns Promise resolving to the authenticated member data
1039
- *
1040
- * @example Log in with Google
1041
- * ```typescript
1042
- * const { data } = await memberstack.loginWithProvider({
1043
- * provider: 'google'
1044
- * });
1045
- * console.log('Logged in:', data.member.auth.email);
1046
- * ```
1047
- *
1048
- * @example Allow signup if account doesn't exist
1049
- * ```typescript
1050
- * const { data } = await memberstack.loginWithProvider({
1051
- * provider: 'google',
1052
- * allowSignup: true
1053
- * });
1054
- * ```
1055
- */
1056
- loginWithProvider(params) {
1057
- return __async(this, null, function* () {
1058
- const allowSignup = encodeURIComponent(params.allowSignup === true ? "true" : "false");
1059
- const queryParams = new URLSearchParams(__spreadProps(__spreadValues({
1060
- provider: params.provider,
1061
- appId: appId != null ? appId : ""
1062
- }, publicKey && {
1063
- publicKey
1064
- }), {
1065
- origin: window.location.hostname,
1066
- allowSignup
1067
- }));
1068
- return openSignInWindow(`${domain}/auth-provider/login?${queryParams}`, "login");
1069
- });
1070
- },
1071
- /**
1072
- * Connects an OAuth provider to the current member's account.
1073
- * Allows the member to use additional OAuth providers for login.
1074
- * Member must be logged in to use this method.
1075
- *
1076
- * @param params - Provider parameters
1077
- * @param params.provider - The OAuth provider to connect ('google', 'facebook', etc.)
1078
- * @returns Promise resolving to the connection result
1079
- *
1080
- * @example Connect Google to existing account
1081
- * ```typescript
1082
- * await memberstack.connectProvider({
1083
- * provider: 'google'
1084
- * });
1085
- * // Member can now log in with either email/password or Google
1086
- * ```
1087
- */
1088
- connectProvider(params) {
1089
- return __async(this, null, function* () {
1090
- const memberToken = getMemberToken();
1091
- const queryParams = new URLSearchParams(__spreadProps(__spreadValues(__spreadValues({
1092
- provider: params.provider,
1093
- appId: appId != null ? appId : ""
1094
- }, publicKey && {
1095
- publicKey
1096
- }), memberToken && { member: memberToken }), {
1097
- origin: window.location.hostname
1098
- }));
1099
- return openSignInWindow(`${domain}/auth-provider/connect?${queryParams}`, "connect");
1100
- });
1101
- },
1102
- /**
1103
- * Disconnects an OAuth provider from the current member's account.
1104
- * After disconnecting, the member can no longer use this provider to log in.
1105
- * Member must be logged in and have another login method available.
1106
- *
1107
- * @param params - Provider parameters
1108
- * @param params.provider - The OAuth provider to disconnect ('google', 'facebook', etc.)
1109
- * @returns Promise resolving to the disconnection result
1110
- *
1111
- * @example Disconnect Google from account
1112
- * ```typescript
1113
- * await memberstack.disconnectProvider({
1114
- * provider: 'google'
1115
- * });
1116
- * // Member must now use email/password or another connected provider
1117
- * ```
1118
- */
1119
- disconnectProvider(params) {
1120
- return __async(this, null, function* () {
1121
- return sendRequest({
1122
- method: "POST" /* POST */,
1123
- url: "/member/disconnect-provider",
1124
- data: {
1125
- provider: params.provider
1126
- }
1127
- });
1128
- });
1129
- },
1130
- getAppAndMember(params) {
1131
- return __async(this, null, function* () {
1132
- var _a2, _b;
1133
- const data = yield sendRequest({
1134
- method: "POST" /* POST */,
1135
- url: `/app-member`,
1136
- data: {
1137
- data: {
1138
- // @ts-ignore
1139
- includeSSOText: window == null ? void 0 : window.ssoUI,
1140
- trackPageView: params == null ? void 0 : params.trackPageView,
1141
- sessionData: __spreadValues({}, getConversionData())
1142
- }
1143
- }
1144
- });
1145
- try {
1146
- const backendSessionId = (_b = (_a2 = data.data) == null ? void 0 : _a2.sessionData) == null ? void 0 : _b.sessionId;
1147
- const storedSessionId = getSessionId();
1148
- if (storedSessionId !== backendSessionId)
1149
- setSessionId(backendSessionId);
1150
- } catch (e) {
1151
- }
1152
- return data;
1153
- });
1154
- },
1155
- /**
1156
- * Retrieves your Memberstack app configuration.
1157
- * Returns app settings including authentication options, branding, and enabled features.
1158
- *
1159
- * @returns Promise resolving to the app configuration
1160
- *
1161
- * @example
1162
- * ```typescript
1163
- * const { data: app } = await memberstack.getApp();
1164
- * console.log('App name:', app.name);
1165
- * console.log('OAuth providers:', app.authProviders);
1166
- * ```
1167
- */
1168
- getApp() {
1169
- return __async(this, null, function* () {
1170
- const queryParams = new URLSearchParams({
1171
- // @ts-ignore
1172
- includeSSOText: window == null ? void 0 : window.ssoUI
1173
- });
1174
- return sendRequest({
1175
- method: "GET" /* GET */,
1176
- url: `/app?${queryParams}`
1177
- });
1178
- });
1179
- },
1180
- /**
1181
- * Authenticates a member using their email and password.
1182
- * On success, the member's session is automatically stored and they become the current user.
1183
- *
1184
- * @param params - Login credentials
1185
- * @param params.email - The member's email address
1186
- * @param params.password - The member's password
1187
- * @returns Promise resolving to the authenticated member data and tokens
1188
- * @throws When credentials are invalid or account doesn't exist
1189
- *
1190
- * @example
1191
- * ```typescript
1192
- * try {
1193
- * const { data } = await memberstack.loginMemberEmailPassword({
1194
- * email: 'user@example.com',
1195
- * password: 'securePassword123'
1196
- * });
1197
- * console.log('Logged in:', data.member.auth.email);
1198
- * } catch (error) {
1199
- * console.error('Login failed:', error.message);
1200
- * }
1201
- * ```
1202
- */
1203
- loginMemberEmailPassword(params, options) {
1204
- return __async(this, null, function* () {
1205
- const data = yield sendRequest({
1206
- method: "POST" /* POST */,
1207
- url: `/auth/login`,
1208
- data: {
1209
- email: params.email,
1210
- password: params.password,
1211
- options
1212
- }
1213
- });
1214
- const sessionDurationDays = getSessionDurationDays(data.data.tokens.expires);
1215
- setPersistedMember(data.data.member);
1216
- setMemberToken(data.data.tokens.accessToken, sessionDurationDays);
1217
- return data;
1218
- });
1219
- },
1220
- /**
1221
- * Sends a passwordless login code to an existing member's email.
1222
- * The member will receive a one-time code they can use to log in without a password.
1223
- *
1224
- * @param params - Email parameters
1225
- * @param params.email - The member's email address
1226
- * @returns Promise resolving to success confirmation
1227
- * @throws When the email is not associated with an existing member
1228
- *
1229
- * @example
1230
- * ```typescript
1231
- * // Step 1: Send the code
1232
- * await memberstack.sendMemberLoginPasswordlessEmail({
1233
- * email: 'user@example.com'
1234
- * });
1235
- * // User receives email with code
1236
- *
1237
- * // Step 2: Complete login with the code (see loginMemberPasswordless)
1238
- * ```
1239
- */
1240
- sendMemberLoginPasswordlessEmail(params, options) {
1241
- return __async(this, null, function* () {
1242
- return yield sendRequest({
1243
- method: "POST" /* POST */,
1244
- url: `/auth/passwordless/login/send`,
1245
- data: {
1246
- email: params.email
1247
- }
1248
- });
1249
- });
1250
- },
1251
- /**
1252
- * Sends a passwordless signup code to a new member's email.
1253
- * Use this for registration flows where you don't want to collect passwords.
1254
- *
1255
- * @param params - Email parameters
1256
- * @param params.email - The new member's email address
1257
- * @returns Promise resolving to success confirmation
1258
- *
1259
- * @example
1260
- * ```typescript
1261
- * // Step 1: Send the signup code
1262
- * await memberstack.sendMemberSignupPasswordlessEmail({
1263
- * email: 'newuser@example.com'
1264
- * });
1265
- *
1266
- * // Step 2: Complete signup with the code (see signupMemberPasswordless)
1267
- * ```
1268
- */
1269
- sendMemberSignupPasswordlessEmail(params, options) {
1270
- return __async(this, null, function* () {
1271
- return yield sendRequest({
1272
- method: "POST" /* POST */,
1273
- url: `/auth/passwordless/signup/send`,
1274
- data: {
1275
- email: params.email
1276
- }
1277
- });
1278
- });
1279
- },
1280
- /**
1281
- * Completes passwordless login using the code sent via email.
1282
- * On success, the member is logged in and their session is stored.
1283
- *
1284
- * @param params - Login credentials
1285
- * @param params.email - The member's email address
1286
- * @param params.passwordlessToken - The one-time code from the email
1287
- * @returns Promise resolving to the authenticated member data and tokens
1288
- * @throws When the code is invalid or expired
1289
- *
1290
- * @example Complete passwordless login flow
1291
- * ```typescript
1292
- * // After user enters the code from their email
1293
- * const { data } = await memberstack.loginMemberPasswordless({
1294
- * email: 'user@example.com',
1295
- * passwordlessToken: '123456' // Code from email
1296
- * });
1297
- * console.log('Logged in:', data.member.auth.email);
1298
- * ```
1299
- */
1300
- loginMemberPasswordless(params, options) {
1301
- return __async(this, null, function* () {
1302
- const data = yield sendRequest({
1303
- method: "POST" /* POST */,
1304
- url: `/auth/passwordless/login`,
1305
- data: {
1306
- passwordlessToken: params.passwordlessToken,
1307
- email: params.email,
1308
- options
1309
- }
1310
- });
1311
- const sessionDurationDays = getSessionDurationDays(data.data.tokens.expires);
1312
- setPersistedMember(data.data.member);
1313
- setMemberToken(data.data.tokens.accessToken, sessionDurationDays);
1314
- return data;
1315
- });
1316
- },
1317
- /**
1318
- * Retrieves details for a specific plan by ID.
1319
- * Returns plan information including name, description, and pricing.
1320
- *
1321
- * @param params - Plan parameters
1322
- * @param params.planId - The ID of the plan to retrieve
1323
- * @returns Promise resolving to the plan details
1324
- *
1325
- * @example
1326
- * ```typescript
1327
- * const { data: plan } = await memberstack.getPlan({
1328
- * planId: 'pln_pro123'
1329
- * });
1330
- * console.log('Plan:', plan.name);
1331
- * console.log('Prices:', plan.prices);
1332
- * ```
1333
- */
1334
- getPlan(params) {
1335
- return __async(this, null, function* () {
1336
- return sendRequest({
1337
- method: "GET" /* GET */,
1338
- url: `/app/plans/${params.planId}`
1339
- });
1340
- });
1341
- },
1342
- /**
1343
- * Retrieves all plans configured for your Memberstack app.
1344
- * Returns both free and paid plans with their pricing information.
1345
- *
1346
- * @returns Promise resolving to an array of plans
1347
- *
1348
- * @example List all plans
1349
- * ```typescript
1350
- * const { data: plans } = await memberstack.getPlans();
1351
- *
1352
- * plans.forEach(plan => {
1353
- * console.log(plan.name, plan.id);
1354
- * plan.prices?.forEach(price => {
1355
- * console.log(` ${price.name}: ${price.amount} ${price.currency}`);
1356
- * });
1357
- * });
1358
- * ```
1359
- *
1360
- * @example Build a pricing page
1361
- * ```typescript
1362
- * const { data: plans } = await memberstack.getPlans();
1363
- *
1364
- * const pricingHtml = plans.map(plan => `
1365
- * <div class="plan">
1366
- * <h3>${plan.name}</h3>
1367
- * <p>${plan.description}</p>
1368
- * </div>
1369
- * `).join('');
1370
- * ```
1371
- */
1372
- getPlans() {
1373
- return __async(this, null, function* () {
1374
- const { data } = yield sendRequest({
1375
- method: "GET" /* GET */,
1376
- url: `/app`
1377
- });
1378
- return {
1379
- data: data.plans
1380
- };
1381
- });
1382
- },
1383
- /**
1384
- * Retrieves URL restriction groups configured for your app.
1385
- * These define which URLs require specific plans or authentication to access.
1386
- *
1387
- * @returns Promise resolving to an array of content access groups
1388
- *
1389
- * @example
1390
- * ```typescript
1391
- * const { data: groups } = await memberstack.getRestrictedUrlGroups();
1392
- *
1393
- * groups.forEach(group => {
1394
- * console.log('Group:', group.name);
1395
- * console.log('Required plans:', group.planIds);
1396
- * console.log('URLs:', group.urls);
1397
- * });
1398
- * ```
1399
- */
1400
- getRestrictedUrlGroups() {
1401
- return __async(this, null, function* () {
1402
- const { data } = yield sendRequest({
1403
- method: "GET" /* GET */,
1404
- url: `/app`
1405
- });
1406
- return {
1407
- data: data.contentGroups
1408
- };
1409
- });
1410
- },
1411
- /**
1412
- * Retrieves the currently authenticated member's data.
1413
- * Returns `null` if no user is logged in.
1414
- *
1415
- * @param options - Optional configuration
1416
- * @param options.useCache - If true, returns cached member data instead of fetching from server
1417
- * @returns Promise resolving to the current member's data, or null if not authenticated
1418
- *
1419
- * @example Check if user is logged in
1420
- * ```typescript
1421
- * const { data: member } = await memberstack.getCurrentMember();
1422
- *
1423
- * if (member) {
1424
- * console.log('Logged in as:', member.auth.email);
1425
- * console.log('Plans:', member.planConnections);
1426
- * } else {
1427
- * console.log('Not logged in');
1428
- * }
1429
- * ```
1430
- *
1431
- * @example Access member properties
1432
- * ```typescript
1433
- * const { data: member } = await memberstack.getCurrentMember();
1434
- *
1435
- * if (member) {
1436
- * const email = member.auth.email;
1437
- * const isVerified = member.verified;
1438
- * const customFields = member.customFields;
1439
- * const hasPro = member.planConnections.some(p => p.planId === 'pln_pro');
1440
- * }
1441
- * ```
1442
- */
1443
- getCurrentMember(options) {
1444
- return __async(this, null, function* () {
1445
- const memberToken = getMemberToken();
1446
- if (!memberToken)
1447
- return { data: null };
1448
- const getMemberRequest = sendRequest({
1449
- method: "GET" /* GET */,
1450
- url: `/member`,
1451
- headers: addHeaders(options)
1452
- });
1453
- function setMember() {
1454
- return __async(this, null, function* () {
1455
- const data = yield getMemberRequest;
1456
- updatePersistedMember(data.data);
1457
- });
1458
- }
1459
- setMember();
1460
- if ((options == null ? void 0 : options.useCache) === true) {
1461
- const member = getPersistedMember();
1462
- return { data: member };
1463
- } else {
1464
- return getMemberRequest;
1465
- }
1466
- });
1467
- },
1468
- /**
1469
- * Retrieves the current member's JSON data store.
1470
- * This is a flexible key-value store for storing arbitrary member data.
1471
- *
1472
- * @returns Promise resolving to the member's JSON data object
1473
- *
1474
- * @example
1475
- * ```typescript
1476
- * const { data: json } = await memberstack.getMemberJSON();
1477
- * console.log('Preferences:', json.preferences);
1478
- * console.log('Last visited:', json.lastVisitedPage);
1479
- * ```
1480
- */
1481
- getMemberJSON(options) {
1482
- return __async(this, null, function* () {
1483
- return sendRequest({
1484
- method: "GET" /* GET */,
1485
- url: `/member/json`,
1486
- headers: addHeaders(options)
1487
- });
1488
- });
1489
- },
1490
- /**
1491
- * Updates the current member's JSON data store.
1492
- * You can store any JSON-serializable data. Updates are merged with existing data.
1493
- *
1494
- * @param params - JSON data to store
1495
- * @param params.json - Object containing the data to store
1496
- * @returns Promise resolving to the updated JSON data
1497
- *
1498
- * @example Store user preferences
1499
- * ```typescript
1500
- * await memberstack.updateMemberJSON({
1501
- * json: {
1502
- * preferences: { theme: 'dark', notifications: true },
1503
- * lastVisitedPage: '/dashboard',
1504
- * onboardingComplete: true
1505
- * }
1506
- * });
1507
- * ```
1508
- *
1509
- * @example Store app-specific data
1510
- * ```typescript
1511
- * await memberstack.updateMemberJSON({
1512
- * json: {
1513
- * savedItems: ['item1', 'item2'],
1514
- * progress: { level: 5, score: 1200 }
1515
- * }
1516
- * });
1517
- * ```
1518
- */
1519
- updateMemberJSON(params, options) {
1520
- return __async(this, null, function* () {
1521
- return sendRequest({
1522
- method: "POST" /* POST */,
1523
- url: `/member/json`,
1524
- data: {
1525
- json: params.json
1526
- },
1527
- headers: addHeaders(options)
1528
- });
1529
- });
1530
- },
1531
- /**
1532
- * Adds a free plan to the current member.
1533
- * For paid plans, use `purchasePlansWithCheckout()` instead.
1534
- *
1535
- * @param params - Plan parameters
1536
- * @param params.planId - The ID of the free plan to add
1537
- * @returns Promise resolving to the updated member data with the new plan
1538
- *
1539
- * @example Add a free tier plan
1540
- * ```typescript
1541
- * const { data } = await memberstack.addPlan({
1542
- * planId: 'pln_free_tier'
1543
- * });
1544
- * console.log('Plan added, redirect:', data.redirect);
1545
- * ```
1546
- */
1547
- addPlan(params, options) {
1548
- return __async(this, null, function* () {
1549
- return sendRequest({
1550
- method: "POST" /* POST */,
1551
- url: `/member/plans/add`,
1552
- data: {
1553
- planId: params.planId
1554
- },
1555
- headers: addHeaders(options)
1556
- });
1557
- });
1558
- },
1559
- /**
1560
- * Initiates a Stripe checkout session for purchasing a paid plan.
1561
- * By default, redirects the user to Stripe's hosted checkout page.
1562
- *
1563
- * @param params - Checkout configuration
1564
- * @param params.priceId - The Memberstack price ID to purchase (e.g., 'prc_monthly_pro')
1565
- * @param params.successUrl - URL to redirect to after successful payment (relative or absolute)
1566
- * @param params.cancelUrl - URL to redirect to if user cancels checkout (relative or absolute)
1567
- * @param params.couponId - Optional Stripe coupon ID to apply
1568
- * @param params.autoRedirect - Set to `false` to get the checkout URL without redirecting
1569
- * @returns Promise resolving to checkout data (includes URL if autoRedirect is false)
1570
- *
1571
- * @example Start checkout for a plan
1572
- * ```typescript
1573
- * await memberstack.purchasePlansWithCheckout({
1574
- * priceId: 'prc_monthly_pro',
1575
- * successUrl: '/welcome',
1576
- * cancelUrl: '/pricing'
1577
- * });
1578
- * // User is redirected to Stripe checkout
1579
- * ```
1580
- *
1581
- * @example Get checkout URL without redirecting
1582
- * ```typescript
1583
- * const { data } = await memberstack.purchasePlansWithCheckout({
1584
- * priceId: 'prc_monthly_pro',
1585
- * successUrl: '/welcome',
1586
- * cancelUrl: '/pricing',
1587
- * autoRedirect: false
1588
- * });
1589
- * console.log('Checkout URL:', data.url);
1590
- * ```
1591
- *
1592
- * @example Apply a coupon
1593
- * ```typescript
1594
- * await memberstack.purchasePlansWithCheckout({
1595
- * priceId: 'prc_annual_pro',
1596
- * couponId: 'SAVE20',
1597
- * successUrl: '/welcome',
1598
- * cancelUrl: '/pricing'
1599
- * });
1600
- * ```
1601
- */
1602
- purchasePlansWithCheckout(params, options) {
1603
- return __async(this, null, function* () {
1604
- function getRedirectURL(URL2) {
1605
- let redirectUrl = window.location.href;
1606
- const urlParam = URL2;
1607
- if (urlParam) {
1608
- if (urlParam.indexOf("http://") === 0 || urlParam.indexOf("https://") === 0) {
1609
- redirectUrl = urlParam;
1610
- } else {
1611
- redirectUrl = window.location.origin + urlParam;
1612
- }
1613
- }
1614
- return redirectUrl;
1615
- }
1616
- const success_url = params.successUrl ? getRedirectURL(params.successUrl) : void 0;
1617
- const cancel_url = params.cancelUrl ? getRedirectURL(params.cancelUrl) : window.location.href;
1618
- const request = yield sendRequest({
1619
- method: "POST" /* POST */,
1620
- url: `/member/plans/create-checkout-session`,
1621
- data: {
1622
- priceId: params.priceId,
1623
- couponId: params.couponId,
1624
- metadataForCheckout: params.metadataForCheckout,
1625
- //window.location requires dom
1626
- success_url,
1627
- cancel_url,
1628
- origin_url: window.location.href,
1629
- conversionData: __spreadValues({
1630
- url: window.location.pathname
1631
- }, getConversionData())
1632
- },
1633
- headers: addHeaders(options)
1634
- });
1635
- if (params.autoRedirect === false) {
1636
- return request;
1637
- }
1638
- window.location.href = request.data.url;
1639
- return request;
1640
- });
1641
- },
1642
- /**
1643
- * Opens the Stripe Customer Portal for the current member.
1644
- * The portal allows members to manage their subscriptions, update payment methods, and view invoices.
1645
- * By default, redirects the user to the Stripe-hosted portal.
1646
- *
1647
- * @param params - Portal configuration
1648
- * @param params.returnUrl - URL to redirect to when member exits the portal (relative or absolute)
1649
- * @param params.priceIds - Optional array of price IDs to show for plan switching
1650
- * @param params.autoRedirect - Set to `false` to get the portal URL without redirecting
1651
- * @returns Promise resolving to portal data (includes URL if autoRedirect is false)
1652
- *
1653
- * @example Open customer portal
1654
- * ```typescript
1655
- * await memberstack.launchStripeCustomerPortal({
1656
- * returnUrl: '/account'
1657
- * });
1658
- * // User is redirected to Stripe Customer Portal
1659
- * ```
1660
- *
1661
- * @example Get portal URL without redirecting
1662
- * ```typescript
1663
- * const { data } = await memberstack.launchStripeCustomerPortal({
1664
- * returnUrl: '/account',
1665
- * autoRedirect: false
1666
- * });
1667
- * console.log('Portal URL:', data.url);
1668
- * ```
1669
- */
1670
- launchStripeCustomerPortal(params, options) {
1671
- return __async(this, null, function* () {
1672
- function getRedirectURL(URL2) {
1673
- let redirectUrl = window.location.href;
1674
- const urlParam = URL2;
1675
- if (urlParam) {
1676
- if (urlParam.indexOf("http://") === 0 || urlParam.indexOf("https://") === 0) {
1677
- redirectUrl = urlParam;
1678
- } else {
1679
- redirectUrl = window.location.origin + urlParam;
1680
- }
1681
- }
1682
- return redirectUrl;
1683
- }
1684
- const returnUrl = (params == null ? void 0 : params.returnUrl) ? getRedirectURL(params.returnUrl) : void 0;
1685
- const request = yield sendRequest({
1686
- method: "POST" /* POST */,
1687
- url: `/member/create-billing-portal-session`,
1688
- data: __spreadValues({
1689
- //window.location requires dom
1690
- return_url: returnUrl,
1691
- origin_url: window.location.href
1692
- }, params && {
1693
- priceIds: params.priceIds,
1694
- configuration: params.configuration
1695
- }),
1696
- headers: addHeaders(options)
1697
- });
1698
- if ((params == null ? void 0 : params.autoRedirect) === false) {
1699
- return request;
1700
- }
1701
- window.location.href = request.data.url;
1702
- return request;
1703
- });
1704
- },
1705
- /**
1706
- * Removes a plan from the current member.
1707
- * For paid plans, this will cancel the subscription.
1708
- *
1709
- * @param params - Plan parameters
1710
- * @param params.planId - The ID of the plan to remove
1711
- * @returns Promise resolving to the updated member data
1712
- *
1713
- * @example Remove a plan
1714
- * ```typescript
1715
- * await memberstack.removePlan({
1716
- * planId: 'pln_premium'
1717
- * });
1718
- * // Plan removed/subscription cancelled
1719
- * ```
1720
- */
1721
- removePlan(params, options) {
1722
- return __async(this, null, function* () {
1723
- return sendRequest({
1724
- method: "POST" /* POST */,
1725
- url: `/member/plans/remove`,
1726
- data: {
1727
- planId: params.planId
1728
- },
1729
- headers: addHeaders(options)
1730
- });
1731
- });
1732
- },
1733
- /**
1734
- * Updates the current member's custom fields.
1735
- * Only updates the fields you specify; other fields remain unchanged.
1736
- *
1737
- * @param params - Update data
1738
- * @param params.customFields - Object containing custom field key-value pairs to update
1739
- * @returns Promise resolving to the updated member data
1740
- *
1741
- * @example Update custom fields
1742
- * ```typescript
1743
- * const { data: member } = await memberstack.updateMember({
1744
- * customFields: {
1745
- * firstName: 'Jane',
1746
- * company: 'Acme Inc',
1747
- * preferences: { theme: 'dark' }
1748
- * }
1749
- * });
1750
- * console.log('Updated:', member.customFields);
1751
- * ```
1752
- *
1753
- * @example Update a single field
1754
- * ```typescript
1755
- * await memberstack.updateMember({
1756
- * customFields: {
1757
- * lastLoginPage: window.location.pathname
1758
- * }
1759
- * });
1760
- * ```
1761
- */
1762
- updateMember(params, options) {
1763
- return __async(this, null, function* () {
1764
- return sendRequest({
1765
- method: "POST" /* POST */,
1766
- url: `/member`,
1767
- data: __spreadValues({}, params.customFields && { customFields: params.customFields }),
1768
- headers: addHeaders(options)
1769
- });
1770
- });
1771
- },
1772
- /**
1773
- * Updates the current member's authentication credentials (email and/or password).
1774
- * Requires the current password to verify the member's identity.
1775
- *
1776
- * @param params - Auth update parameters
1777
- * @param params.email - New email address (optional)
1778
- * @param params.oldPassword - Current password (required for password changes)
1779
- * @param params.newPassword - New password (optional)
1780
- * @returns Promise resolving to the updated member data
1781
- * @throws When the old password is incorrect
1782
- *
1783
- * @example Change email
1784
- * ```typescript
1785
- * await memberstack.updateMemberAuth({
1786
- * email: 'newemail@example.com',
1787
- * oldPassword: 'currentPassword'
1788
- * });
1789
- * ```
1790
- *
1791
- * @example Change password
1792
- * ```typescript
1793
- * await memberstack.updateMemberAuth({
1794
- * oldPassword: 'currentPassword',
1795
- * newPassword: 'newSecurePassword123'
1796
- * });
1797
- * ```
1798
- */
1799
- updateMemberAuth(params, options) {
1800
- return __async(this, null, function* () {
1801
- return sendRequest({
1802
- method: "POST" /* POST */,
1803
- url: `/member-auth`,
1804
- data: __spreadValues(__spreadValues(__spreadValues({}, params.email && { email: params.email }), params.oldPassword && { oldPassword: params.oldPassword }), params.newPassword && { newPassword: params.newPassword }),
1805
- headers: addHeaders(options)
1806
- });
1807
- });
1808
- },
1809
- /**
1810
- * Sets a password for a member who signed up via passwordless or OAuth.
1811
- * Use this when a member wants to add password-based login to their account.
1812
- *
1813
- * @param params - Password parameters
1814
- * @param params.password - The password to set
1815
- * @returns Promise resolving to the updated member data
1816
- *
1817
- * @example
1818
- * ```typescript
1819
- * // For members who signed up via Google OAuth or passwordless
1820
- * await memberstack.setPassword({
1821
- * password: 'newSecurePassword123'
1822
- * });
1823
- * // Member can now log in with email/password
1824
- * ```
1825
- */
1826
- setPassword(params, options) {
1827
- return __async(this, null, function* () {
1828
- return sendRequest({
1829
- method: "POST" /* POST */,
1830
- url: `/member/set-password`,
1831
- data: {
1832
- password: params.password
1833
- },
1834
- headers: addHeaders(options)
1835
- });
1836
- });
1837
- },
1838
- signupMemberPasswordless(params, options) {
1839
- return __async(this, null, function* () {
1840
- var _a2, _b, _c;
1841
- const data = yield sendRequest({
1842
- method: "POST" /* POST */,
1843
- url: `/auth/signup?isPasswordless=true`,
1844
- data: __spreadValues(__spreadProps(__spreadValues({
1845
- email: params.email,
1846
- customFields: params.customFields,
1847
- passwordlessToken: params.passwordlessToken,
1848
- metaData: params.metaData
1849
- }, params.plans && { plans: params.plans }), {
1850
- //internal use only
1851
- origin_domain: window.location.origin,
1852
- conversionData: __spreadValues(__spreadProps(__spreadValues({}, (_a2 = params == null ? void 0 : params.conversionData) != null ? _a2 : {}), {
1853
- url: window.location.pathname
1854
- }), getConversionData()),
1855
- options
1856
- }), ((_b = window.Rewardful) == null ? void 0 : _b.referral) && {
1857
- rewardfulData: {
1858
- // @ts-ignore
1859
- referral: window.Rewardful.referral,
1860
- // @ts-ignore
1861
- coupon: (_c = window.Rewardful.coupon) == null ? void 0 : _c.id
1862
- }
1863
- })
1864
- });
1865
- const sessionDurationDays = getSessionDurationDays(data.data.tokens.expires);
1866
- setPersistedMember(data.data.member);
1867
- setMemberToken(data.data.tokens.accessToken, sessionDurationDays);
1868
- return data;
1869
- });
1870
- },
1871
- /**
1872
- * Creates a new member account with email and password.
1873
- * On success, the member is automatically logged in and their session is stored.
1874
- *
1875
- * @param params - Signup details
1876
- * @param params.email - The new member's email address
1877
- * @param params.password - The new member's password (minimum 8 characters recommended)
1878
- * @param params.customFields - Optional custom field values defined in your Memberstack dashboard
1879
- * @param params.plans - Optional array of plan IDs to assign on signup (for free plans)
1880
- * @param params.metaData - Optional metadata to store with the member
1881
- * @param params.inviteToken - Optional team invite token for team signups
1882
- * @returns Promise resolving to the new member data and tokens
1883
- * @throws When email is already in use or validation fails
1884
- *
1885
- * @example Basic signup
1886
- * ```typescript
1887
- * const { data } = await memberstack.signupMemberEmailPassword({
1888
- * email: 'newuser@example.com',
1889
- * password: 'securePassword123'
1890
- * });
1891
- * console.log('Welcome!', data.member.id);
1892
- * ```
1893
- *
1894
- * @example Signup with custom fields and a free plan
1895
- * ```typescript
1896
- * const { data } = await memberstack.signupMemberEmailPassword({
1897
- * email: 'newuser@example.com',
1898
- * password: 'securePassword123',
1899
- * customFields: {
1900
- * firstName: 'Jane',
1901
- * lastName: 'Doe',
1902
- * company: 'Acme Inc'
1903
- * },
1904
- * plans: [{ planId: 'pln_free_tier' }]
1905
- * });
1906
- * ```
1907
- */
1908
- signupMemberEmailPassword(params, options) {
1909
- return __async(this, null, function* () {
1910
- var _a2, _b, _c;
1911
- const data = yield sendRequest({
1912
- method: "POST" /* POST */,
1913
- url: `/auth/signup`,
1914
- data: __spreadValues(__spreadProps(__spreadValues({
1915
- email: params.email,
1916
- password: params.password,
1917
- customFields: params.customFields,
1918
- metaData: params.metaData,
1919
- captchaToken: params.captchaToken,
1920
- inviteToken: params.inviteToken
1921
- }, params.plans && { plans: params.plans }), {
1922
- //internal use only
1923
- origin_domain: window.location.origin,
1924
- conversionData: __spreadValues(__spreadProps(__spreadValues({}, (_a2 = params == null ? void 0 : params.conversionData) != null ? _a2 : {}), {
1925
- url: window.location.pathname
1926
- }), getConversionData()),
1927
- options
1928
- }), ((_b = window.Rewardful) == null ? void 0 : _b.referral) && {
1929
- rewardfulData: {
1930
- // @ts-ignore
1931
- referral: window.Rewardful.referral,
1932
- // @ts-ignore
1933
- coupon: (_c = window.Rewardful.coupon) == null ? void 0 : _c.id
1934
- }
1935
- })
1936
- });
1937
- const sessionDurationDays = getSessionDurationDays(data.data.tokens.expires);
1938
- setPersistedMember(data.data.member);
1939
- setMemberToken(data.data.tokens.accessToken, sessionDurationDays);
1940
- return data;
1941
- });
1942
- },
1943
- joinTeam(params, options) {
1944
- return __async(this, null, function* () {
1945
- return sendRequest({
1946
- method: "POST" /* POST */,
1947
- url: `/member/team/join`,
1948
- data: {
1949
- inviteToken: params.inviteToken
1950
- },
1951
- headers: addHeaders(options)
1952
- });
1953
- });
1954
- },
1955
- getTeam(params, options) {
1956
- return __async(this, null, function* () {
1957
- return sendRequest({
1958
- method: "GET" /* GET */,
1959
- url: `/member/team/${params.teamId}`,
1960
- headers: addHeaders(options)
1961
- });
1962
- });
1963
- },
1964
- removeMemberFromTeam(params, options) {
1965
- return __async(this, null, function* () {
1966
- return sendRequest({
1967
- method: "POST" /* POST */,
1968
- url: `/member/team/remove-member`,
1969
- data: {
1970
- teamId: params.teamId,
1971
- memberId: params.memberId
1972
- },
1973
- headers: addHeaders(options)
1974
- });
1975
- });
1976
- },
1977
- generateInviteToken(params, options) {
1978
- return __async(this, null, function* () {
1979
- return sendRequest({
1980
- method: "POST" /* POST */,
1981
- url: `/member/team/generate-invite-link`,
1982
- data: {
1983
- teamId: params.teamId
1984
- },
1985
- headers: addHeaders(options)
1986
- });
1987
- });
1988
- },
1989
- /**
1990
- * Uploads a new profile image for the current member.
1991
- * Accepts a File object (from an input element) or a Blob.
1992
- *
1993
- * @param params - Image parameters
1994
- * @param params.profileImage - The image file to upload
1995
- * @returns Promise resolving to the new profile image URL
1996
- *
1997
- * @example Upload from file input
1998
- * ```typescript
1999
- * const input = document.querySelector('input[type="file"]');
2000
- * const file = input.files[0];
2001
- *
2002
- * const { data } = await memberstack.updateMemberProfileImage({
2003
- * profileImage: file
2004
- * });
2005
- * console.log('New image URL:', data.profileImage);
2006
- * ```
2007
- */
2008
- updateMemberProfileImage(params) {
2009
- return __async(this, null, function* () {
2010
- if (!params.profileImage) {
2011
- throw new Error("profileImage is required");
2012
- }
2013
- const formData = new FormData();
2014
- formData.append("profileImage", params.profileImage);
2015
- return sendRequest({
2016
- method: "POST" /* POST */,
2017
- url: `/member/profile-image`,
2018
- data: formData,
2019
- contentType: "multipart/form-data"
2020
- });
2021
- });
2022
- },
2023
- /**
2024
- * Sends a verification email to the current member.
2025
- * Use this when email verification is enabled in your Memberstack settings.
2026
- *
2027
- * @returns Promise resolving to success confirmation
2028
- *
2029
- * @example
2030
- * ```typescript
2031
- * await memberstack.sendMemberVerificationEmail();
2032
- * // Show message: "Verification email sent! Check your inbox."
2033
- * ```
2034
- */
2035
- sendMemberVerificationEmail() {
2036
- return __async(this, null, function* () {
2037
- return sendRequest({
2038
- method: "POST" /* POST */,
2039
- url: `/auth/send-email-verification`,
2040
- data: {
2041
- //internal use only
2042
- origin_domain: window.location.origin
2043
- }
2044
- });
2045
- });
2046
- },
2047
- /**
2048
- * Sends a password reset email to a member.
2049
- * The email contains a link with a token that can be used to reset their password.
2050
- *
2051
- * @param params - Email parameters
2052
- * @param params.email - The member's email address
2053
- * @returns Promise resolving to success confirmation
2054
- *
2055
- * @example
2056
- * ```typescript
2057
- * await memberstack.sendMemberResetPasswordEmail({
2058
- * email: 'user@example.com'
2059
- * });
2060
- * // Show confirmation: "Check your email for reset instructions"
2061
- * ```
2062
- */
2063
- sendMemberResetPasswordEmail(params) {
2064
- return __async(this, null, function* () {
2065
- return sendRequest({
2066
- method: "POST" /* POST */,
2067
- url: `/auth/send-reset-password-email`,
2068
- data: {
2069
- email: params.email
2070
- }
2071
- });
2072
- });
2073
- },
2074
- /**
2075
- * Completes the password reset process using the token from the reset email.
2076
- * Typically called from a password reset page that receives the token via URL parameter.
2077
- *
2078
- * @param params - Reset parameters
2079
- * @param params.token - The reset token from the email link
2080
- * @param params.newPassword - The new password to set
2081
- * @returns Promise resolving to success confirmation
2082
- * @throws When the token is invalid or expired
2083
- *
2084
- * @example
2085
- * ```typescript
2086
- * // Get token from URL: /reset-password?token=abc123
2087
- * const token = new URLSearchParams(window.location.search).get('token');
2088
- *
2089
- * await memberstack.resetMemberPassword({
2090
- * token,
2091
- * newPassword: 'newSecurePassword123'
2092
- * });
2093
- * // Password updated, redirect to login
2094
- * ```
2095
- */
2096
- resetMemberPassword(params) {
2097
- return __async(this, null, function* () {
2098
- return sendRequest({
2099
- method: "POST" /* POST */,
2100
- url: `/auth/reset-password`,
2101
- data: {
2102
- token: params.token,
2103
- newPassword: params.newPassword
2104
- }
2105
- });
2106
- });
2107
- },
2108
- /**
2109
- * Signs out the currently authenticated member.
2110
- * Clears the local session and invalidates the server-side session.
2111
- *
2112
- * @returns Promise resolving to logout confirmation (may include a redirect URL)
2113
- *
2114
- * @example
2115
- * ```typescript
2116
- * await memberstack.logout();
2117
- * // User is now logged out
2118
- * window.location.href = '/login';
2119
- * ```
2120
- *
2121
- * @example With redirect handling
2122
- * ```typescript
2123
- * const { data } = await memberstack.logout();
2124
- * if (data.redirect) {
2125
- * window.location.href = data.redirect;
2126
- * }
2127
- * ```
2128
- */
2129
- logout(options) {
2130
- return __async(this, null, function* () {
2131
- const data = yield sendRequest({
2132
- method: "POST" /* POST */,
2133
- url: `/member/logout`,
2134
- headers: addHeaders(options)
2135
- });
2136
- unsetPersistedMember();
2137
- return data;
2138
- });
2139
- },
2140
- // Data Tables Methods
2141
- /**
2142
- * Retrieves all data tables configured for your app.
2143
- * Returns the list of tables and their schemas.
2144
- *
2145
- * @returns Promise resolving to an array of data tables
2146
- *
2147
- * @example
2148
- * ```typescript
2149
- * const { data: tables } = await memberstack.getDataTables();
2150
- * tables.forEach(table => {
2151
- * console.log('Table:', table.name, table.key);
2152
- * });
2153
- * ```
2154
- */
2155
- getDataTables(options) {
2156
- return __async(this, null, function* () {
2157
- return sendRequest({
2158
- method: "GET" /* GET */,
2159
- url: `/v1/data-tables`,
2160
- headers: addHeaders(options)
2161
- });
2162
- });
2163
- },
2164
- /**
2165
- * Retrieves a specific data table's schema and configuration.
2166
- *
2167
- * @param params - Table parameters
2168
- * @param params.table - The table key/identifier
2169
- * @returns Promise resolving to the table schema
2170
- *
2171
- * @example
2172
- * ```typescript
2173
- * const { data: table } = await memberstack.getDataTable({
2174
- * table: 'posts'
2175
- * });
2176
- * console.log('Columns:', table.columns);
2177
- * ```
2178
- */
2179
- getDataTable(params, options) {
2180
- return __async(this, null, function* () {
2181
- return sendRequest({
2182
- method: "GET" /* GET */,
2183
- //@ts-ignore
2184
- url: `/v1/data-tables/${params.table || params.tableKey}`,
2185
- headers: addHeaders(options)
2186
- });
2187
- });
2188
- },
2189
- /**
2190
- * Retrieves records from a data table with optional filtering and pagination.
2191
- *
2192
- * @param params - Query parameters
2193
- * @param params.table - The table key/identifier
2194
- * @param params.limit - Maximum number of records to return
2195
- * @param params.after - Cursor for pagination (record ID to start after)
2196
- * @param params.sortBy - Field to sort by
2197
- * @param params.sortDirection - Sort direction ('asc' or 'desc')
2198
- * @param params.createdAfter - Filter records created after this date
2199
- * @param params.createdBefore - Filter records created before this date
2200
- * @returns Promise resolving to records array with pagination info
2201
- *
2202
- * @example List records with pagination
2203
- * ```typescript
2204
- * const { data } = await memberstack.getDataRecords({
2205
- * table: 'posts',
2206
- * limit: 10,
2207
- * sortBy: 'createdAt',
2208
- * sortDirection: 'desc'
2209
- * });
2210
- * console.log('Records:', data.records);
2211
- * ```
2212
- */
2213
- getDataRecords(params, options) {
2214
- return __async(this, null, function* () {
2215
- var _a2;
2216
- const query = {};
2217
- if (params.createdAfter || params.createdBefore) {
2218
- query.where = {
2219
- createdAt: __spreadValues(__spreadValues({}, params.createdAfter && { gte: params.createdAfter }), params.createdBefore && { lte: params.createdBefore })
2220
- };
2221
- }
2222
- if (params.sortBy) {
2223
- query.orderBy = {
2224
- [params.sortBy]: params.sortDirection || "asc"
2225
- };
2226
- }
2227
- if (params.limit) {
2228
- query.take = params.limit;
2229
- }
2230
- if (params.after) {
2231
- query.after = params.after;
2232
- }
2233
- const res = yield sendRequest({
2234
- method: "POST" /* POST */,
2235
- url: `/v1/data-records/query`,
2236
- data: {
2237
- // @ts-ignore
2238
- table: params.table || params.tableKey,
2239
- query: {
2240
- findMany: query
2241
- }
2242
- },
2243
- headers: addHeaders(options)
2244
- });
2245
- if ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2.records) {
2246
- return {
2247
- data: __spreadValues({
2248
- records: res.data.records
2249
- }, res.data.pagination && { pagination: res.data.pagination })
2250
- };
2251
- }
2252
- return res;
2253
- });
2254
- },
2255
- /**
2256
- * Creates a new record in a data table.
2257
- *
2258
- * @param params - Record parameters
2259
- * @param params.table - The table key/identifier
2260
- * @param params.data - The record data as key-value pairs
2261
- * @param params.memberId - Optional member ID to associate with the record
2262
- * @returns Promise resolving to the created record
2263
- *
2264
- * @example Create a new post
2265
- * ```typescript
2266
- * const { data: record } = await memberstack.createDataRecord({
2267
- * table: 'posts',
2268
- * data: {
2269
- * title: 'My First Post',
2270
- * content: 'Hello world!',
2271
- * published: true
2272
- * }
2273
- * });
2274
- * console.log('Created record:', record.id);
2275
- * ```
2276
- */
2277
- createDataRecord(params, options) {
2278
- return __async(this, null, function* () {
2279
- return sendRequest({
2280
- method: "POST" /* POST */,
2281
- url: `/v1/data-records`,
2282
- data: __spreadValues({
2283
- table: params.table,
2284
- data: params.data
2285
- }, params.memberId && { memberId: params.memberId }),
2286
- headers: addHeaders(options)
2287
- });
2288
- });
2289
- },
2290
- /**
2291
- * Retrieves a single record by ID from a data table.
2292
- *
2293
- * @param params - Record parameters
2294
- * @param params.table - The table key/identifier
2295
- * @param params.recordId - The ID of the record to retrieve
2296
- * @returns Promise resolving to the record data
2297
- *
2298
- * @example Get a specific post
2299
- * ```typescript
2300
- * const { data: record } = await memberstack.getDataRecord({
2301
- * table: 'posts',
2302
- * recordId: 'rec_abc123'
2303
- * });
2304
- * console.log('Post:', record.title);
2305
- * ```
2306
- */
2307
- getDataRecord(params, options) {
2308
- return __async(this, null, function* () {
2309
- var _a2;
2310
- const res = yield sendRequest({
2311
- method: "POST" /* POST */,
2312
- url: `/v1/data-records/query`,
2313
- data: {
2314
- table: params.table,
2315
- query: {
2316
- findUnique: {
2317
- where: { id: params.recordId }
2318
- }
2319
- }
2320
- },
2321
- headers: addHeaders(options)
2322
- });
2323
- if ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2.record) {
2324
- return { data: res.data.record };
2325
- }
2326
- return res;
2327
- });
2328
- },
2329
- /**
2330
- * Updates an existing record in a data table.
2331
- *
2332
- * @param params - Update parameters
2333
- * @param params.recordId - The ID of the record to update
2334
- * @param params.data - The fields to update as key-value pairs
2335
- * @returns Promise resolving to the updated record
2336
- *
2337
- * @example Update a post
2338
- * ```typescript
2339
- * const { data: record } = await memberstack.updateDataRecord({
2340
- * recordId: 'rec_abc123',
2341
- * data: {
2342
- * title: 'Updated Title',
2343
- * published: false
2344
- * }
2345
- * });
2346
- * ```
2347
- */
2348
- updateDataRecord(params, options) {
2349
- return __async(this, null, function* () {
2350
- return sendRequest({
2351
- method: "PUT" /* PUT */,
2352
- url: `/v1/data-records/${params.recordId}`,
2353
- data: {
2354
- data: params.data
2355
- },
2356
- headers: addHeaders(options)
2357
- });
2358
- });
2359
- },
2360
- /**
2361
- * Deletes a record from a data table.
2362
- *
2363
- * @param params - Delete parameters
2364
- * @param params.recordId - The ID of the record to delete
2365
- * @returns Promise resolving to deletion confirmation
2366
- *
2367
- * @example Delete a post
2368
- * ```typescript
2369
- * await memberstack.deleteDataRecord({
2370
- * recordId: 'rec_abc123'
2371
- * });
2372
- * ```
2373
- */
2374
- deleteDataRecord(params, options) {
2375
- return __async(this, null, function* () {
2376
- return sendRequest({
2377
- method: "DELETE" /* DELETE */,
2378
- url: `/v1/data-records/${params.recordId}`,
2379
- headers: addHeaders(options)
2380
- });
2381
- });
2382
- },
2383
- /**
2384
- * Queries records from a data table with advanced filtering.
2385
- * Provides more control than getDataRecords for complex queries.
2386
- *
2387
- * @param params - Query parameters
2388
- * @param params.table - The table key/identifier
2389
- * @param params.query - Query object with where, orderBy, take, skip options
2390
- * @returns Promise resolving to matching records
2391
- *
2392
- * @example Query with filters
2393
- * ```typescript
2394
- * const { data } = await memberstack.queryDataRecords({
2395
- * table: 'posts',
2396
- * query: {
2397
- * where: {
2398
- * published: { equals: true },
2399
- * category: { equals: 'tech' }
2400
- * },
2401
- * orderBy: { createdAt: 'desc' },
2402
- * take: 10
2403
- * }
2404
- * });
2405
- * ```
2406
- *
2407
- * @example Query with member filter
2408
- * ```typescript
2409
- * const { data } = await memberstack.queryDataRecords({
2410
- * table: 'comments',
2411
- * query: {
2412
- * where: {
2413
- * memberId: { equals: 'mem_xyz789' }
2414
- * }
2415
- * }
2416
- * });
2417
- * ```
2418
- */
2419
- queryDataRecords(params, options) {
2420
- return __async(this, null, function* () {
2421
- return sendRequest({
2422
- method: "POST" /* POST */,
2423
- url: `/v1/data-records/query`,
2424
- data: {
2425
- table: params.table,
2426
- query: {
2427
- findMany: params.query
2428
- }
2429
- },
2430
- headers: addHeaders(options)
2431
- });
2432
- });
2433
- }
2434
- };
2435
- };
2436
-
2437
- // src/utils/debug.ts
2438
- var debugEnabled = false;
2439
- function setDebugMode(enabled) {
2440
- debugEnabled = enabled;
2441
- if (enabled && typeof window !== "undefined") {
2442
- console.log(
2443
- "%c[Memberstack] Debug mode enabled",
2444
- "color: #6366f1; font-weight: bold;"
2445
- );
2446
- }
2447
- }
2448
- function debugLog(message, ...args) {
2449
- if (debugEnabled) {
2450
- console.log(
2451
- `%c[Memberstack] ${message}`,
2452
- "color: #6366f1;",
2453
- ...args
2454
- );
2455
- }
2456
- }
2457
- function initDevToolsIntegration(state) {
2458
- if (typeof window !== "undefined" && debugEnabled) {
2459
- window.__MEMBERSTACK_DEBUG__ = {
2460
- version: state.version,
2461
- config: {
2462
- publicKey: state.config.publicKey,
2463
- appId: state.config.appId
2464
- },
2465
- getMember: () => state.member,
2466
- isAuthenticated: () => state.member !== null,
2467
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
2468
- };
2469
- debugLog("DevTools integration initialized. Access via window.__MEMBERSTACK_DEBUG__");
2470
- }
2471
- }
2472
-
2473
- // src/methods/index.ts
2474
- var SDK_VERSION = "1.2.0";
2475
- var captchaReadyPromise = new Promise((resolve) => {
2476
- if (typeof window !== "undefined") {
2477
- window._hcaptchaReady = resolve;
2478
- }
2479
- });
2480
- var methods = {
2481
- openModal,
2482
- hideModal,
2483
- preloadModals,
2484
- _hideLoader: hideLoader,
2485
- _showLoader: showLoader,
2486
- _showMessage: showMessage,
2487
- getMemberCookie: getMemberToken,
2488
- onAuthChange,
2489
- _captchaReady: captchaReadyPromise
2490
- };
2491
- function init(props) {
2492
- if (props.debug) {
2493
- setDebugMode(true);
2494
- debugLog(`Initializing Memberstack SDK v${SDK_VERSION}`);
2495
- debugLog("Config:", {
2496
- publicKey: props.publicKey ? `${props.publicKey.slice(0, 10)}...` : void 0,
2497
- appId: props.appId,
2498
- useCookies: props.useCookies,
2499
- domain: props.domain
2500
- });
2501
- }
2502
- const apiDomain2 = props.domain || endpoints.API || "https://client.memberstack.com";
2503
- setApiDomain(apiDomain2);
2504
- if (props.useCookies)
2505
- setUseCookies(props.setCookieOnRootDomain);
2506
- setMemberTokenIfAvailable();
2507
- const requests = initRequest({
2508
- publicKey: props.publicKey,
2509
- appId: props.appId,
2510
- token: getMemberToken(),
2511
- domain: apiDomain2
2512
- });
2513
- const allMethods = Object.assign(methods, requests);
2514
- if (typeof window !== "undefined") {
2515
- window.$memberstackDom = allMethods;
2516
- if (props.debug) {
2517
- initDevToolsIntegration({
2518
- config: { publicKey: props.publicKey, appId: props.appId },
2519
- member: null,
2520
- // Will be updated by auth state
2521
- version: SDK_VERSION
2522
- });
2523
- }
2524
- }
2525
- if (props.debug) {
2526
- debugLog("SDK initialized successfully");
2527
- }
2528
- return allMethods;
2529
- }
2530
- var methods_default = { init: (props) => init(props) };