abmp-npm 10.3.7 → 10.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,13 @@
1
1
  const { auth } = require('@wix/essentials');
2
2
  const { members, authentication } = require('@wix/members');
3
+
4
+ const { LOGIN_EMAIL_SYNC_STATUS } = require('./consts');
5
+
3
6
  const elevatedCreateMember = auth.elevate(members.createMember);
4
7
  const elevatedChangeLoginEmail = auth.elevate(authentication.changeLoginEmail);
5
8
 
9
+ const LOG = '[loginEmailSync]';
10
+
6
11
  function prepareMemberData(partner) {
7
12
  const options = {
8
13
  member: {
@@ -37,48 +42,42 @@ const getCurrentMember = async () => {
37
42
  };
38
43
 
39
44
  /**
40
- * Updates Wix member login email if the member has a wixMemberId (registered Wix member)
41
- * @param {Object} member - Member object with wixMemberId and email
42
- * @param {Object} result - Result object to track Wix member updates
45
+ * Attempts to change a Wix member's login email to `member.email` and reports a structured
46
+ * outcome instead of swallowing failures. Never throws.
47
+ *
48
+ * Outcomes:
49
+ * - SKIPPED: member has no wixMemberId, nothing to change.
50
+ * - UPDATED: Wix login email changed successfully.
51
+ * - FAILED: change failed. The caller keeps the CMS login email unchanged (so it stays
52
+ * consistent with Wix) and reports the member in the task result for manual handling.
53
+ *
54
+ * @param {Object} member - Member with { memberId, wixMemberId, email }
55
+ * @returns {Promise<Object>} outcome
43
56
  */
44
- async function updateWixMemberLoginEmail(member, result = {}) {
57
+ async function updateWixMemberLoginEmail(member) {
58
+ const desiredEmail = member.email;
59
+ const base = { memberId: member.memberId, wixMemberId: member.wixMemberId, desiredEmail };
60
+
45
61
  if (!member.wixMemberId) {
46
- console.log(`Member ${member.memberId} has no wixMemberId - skipping Wix login email update`);
47
- return;
62
+ console.log(`${LOG} member ${member.memberId} has no wixMemberId - skipping`);
63
+ return { ...base, status: LOGIN_EMAIL_SYNC_STATUS.SKIPPED };
48
64
  }
49
65
 
50
- try {
51
- console.log(
52
- `Updating Wix login email for member ${member.memberId} (wixMemberId: ${member.wixMemberId})`
53
- );
54
-
55
- const updatedWixMember = await elevatedChangeLoginEmail(member.wixMemberId, member.email);
66
+ console.log(
67
+ `${LOG} attempting login-email change for member ${member.memberId} (wixMemberId: ${member.wixMemberId}) -> ${desiredEmail}`
68
+ );
56
69
 
70
+ try {
71
+ const updatedWixMember = await elevatedChangeLoginEmail(member.wixMemberId, desiredEmail);
57
72
  console.log(
58
- `✅ Successfully updated Wix login email for member ${member.memberId}: ${updatedWixMember.loginEmail}`
73
+ `${LOG} updated member ${member.memberId} (wixMemberId: ${member.wixMemberId}) -> ${updatedWixMember.loginEmail}`
59
74
  );
60
-
61
- if (!result.wixMemberUpdates) {
62
- result.wixMemberUpdates = { successful: 0, failed: 0 };
63
- }
64
- result.wixMemberUpdates.successful++;
75
+ return { ...base, status: LOGIN_EMAIL_SYNC_STATUS.UPDATED };
65
76
  } catch (error) {
66
- console.error(`❌ Failed to update Wix login email for member ${member.memberId}:`, error);
67
-
68
- if (!result.wixMemberUpdates) {
69
- result.wixMemberUpdates = { successful: 0, failed: 0 };
70
- }
71
- result.wixMemberUpdates.failed++;
72
-
73
- if (!result.wixMemberErrors) {
74
- result.wixMemberErrors = [];
75
- }
76
- result.wixMemberErrors.push({
77
- memberId: member.memberId,
78
- wixMemberId: member.wixMemberId,
79
- email: member.email,
80
- error: error.message,
81
- });
77
+ console.error(
78
+ `${LOG} ❌ login-email change failed for member ${member.memberId} (wixMemberId: ${member.wixMemberId}) -> ${desiredEmail}: ${error.message}`
79
+ );
80
+ return { ...base, status: LOGIN_EMAIL_SYNC_STATUS.FAILED, error: error.message };
82
81
  }
83
82
  }
84
83
 
@@ -1,5 +1,5 @@
1
1
  const { COLLECTIONS } = require('../public/consts');
2
- const { isWixHostedImage } = require('../public/Utils/sharedUtils');
2
+ const { isWixHostedImage, emailsMatch, normalizeEmail } = require('../public/Utils/sharedUtils');
3
3
 
4
4
  const { MEMBERSHIPS_TYPES } = require('./consts');
5
5
  const { createSiteContact } = require('./contacts-methods');
@@ -15,6 +15,7 @@ const {
15
15
  generateGeoHash,
16
16
  searchAllItems,
17
17
  runIf,
18
+ withTransientErrorRetry,
18
19
  } = require('./utils');
19
20
 
20
21
  /**
@@ -35,7 +36,42 @@ async function findMemberByWixDataId(memberId) {
35
36
  }
36
37
 
37
38
  const hasDifferentEmails = memberData =>
38
- memberData.contactFormEmail && memberData.contactFormEmail !== memberData.email;
39
+ Boolean(memberData.contactFormEmail) &&
40
+ !emailsMatch(memberData.contactFormEmail, memberData.email);
41
+
42
+ /**
43
+ * Returns a shallow copy of a member record with its email fields normalized
44
+ * (lowercased + trimmed). Wix CRM and our uniqueness checks treat emails
45
+ * case-insensitively, so we persist them in canonical form to keep `.eq` lookups
46
+ * reliable. Only rewrites string values that are actually present.
47
+ * @param {Object} memberData
48
+ * @returns {Object}
49
+ */
50
+ const normalizeMemberEmailFields = memberData => {
51
+ if (!memberData || typeof memberData !== 'object') return memberData;
52
+ const normalized = { ...memberData };
53
+ if (typeof normalized.email === 'string') {
54
+ normalized.email = normalizeEmail(normalized.email);
55
+ }
56
+ if (typeof normalized.contactFormEmail === 'string') {
57
+ normalized.contactFormEmail = normalizeEmail(normalized.contactFormEmail);
58
+ }
59
+ return normalized;
60
+ };
61
+
62
+ /**
63
+ * Whether a member's stored email fields are not already in canonical form
64
+ * (lowercased + trimmed) and therefore need the normalization backfill.
65
+ * @param {Object} member
66
+ * @returns {boolean}
67
+ */
68
+ const memberNeedsEmailNormalization = member =>
69
+ (typeof member.email === 'string' &&
70
+ member.email.length > 0 &&
71
+ member.email !== normalizeEmail(member.email)) ||
72
+ (typeof member.contactFormEmail === 'string' &&
73
+ member.contactFormEmail.length > 0 &&
74
+ member.contactFormEmail !== normalizeEmail(member.contactFormEmail));
39
75
 
40
76
  async function createContactAndMemberIfNew(memberData) {
41
77
  if (!memberData) {
@@ -97,8 +133,14 @@ async function bulkSaveMembers(memberDataList, collectionName = COLLECTIONS.MEMB
97
133
  }
98
134
 
99
135
  try {
136
+ // Normalize email fields only for the members collection; other collections passed here
137
+ // (e.g. staging copies) don't have these fields and must be saved untouched.
138
+ const listToSave =
139
+ collectionName === COLLECTIONS.MEMBERS_DATA
140
+ ? memberDataList.map(normalizeMemberEmailFields)
141
+ : memberDataList;
100
142
  // bulkSave all with batches of 1000 items as this is the Velo limit for bulkSave
101
- const batches = chunkArray(memberDataList, 1000);
143
+ const batches = chunkArray(listToSave, 1000);
102
144
  return await Promise.all(batches.map(batch => wixData.bulkSave(collectionName, batch)));
103
145
  } catch (error) {
104
146
  console.error('Error bulk saving members:', error);
@@ -117,11 +159,9 @@ async function findMemberById(memberId) {
117
159
  }
118
160
 
119
161
  try {
120
- const queryResult = await wixData
121
- .query(COLLECTIONS.MEMBERS_DATA)
122
- .eq('memberId', memberId)
123
- .limit(2)
124
- .find();
162
+ const queryResult = await withTransientErrorRetry(() =>
163
+ wixData.query(COLLECTIONS.MEMBERS_DATA).eq('memberId', memberId).limit(2).find()
164
+ );
125
165
  if (queryResult.items.length > 1) {
126
166
  throw new Error(
127
167
  `Multiple members found with memberId ${memberId} members _ids are : [${queryResult.items.map(member => member._id).join(', ')}]`
@@ -134,6 +174,51 @@ async function findMemberById(memberId) {
134
174
  }
135
175
  }
136
176
 
177
+ /**
178
+ * Retrieves existing members for a list of member IDs in bulk.
179
+ * Uses chunked `hasSome` queries so a full page of members costs a handful of
180
+ * requests instead of one query per member (the per-member fan-out made a whole
181
+ * page fail whenever a single query hit a transient "fetch failed").
182
+ * @param {Array<string|number>} memberIds - Member IDs to look up
183
+ * @returns {Promise<Map<string, Object>>} - Map of String(memberId) to member record (missing IDs are absent)
184
+ */
185
+ async function findMembersByIds(memberIds) {
186
+ const uniqueIds = [...new Set((memberIds || []).filter(id => id !== undefined && id !== null))];
187
+ const membersById = new Map();
188
+ if (uniqueIds.length === 0) {
189
+ return membersById;
190
+ }
191
+
192
+ try {
193
+ const idChunks = chunkArray(uniqueIds, 100);
194
+ const chunkResults = await Promise.all(
195
+ idChunks.map(idsChunk =>
196
+ withTransientErrorRetry(() =>
197
+ queryAllItems(
198
+ wixData.query(COLLECTIONS.MEMBERS_DATA).hasSome('memberId', idsChunk).limit(1000)
199
+ )
200
+ )
201
+ )
202
+ );
203
+
204
+ const duplicateIds = new Set();
205
+ chunkResults.flat().forEach(member => {
206
+ const key = String(member.memberId);
207
+ if (membersById.has(key)) {
208
+ duplicateIds.add(key);
209
+ }
210
+ membersById.set(key, member);
211
+ });
212
+ if (duplicateIds.size > 0) {
213
+ throw new Error(`Multiple members found with memberId(s): [${[...duplicateIds].join(', ')}]`);
214
+ }
215
+ return membersById;
216
+ } catch (error) {
217
+ console.error('Error finding members by IDs:', error);
218
+ throw new Error(`Failed to retrieve member data: ${error.message}`);
219
+ }
220
+ }
221
+
137
222
  /**
138
223
  * Method to get member by slug with flexible filtering options
139
224
  * @param {Object} options - Query options
@@ -244,24 +329,48 @@ const getAllEmptyAboutYouMembers = async () => {
244
329
  */
245
330
  async function updateMember(memberToUpdate) {
246
331
  try {
247
- const updatedMember = await wixData.update(COLLECTIONS.MEMBERS_DATA, memberToUpdate);
332
+ const updatedMember = await wixData.update(
333
+ COLLECTIONS.MEMBERS_DATA,
334
+ normalizeMemberEmailFields(memberToUpdate)
335
+ );
248
336
  return updatedMember;
249
337
  } catch (error) {
250
338
  throw new Error(`Failed to update member data: ${error.message}`);
251
339
  }
252
340
  }
341
+ /**
342
+ * Whether the given email is already used by a DIFFERENT member (case-insensitive).
343
+ * Returns false when the email is free or belongs to the same member, so a member can
344
+ * always keep/normalize their own email.
345
+ * @param {string} email
346
+ * @param {string|number} memberId - The member requesting the change
347
+ * @returns {Promise<boolean>}
348
+ */
253
349
  async function isEmailAlreadyUsed(email, memberId) {
254
350
  const member = await getMemberByContactEmail(email);
255
- return member !== null && member.memberId !== memberId;
351
+ return member !== null && String(member.memberId) !== String(memberId);
256
352
  }
353
+ /**
354
+ * Finds the member that owns an email (in either the login or contact-form field),
355
+ * matching case-insensitively. Emails are normalized (lowercased + trimmed) on write and
356
+ * backfilled by the email-normalization migration, so stored values are canonical: a single
357
+ * `.eq` against the normalized email is an exact, case-insensitive lookup.
358
+ * Throws if two DIFFERENT members share the email (a data-integrity violation).
359
+ * @param {string} email
360
+ * @returns {Promise<Object|null>}
361
+ */
257
362
  async function getMemberByContactEmail(email) {
363
+ const normalized = normalizeEmail(email);
364
+ if (!normalized) return null;
365
+
258
366
  const members = await wixData
259
367
  .query(COLLECTIONS.MEMBERS_DATA)
260
- .eq('contactFormEmail', email)
261
- .or(wixData.query(COLLECTIONS.MEMBERS_DATA).eq('email', email))
368
+ .eq('contactFormEmail', normalized)
369
+ .or(wixData.query(COLLECTIONS.MEMBERS_DATA).eq('email', normalized))
262
370
  .limit(2)
263
371
  .find()
264
372
  .then(res => res.items);
373
+
265
374
  if (members.length > 1) {
266
375
  throw new Error(
267
376
  `[getMemberByContactEmail] Multiple members found with same loginemail or contactFormEmail ${email} membersIds are : [${members.map(member => member.memberId).join(', ')}]`
@@ -451,6 +560,29 @@ const getAllMembersWithoutContactFormEmail = async () => {
451
560
  }
452
561
  };
453
562
 
563
+ /**
564
+ * Gets all members whose email or contactFormEmail is stored with non-canonical casing
565
+ * (or surrounding whitespace) and therefore needs the normalization backfill.
566
+ * Wix Data cannot compare a field to its own lowercase form, so we fetch members that have
567
+ * an email set and filter in memory.
568
+ * @returns {Promise<Array>} - Array of member data
569
+ */
570
+ const getAllMembersNeedingEmailNormalization = async () => {
571
+ try {
572
+ const membersQuery = wixData
573
+ .query(COLLECTIONS.MEMBERS_DATA)
574
+ .isNotEmpty('email')
575
+ .or(wixData.query(COLLECTIONS.MEMBERS_DATA).isNotEmpty('contactFormEmail'))
576
+ .limit(1000);
577
+
578
+ const allItems = await queryAllItems(membersQuery);
579
+ return allItems.filter(memberNeedsEmailNormalization);
580
+ } catch (error) {
581
+ console.error('Error getting members needing email normalization:', error);
582
+ throw new Error(`Failed to get members needing email normalization: ${error.message}`);
583
+ }
584
+ };
585
+
454
586
  /* Gets all updated login emails from the updated emails database
455
587
  * @returns {Promise<Array>} - Array of updated email data
456
588
  */
@@ -488,9 +620,13 @@ const getMembersByIds = async memberIds => {
488
620
 
489
621
  const getMemberByEmail = async email => {
490
622
  try {
623
+ // Login emails are normalized on write, so match against the normalized value (see
624
+ // getMemberByContactEmail) — an exact `.eq` is a case-insensitive lookup.
625
+ const normalized = normalizeEmail(email);
626
+ if (!normalized) return null;
491
627
  const members = await wixData
492
628
  .query(COLLECTIONS.MEMBERS_DATA)
493
- .eq('email', email)
629
+ .eq('email', normalized)
494
630
  .limit(2)
495
631
  .find()
496
632
  .then(res => res.items);
@@ -631,6 +767,7 @@ module.exports = {
631
767
  saveRegistrationData,
632
768
  bulkSaveMembers,
633
769
  findMemberById,
770
+ findMembersByIds,
634
771
  getMemberBySlug,
635
772
  getCMSMemberByWixMemberId,
636
773
  getAllEmptyAboutYouMembers,
@@ -638,6 +775,8 @@ module.exports = {
638
775
  getAllMembersWithExternalImages,
639
776
  getMembersWithWixUrl,
640
777
  getAllMembersWithoutContactFormEmail,
778
+ getAllMembersNeedingEmailNormalization,
779
+ memberNeedsEmailNormalization,
641
780
  getAllUpdatedLoginEmails,
642
781
  getMembersByIds,
643
782
  getMemberByEmail,
@@ -1,3 +1,5 @@
1
+ const axios = require('axios');
2
+
1
3
  const { PAC_API_URL, TEST_PAC_API_URL, BACKUP_API_URL } = require('./consts');
2
4
  const { getSecret } = require('./utils');
3
5
 
@@ -31,24 +33,22 @@ const fetchPACMembers = async ({ page, action, backupDate, isTestEnvironment })
31
33
  const url = `${baseUrl}/Members?${new URLSearchParams(queryParams).toString()}`;
32
34
  console.log(`Fetching PAC members from: ${url}`);
33
35
  const headers = await getHeaders();
34
- const fetchOptions = {
35
- method: 'get',
36
- headers: headers,
37
- };
38
- const response = await fetch(url, fetchOptions);
39
- const responseType = response.headers.get('content-type');
36
+ const response = await axios.get(url, {
37
+ headers,
38
+ validateStatus: () => true,
39
+ });
40
+ const responseType = response.headers['content-type'] || '';
40
41
  if (!responseType.includes('application/json')) {
41
42
  const errorMessage = `[fetchPACMembers] got invalid responseType: ${responseType} for page ${page} and actionFilter ${action}`;
42
43
  console.error(errorMessage);
43
44
  throw new Error(errorMessage);
44
45
  }
45
- if (response.ok) {
46
- return response.json();
47
- } else {
48
- const errorMessage = `[fetchPACMembers] failed with status ${response.status} for page ${page} and actionFilter ${action}`;
49
- console.error(errorMessage);
50
- throw new Error(errorMessage);
46
+ if (response.status >= 200 && response.status < 300) {
47
+ return response.data;
51
48
  }
49
+ const errorMessage = `[fetchPACMembers] failed with status ${response.status} for page ${page} and actionFilter ${action}`;
50
+ console.error(errorMessage);
51
+ throw new Error(errorMessage);
52
52
  };
53
53
 
54
54
  module.exports = { fetchPACMembers, getHeaders }; //TODO: remove getHeaders from exported methods once npm movement finishes
@@ -22,6 +22,8 @@ const TASKS_NAMES = {
22
22
  fixPrimaryAddressChunk: 'fixPrimaryAddressChunk',
23
23
  scheduleFixUrlsWithSpaces: 'scheduleFixUrlsWithSpaces',
24
24
  fixUrlsWithSpacesChunk: 'fixUrlsWithSpacesChunk',
25
+ scheduleNormalizeMemberEmails: 'scheduleNormalizeMemberEmails',
26
+ normalizeMemberEmailsChunk: 'normalizeMemberEmailsChunk',
25
27
  dailyPullExecutionCheck: 'dailyPullExecutionCheck',
26
28
  };
27
29
 
@@ -0,0 +1,134 @@
1
+ const { taskManager } = require('psdev-task-manager');
2
+
3
+ const {
4
+ bulkSaveMembers,
5
+ getMembersByIds,
6
+ getAllMembersNeedingEmailNormalization,
7
+ memberNeedsEmailNormalization,
8
+ } = require('../members-data-methods');
9
+ const { chunkArray } = require('../utils');
10
+
11
+ const { TASKS_NAMES } = require('./consts');
12
+
13
+ const CHUNK_SIZE = 1000;
14
+
15
+ /**
16
+ * One-off backfill: schedules tasks to normalize (lowercase + trim) the email and
17
+ * contactFormEmail fields of existing members so stored values match the normalize-on-write
18
+ * behavior, keeping case-insensitive uniqueness lookups reliable.
19
+ */
20
+ async function scheduleNormalizeMemberEmails() {
21
+ console.log('=== Scheduling Member Email Normalization ===');
22
+
23
+ try {
24
+ const members = await getAllMembersNeedingEmailNormalization();
25
+ console.log(`Fetched ${members.length} members needing email normalization`);
26
+
27
+ const memberIds = [
28
+ ...new Set(
29
+ members
30
+ .map(member => Number(member.memberId))
31
+ .filter(memberId => Number.isFinite(memberId) && memberId > 0)
32
+ ),
33
+ ];
34
+ console.log(`Members to normalize: ${memberIds.length}`);
35
+
36
+ if (memberIds.length === 0) {
37
+ console.log('No members need email normalization');
38
+ return {
39
+ success: true,
40
+ message: 'No members need email normalization',
41
+ totalMembers: 0,
42
+ tasksScheduled: 0,
43
+ };
44
+ }
45
+
46
+ const chunks = chunkArray(memberIds, CHUNK_SIZE);
47
+ for (let i = 0; i < chunks.length; i++) {
48
+ const chunk = chunks[i];
49
+ const task = {
50
+ name: TASKS_NAMES.normalizeMemberEmailsChunk,
51
+ data: {
52
+ memberIds: chunk,
53
+ chunkIndex: i,
54
+ totalChunks: chunks.length,
55
+ },
56
+ type: 'scheduled',
57
+ };
58
+ await taskManager().schedule(task);
59
+ console.log(`Scheduled task ${i + 1}/${chunks.length} (${chunk.length} members)`);
60
+ }
61
+
62
+ const result = {
63
+ success: true,
64
+ message: `Scheduled ${chunks.length} tasks for ${memberIds.length} members`,
65
+ totalMembers: memberIds.length,
66
+ tasksScheduled: chunks.length,
67
+ };
68
+
69
+ console.log('=== Scheduling Complete ===');
70
+ console.log(JSON.stringify(result, null, 2));
71
+
72
+ return result;
73
+ } catch (error) {
74
+ console.error('Error scheduling member email normalization:', error);
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Processes a chunk of members, normalizing their email fields.
81
+ * bulkSaveMembers normalizes on write, so we only need to select the members that still
82
+ * have non-canonical values and save them.
83
+ */
84
+ async function normalizeMemberEmailsChunk(data) {
85
+ const { memberIds, chunkIndex, totalChunks } = data;
86
+ console.log(
87
+ `Processing email normalization chunk ${chunkIndex + 1}/${totalChunks} (${memberIds.length} members)`
88
+ );
89
+
90
+ const result = {
91
+ successful: 0,
92
+ failed: 0,
93
+ skipped: 0,
94
+ errors: [],
95
+ failedIds: [],
96
+ };
97
+
98
+ try {
99
+ const members = await getMembersByIds(memberIds);
100
+ console.log(`Loaded ${members.length} members for this chunk`);
101
+
102
+ const membersToUpdate = members.filter(memberNeedsEmailNormalization);
103
+ result.skipped = members.length - membersToUpdate.length;
104
+
105
+ if (membersToUpdate.length === 0) {
106
+ console.log('No members need updating in this batch');
107
+ return result;
108
+ }
109
+
110
+ try {
111
+ await bulkSaveMembers(membersToUpdate);
112
+ result.successful += membersToUpdate.length;
113
+ console.log(`✅ Successfully normalized ${membersToUpdate.length} members`);
114
+ } catch (error) {
115
+ console.error('❌ Error bulk saving members:', error);
116
+ result.failed += membersToUpdate.length;
117
+ result.failedIds.push(...membersToUpdate.map(member => member.memberId));
118
+ result.errors.push({
119
+ error: error.message,
120
+ memberCount: membersToUpdate.length,
121
+ });
122
+ }
123
+
124
+ return result;
125
+ } catch (error) {
126
+ console.error(`Error processing email normalization chunk ${chunkIndex}:`, error);
127
+ throw error;
128
+ }
129
+ }
130
+
131
+ module.exports = {
132
+ scheduleNormalizeMemberEmails,
133
+ normalizeMemberEmailsChunk,
134
+ };
@@ -10,6 +10,10 @@ const {
10
10
  } = require('./address-primary-methods');
11
11
  const { TASKS_NAMES } = require('./consts');
12
12
  const { dailyPullExecutionCheck } = require('./daily-pull-check-methods');
13
+ const {
14
+ scheduleNormalizeMemberEmails,
15
+ normalizeMemberEmailsChunk,
16
+ } = require('./email-normalize-methods');
13
17
  const {
14
18
  scheduleTaskForEmptyAboutYouMembers,
15
19
  convertAboutYouHtmlToRichContent,
@@ -203,6 +207,20 @@ const TASKS = {
203
207
  shouldSkipCheck: () => false,
204
208
  estimatedDurationSec: 80,
205
209
  },
210
+ [TASKS_NAMES.scheduleNormalizeMemberEmails]: {
211
+ name: TASKS_NAMES.scheduleNormalizeMemberEmails,
212
+ getIdentifier: () => 'SHOULD_NEVER_SKIP',
213
+ process: scheduleNormalizeMemberEmails,
214
+ shouldSkipCheck: () => false,
215
+ estimatedDurationSec: 80,
216
+ },
217
+ [TASKS_NAMES.normalizeMemberEmailsChunk]: {
218
+ name: TASKS_NAMES.normalizeMemberEmailsChunk,
219
+ getIdentifier: task => task.data,
220
+ process: normalizeMemberEmailsChunk,
221
+ shouldSkipCheck: () => false,
222
+ estimatedDurationSec: 80,
223
+ },
206
224
  [TASKS_NAMES.dailyPullExecutionCheck]: {
207
225
  name: TASKS_NAMES.dailyPullExecutionCheck,
208
226
  getIdentifier: task => task.data,
@@ -103,23 +103,23 @@ async function updateMemberRichContent(memberId) {
103
103
  content: htmlString,
104
104
  });
105
105
 
106
- const requestOptions = {
107
- method: 'post',
108
- headers: {
109
- 'Content-Type': 'application/json',
110
- Cookie: 'XSRF-TOKEN=1753949844|p--a7HsuVjR4',
111
- Authorization: 'Bearer ' + (await getServerlessAuth()),
112
- },
113
- body: raw,
106
+ const requestHeaders = {
107
+ 'Content-Type': 'application/json',
108
+ Cookie: 'XSRF-TOKEN=1753949844|p--a7HsuVjR4',
109
+ Authorization: 'Bearer ' + (await getServerlessAuth()),
114
110
  };
115
111
 
116
112
  try {
117
- const response = await fetch(
113
+ const response = await axios.post(
118
114
  'https://www.wixapis.com/data-sync/v1/abmp-content-converter',
119
- requestOptions
115
+ raw,
116
+ {
117
+ headers: requestHeaders,
118
+ validateStatus: () => true,
119
+ }
120
120
  );
121
- if (response.ok) {
122
- const data = await response.json();
121
+ if (response.status >= 200 && response.status < 300) {
122
+ const data = response.data;
123
123
  const updatedMember = {
124
124
  ...member,
125
125
  aboutYourSelf: data.richContent.richContent,
@@ -358,9 +358,13 @@ async function uploadMembersSitemap({ members, tokens, destinationFileName, site
358
358
 
359
359
  const url = `https://${host}${pathName}`;
360
360
  console.log('url', url);
361
- const res = await fetch(url, { method, headers: reqOpts.headers, body });
362
- if (!res.ok) {
363
- const respText = await res.text();
361
+ const res = await axios.put(url, body, {
362
+ headers: reqOpts.headers,
363
+ transformResponse: [d => d],
364
+ validateStatus: () => true,
365
+ });
366
+ if (res.status < 200 || res.status >= 300) {
367
+ const respText = res.data;
364
368
  console.log('Response body', respText);
365
369
  throw new Error(`S3 PUT failed ${res.status} ${res.statusText}: ${respText}`);
366
370
  }
@@ -391,13 +395,13 @@ async function stsPost(body, baseAccessKeyId, baseSecretAccessKey) {
391
395
  accessKeyId: baseAccessKeyId,
392
396
  secretAccessKey: baseSecretAccessKey,
393
397
  });
394
- const res = await fetch(`https://${host}${path}`, {
395
- method,
398
+ const res = await axios.post(`https://${host}${path}`, body, {
396
399
  headers: reqOpts.headers,
397
- body,
400
+ transformResponse: [d => d],
401
+ validateStatus: () => true,
398
402
  });
399
- const text = await res.text();
400
- if (!res.ok) throw new Error(`STS ${res.status}: ${text}`);
403
+ const text = res.data;
404
+ if (res.status < 200 || res.status >= 300) throw new Error(`STS ${res.status}: ${text}`);
401
405
 
402
406
  const accessKeyId = parseXmlVal(text, 'AccessKeyId');
403
407
  const secretAccessKey = parseXmlVal(text, 'SecretAccessKey');