abmp-npm 2.0.72 → 2.0.74

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 (86) hide show
  1. package/.claude/worktrees/fix-save-button-disable/.husky/pre-commit +19 -0
  2. package/.claude/worktrees/fix-save-button-disable/.prettierignore +7 -0
  3. package/.claude/worktrees/fix-save-button-disable/.prettierrc.json +16 -0
  4. package/.claude/worktrees/fix-save-button-disable/README.md +1 -0
  5. package/.claude/worktrees/fix-save-button-disable/backend/README-member-contact-flows.md +136 -0
  6. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/daily-pull-execution-check.test.js +124 -0
  7. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/ensure-unique-urls-in-batch.test.js +129 -0
  8. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/login-email-sync.test.js +49 -0
  9. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/transient-retry-and-bulk-lookup.test.js +129 -0
  10. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/url-uniqueness.test.js +194 -0
  11. package/.claude/worktrees/fix-save-button-disable/backend/automations-methods.js +13 -0
  12. package/.claude/worktrees/fix-save-button-disable/backend/cms-data-methods.js +251 -0
  13. package/.claude/worktrees/fix-save-button-disable/backend/consts.js +58 -0
  14. package/.claude/worktrees/fix-save-button-disable/backend/contacts-methods.js +67 -0
  15. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/bulk-process-methods.js +222 -0
  16. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/consts.js +39 -0
  17. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/index.js +5 -0
  18. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/process-member-methods.js +213 -0
  19. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/schedule-methods.js +41 -0
  20. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/sync-to-cms-methods.js +161 -0
  21. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/utils.js +151 -0
  22. package/.claude/worktrees/fix-save-button-disable/backend/data-hooks.js +29 -0
  23. package/.claude/worktrees/fix-save-button-disable/backend/dev-only-methods.js +58 -0
  24. package/.claude/worktrees/fix-save-button-disable/backend/elevated-modules.js +18 -0
  25. package/.claude/worktrees/fix-save-button-disable/backend/forms-methods.js +52 -0
  26. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/httpFunctions.js +86 -0
  27. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/index.js +3 -0
  28. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/interests.js +35 -0
  29. package/.claude/worktrees/fix-save-button-disable/backend/index.js +19 -0
  30. package/.claude/worktrees/fix-save-button-disable/backend/jobs.js +158 -0
  31. package/.claude/worktrees/fix-save-button-disable/backend/login/generate-member-session-token.js +27 -0
  32. package/.claude/worktrees/fix-save-button-disable/backend/login/index.js +8 -0
  33. package/.claude/worktrees/fix-save-button-disable/backend/login/qa-login-methods.js +54 -0
  34. package/.claude/worktrees/fix-save-button-disable/backend/login/sso-methods.js +159 -0
  35. package/.claude/worktrees/fix-save-button-disable/backend/member-contact-orchestration.js +111 -0
  36. package/.claude/worktrees/fix-save-button-disable/backend/members-area-methods.js +88 -0
  37. package/.claude/worktrees/fix-save-button-disable/backend/members-data-methods.js +789 -0
  38. package/.claude/worktrees/fix-save-button-disable/backend/pac-api-methods.js +54 -0
  39. package/.claude/worktrees/fix-save-button-disable/backend/routers/index.js +3 -0
  40. package/.claude/worktrees/fix-save-button-disable/backend/routers/methods.js +191 -0
  41. package/.claude/worktrees/fix-save-button-disable/backend/routers/utils.js +128 -0
  42. package/.claude/worktrees/fix-save-button-disable/backend/search-filters-methods.js +124 -0
  43. package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-primary-methods.js +256 -0
  44. package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-visibility-methods.js +160 -0
  45. package/.claude/worktrees/fix-save-button-disable/backend/tasks/consts.js +34 -0
  46. package/.claude/worktrees/fix-save-button-disable/backend/tasks/daily-pull-check-methods.js +78 -0
  47. package/.claude/worktrees/fix-save-button-disable/backend/tasks/email-normalize-methods.js +134 -0
  48. package/.claude/worktrees/fix-save-button-disable/backend/tasks/index.js +10 -0
  49. package/.claude/worktrees/fix-save-button-disable/backend/tasks/migration-methods.js +46 -0
  50. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-configs.js +251 -0
  51. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-helpers-methods.js +433 -0
  52. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-process-methods.js +606 -0
  53. package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-migration-methods.js +378 -0
  54. package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-space-fix-methods.js +174 -0
  55. package/.claude/worktrees/fix-save-button-disable/backend/utils.js +277 -0
  56. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/extract-duplicate-url-groups.js +201 -0
  57. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-ids.js +159 -0
  58. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-urls.js +201 -0
  59. package/.claude/worktrees/fix-save-button-disable/eslint.config.js +120 -0
  60. package/.claude/worktrees/fix-save-button-disable/index.js +5 -0
  61. package/.claude/worktrees/fix-save-button-disable/package-lock.json +12160 -0
  62. package/.claude/worktrees/fix-save-button-disable/package.json +60 -0
  63. package/.claude/worktrees/fix-save-button-disable/pages/ContactUs.js +129 -0
  64. package/.claude/worktrees/fix-save-button-disable/pages/Home.js +779 -0
  65. package/.claude/worktrees/fix-save-button-disable/pages/LearnMore.js +27 -0
  66. package/.claude/worktrees/fix-save-button-disable/pages/LoadingPage.js +29 -0
  67. package/.claude/worktrees/fix-save-button-disable/pages/Profile.js +354 -0
  68. package/.claude/worktrees/fix-save-button-disable/pages/QAPage.js +39 -0
  69. package/.claude/worktrees/fix-save-button-disable/pages/SaveAlerts.js +13 -0
  70. package/.claude/worktrees/fix-save-button-disable/pages/SelectBannerImages.js +46 -0
  71. package/.claude/worktrees/fix-save-button-disable/pages/deleteConfirm.js +19 -0
  72. package/.claude/worktrees/fix-save-button-disable/pages/index.js +12 -0
  73. package/.claude/worktrees/fix-save-button-disable/pages/personalDetails.js +2486 -0
  74. package/.claude/worktrees/fix-save-button-disable/public/Utils/homePage.js +798 -0
  75. package/.claude/worktrees/fix-save-button-disable/public/Utils/personalDetailsUtils.js +25 -0
  76. package/.claude/worktrees/fix-save-button-disable/public/Utils/sharedUtils.js +235 -0
  77. package/.claude/worktrees/fix-save-button-disable/public/consts.js +113 -0
  78. package/.claude/worktrees/fix-save-button-disable/public/index.js +5 -0
  79. package/.claude/worktrees/fix-save-button-disable/public/messages.js +16 -0
  80. package/.claude/worktrees/fix-save-button-disable/public/sso-auth-methods.js +43 -0
  81. package/backend/jobs.js +19 -0
  82. package/backend/tasks/address-visibility-methods.js +160 -0
  83. package/backend/tasks/consts.js +2 -0
  84. package/backend/tasks/tasks-configs.js +18 -0
  85. package/package.json +1 -1
  86. package/pages/personalDetails.js +33 -34
@@ -0,0 +1,151 @@
1
+ const { LOGIN_EMAIL_SYNC_STATUS } = require('../consts');
2
+ const { updateWixMemberLoginEmail } = require('../members-area-methods');
3
+ const { extractUrlCounter } = require('../utils');
4
+
5
+ const { MEMBER_ACTIONS } = require('./consts');
6
+
7
+ const isUpdatedMember = member => member.action !== MEMBER_ACTIONS.NONE;
8
+ const isSiteAssociatedMember = (member, siteAssociation) =>
9
+ member.memberships.some(membership => membership.association === siteAssociation);
10
+
11
+ /**
12
+ * Attempts to change Wix login emails for the given members and returns one structured
13
+ * outcome per member (see updateWixMemberLoginEmail). Never throws for an individual member.
14
+ * @param {Array} toChangeWixMembersEmails
15
+ * @returns {Promise<Array>} outcomes
16
+ */
17
+ const changeWixMembersEmails = async toChangeWixMembersEmails => {
18
+ console.log(
19
+ `[loginEmailSync] changing login emails for ${toChangeWixMembersEmails.length} members with ids: [${toChangeWixMembersEmails.map(member => member.memberId).join(', ')}]`
20
+ );
21
+ const outcomes = await Promise.all(
22
+ toChangeWixMembersEmails.map(member => updateWixMemberLoginEmail(member))
23
+ );
24
+ const summary = outcomes.reduce((acc, outcome) => {
25
+ acc[outcome.status] = (acc[outcome.status] || 0) + 1;
26
+ return acc;
27
+ }, {});
28
+ console.log(`[loginEmailSync] results summary: ${JSON.stringify(summary)}`);
29
+ return outcomes;
30
+ };
31
+
32
+ /**
33
+ * Summarizes login-email sync outcomes for manual handling via the task result.
34
+ * Pure function so it can be unit-tested without Wix.
35
+ * @param {Array} outcomes - from updateWixMemberLoginEmail / changeWixMembersEmails
36
+ * @returns {{ failedMemberIds: Set, failures: Array }} set of failed memberIds (whose CMS login
37
+ * email must be left unchanged) and the failure records to surface in the task result
38
+ */
39
+ const summarizeLoginEmailOutcomes = (outcomes = []) => {
40
+ const failedMemberIds = new Set();
41
+ const failures = [];
42
+ outcomes.forEach(outcome => {
43
+ if (outcome.status === LOGIN_EMAIL_SYNC_STATUS.FAILED) {
44
+ failedMemberIds.add(outcome.memberId);
45
+ failures.push({
46
+ memberId: outcome.memberId,
47
+ wixMemberId: outcome.wixMemberId,
48
+ desiredEmail: outcome.desiredEmail,
49
+ error: outcome.error || 'unknown error',
50
+ });
51
+ }
52
+ });
53
+ return { failedMemberIds, failures };
54
+ };
55
+
56
+ const extractBaseUrl = url => {
57
+ if (!url) return url;
58
+ const lastCounter = extractUrlCounter(url);
59
+ if (lastCounter > 0) {
60
+ // Remove the numeric counter to get the base URL
61
+ return url.split('-').slice(0, -1).join('-');
62
+ }
63
+ // No counter found, return the URL as-is
64
+ return url;
65
+ };
66
+ const incrementUrlCounter = (existingUrl, baseUrl) => {
67
+ if (!existingUrl || !baseUrl) {
68
+ return baseUrl;
69
+ }
70
+ // Normalize for comparison (case-insensitive)
71
+ const normalizedExisting = existingUrl.toLowerCase();
72
+ const normalizedBase = baseUrl.toLowerCase();
73
+
74
+ if (
75
+ normalizedExisting === normalizedBase ||
76
+ normalizedExisting.startsWith(`${normalizedBase}-`)
77
+ ) {
78
+ console.log(
79
+ `Found member with same url ${existingUrl} for baseUrl ${baseUrl}, increasing counter by 1`
80
+ );
81
+ const lastCounter = Math.max(0, extractUrlCounter(existingUrl));
82
+ return `${baseUrl}-${lastCounter + 1}`;
83
+ }
84
+
85
+ // No conflict, return baseUrl with counter 1 to be safe
86
+ return `${baseUrl}-1`;
87
+ };
88
+ /**
89
+ * Validates core member data requirements
90
+ * @param {Object} inputMemberData - Raw member data from API to validate
91
+ * @returns {boolean} - True if all required fields are valid, false otherwise
92
+ */
93
+ const validateCoreMemberData = inputMemberData => {
94
+ // Check memberid
95
+ if (!inputMemberData?.memberid) {
96
+ console.warn('validateCoreMemberData: Missing required field - memberid is mandatory');
97
+ return false;
98
+ }
99
+
100
+ // Check email
101
+ if (
102
+ !inputMemberData?.email ||
103
+ typeof inputMemberData.email !== 'string' ||
104
+ !inputMemberData.email.trim()
105
+ ) {
106
+ console.warn(
107
+ 'validateCoreMemberData: Missing required field - email (valid string) is mandatory'
108
+ );
109
+ return false;
110
+ }
111
+
112
+ // Check memberships
113
+ if (
114
+ !inputMemberData?.memberships ||
115
+ !Array.isArray(inputMemberData.memberships) ||
116
+ inputMemberData.memberships.length === 0
117
+ ) {
118
+ console.warn(
119
+ 'validateCoreMemberData: Missing required field - memberships (non-empty array) is mandatory'
120
+ );
121
+ return false;
122
+ }
123
+
124
+ return true;
125
+ };
126
+
127
+ const containsNonEnglish = str => /[^a-zA-Z0-9-]/.test(str); // if it contains any non-english characters or invalid URL chars, test1 is allowed, hyphens are allowed
128
+
129
+ /**
130
+ * Creates a full name from first and last name components
131
+ * @param {string} firstName - First name
132
+ * @param {string} lastName - Last name
133
+ * @returns {string} - Combined full name
134
+ */
135
+ const createFullName = (firstName, lastName) => {
136
+ const trimmedFirst = firstName?.trim() || '';
137
+ const trimmedLast = lastName?.trim() || '';
138
+ return `${trimmedFirst} ${trimmedLast}`.trim();
139
+ };
140
+
141
+ module.exports = {
142
+ isUpdatedMember,
143
+ isSiteAssociatedMember,
144
+ changeWixMembersEmails,
145
+ summarizeLoginEmailOutcomes,
146
+ validateCoreMemberData,
147
+ containsNonEnglish,
148
+ createFullName,
149
+ incrementUrlCounter,
150
+ extractBaseUrl,
151
+ };
@@ -0,0 +1,29 @@
1
+ const { taskManager, TASK_TYPE } = require('psdev-task-manager');
2
+
3
+ const { COMPILED_FILTERS_FIELDS } = require('./consts');
4
+ const { TASKS_NAMES } = require('./tasks/consts');
5
+
6
+ const scheduleCompileFiltersTask = field =>
7
+ taskManager().schedule({
8
+ name: TASKS_NAMES.CompileFiltersOptions,
9
+ data: { field },
10
+ type: TASK_TYPE.SCHEDULED,
11
+ });
12
+
13
+ function scheduleCompileInterestsTask() {
14
+ return scheduleCompileFiltersTask(COMPILED_FILTERS_FIELDS.COMPILED_AREAS_OF_PRACTICES);
15
+ }
16
+
17
+ function scheduleCompileStatesTask() {
18
+ return scheduleCompileFiltersTask(COMPILED_FILTERS_FIELDS.COMPILED_STATE_LIST);
19
+ }
20
+
21
+ function scheduleCompileCitiesTask() {
22
+ return scheduleCompileFiltersTask(COMPILED_FILTERS_FIELDS.COMPILED_STATE_CITY_MAP);
23
+ }
24
+
25
+ module.exports = {
26
+ scheduleCompileInterestsTask,
27
+ scheduleCompileStatesTask,
28
+ scheduleCompileCitiesTask,
29
+ };
@@ -0,0 +1,58 @@
1
+ const { COLLECTIONS } = require('../public/consts');
2
+
3
+ const { ensureUniqueUrlsInBatch } = require('./daily-pull/bulk-process-methods');
4
+ const { ensureUniqueUrl } = require('./daily-pull/process-member-methods');
5
+ const { wixData } = require('./elevated-modules');
6
+ const { bulkSaveMembers } = require('./members-data-methods');
7
+ const { queryAllItems } = require('./utils');
8
+
9
+ async function deduplicateURls(collectionName, duplicateUrlsList) {
10
+ const query = await wixData.query(collectionName).hasSome('url', duplicateUrlsList).limit(1000);
11
+ const membersWithSameUrl = await queryAllItems(query);
12
+
13
+ console.log({ membersWithSameUrl });
14
+ const membersWithUniqueUrls = await ensureUniqueUrlsInBatch(membersWithSameUrl);
15
+ console.log({ membersWithUniqueUrls });
16
+ const deduplicatedUrls = membersWithUniqueUrls.map(m => m.url);
17
+ console.log({ deduplicatedUrls });
18
+ return await bulkSaveMembers(membersWithUniqueUrls, collectionName);
19
+ }
20
+
21
+ async function copyContactIdToWixMemberId() {
22
+ const query = wixData.query(COLLECTIONS.MEMBERS_DATA).isNotEmpty('contactId');
23
+ const members = await queryAllItems(query);
24
+ const updatedMembers = members.map(member => ({
25
+ ...member,
26
+ wixMemberId: member.contactId,
27
+ }));
28
+ return await bulkSaveMembers(updatedMembers, COLLECTIONS.MEMBERS_DATA);
29
+ }
30
+
31
+ async function createMissingUrls() {
32
+ const query = wixData.query(COLLECTIONS.MEMBERS_DATA).isEmpty('url');
33
+ const members = await queryAllItems(query);
34
+ console.log(
35
+ 'membersWithoutUrls info',
36
+ JSON.stringify({
37
+ count: members.length,
38
+ membersIds: members.map(m => m.memberId),
39
+ })
40
+ );
41
+
42
+ const membersWithGeneratedUrlsPromises = members.map(async member => ({
43
+ ...member,
44
+ url: await ensureUniqueUrl({
45
+ url: member.url,
46
+ memberId: member.memberId,
47
+ fullName: member.fullName,
48
+ }),
49
+ }));
50
+ const membersWithGeneratedUrls = await Promise.all(membersWithGeneratedUrlsPromises);
51
+ //recheck urls in same batch to avoid duplicates
52
+ const uniqueUrlsUpdatedMembers = await ensureUniqueUrlsInBatch(membersWithGeneratedUrls);
53
+ const urls = uniqueUrlsUpdatedMembers.map(m => m.url).filter(Boolean);
54
+ console.log('unique urls', [...new Set(urls)]);
55
+ return await bulkSaveMembers(uniqueUrlsUpdatedMembers, COLLECTIONS.MEMBERS_DATA);
56
+ }
57
+
58
+ module.exports = { deduplicateURls, copyContactIdToWixMemberId, createMissingUrls };
@@ -0,0 +1,18 @@
1
+ const { items } = require('@wix/data');
2
+ const { auth } = require('@wix/essentials');
3
+
4
+ // @wix/data does not support suppressAuth currently, so we need to elevate it
5
+ const wixData = {
6
+ insert: auth.elevate(items.insert),
7
+ update: auth.elevate(items.update),
8
+ bulkInsert: auth.elevate(items.bulkInsert),
9
+ query: auth.elevate(items.query),
10
+ save: auth.elevate(items.save),
11
+ remove: auth.elevate(items.remove),
12
+ get: auth.elevate(items.get),
13
+ truncate: auth.elevate(items.truncate),
14
+ bulkSave: auth.elevate(items.bulkSave),
15
+ search: auth.elevate(items.search),
16
+ //TODO: add other methods here as needed
17
+ };
18
+ module.exports = { wixData };
@@ -0,0 +1,52 @@
1
+ const { COLLECTIONS } = require('../public/consts');
2
+
3
+ const { triggerAutomation } = require('./automations-methods');
4
+ const { CONFIG_KEYS } = require('./consts');
5
+ const { wixData } = require('./elevated-modules');
6
+ const { findMemberByWixDataId, createContactAndMemberIfNew } = require('./members-data-methods');
7
+ const { getSiteConfigs } = require('./utils');
8
+
9
+ const contactSubmission = async (data, memberDataId) => {
10
+ const { firstName, lastName, email, phone, message } = data;
11
+ const [memberData, automationEmailTriggerId] = await Promise.all([
12
+ findMemberByWixDataId(memberDataId),
13
+ getSiteConfigs(CONFIG_KEYS.AUTOMATION_EMAIL_TRIGGER_ID),
14
+ ]);
15
+ if (!memberData.showContactForm) {
16
+ console.log('Member contact form is not enabled for user, skipping contact submission!');
17
+ return;
18
+ }
19
+ let memberContactId = memberData.wixContactId;
20
+ if (!memberContactId) {
21
+ /**
22
+ * Create a member contact here since some members may have never logged in
23
+ * and therefore don’t have a contact ID. However, these members can still
24
+ * appear in the directory, and site visitors can reach out to them if they’ve
25
+ * enabled their contact form. To handle this, we ensure a contact is created for
26
+ * them during this flow if it doesn’t already exist.
27
+ */
28
+ console.info('Member contact id not found for user, creating new contact!');
29
+ const member = await createContactAndMemberIfNew(memberData);
30
+ memberContactId = member.wixContactId;
31
+ }
32
+ console.log('memberContactId', memberContactId);
33
+ const emailTriggered = await triggerAutomation(automationEmailTriggerId, {
34
+ contactId: memberContactId,
35
+ name: `${firstName} ${lastName}`,
36
+ email: email,
37
+ phone: phone,
38
+ message: message,
39
+ });
40
+ data = {
41
+ ...data,
42
+ phone: Number(data.phone),
43
+ memberContactId,
44
+ memberEmail: memberData.contactFormEmail,
45
+ };
46
+ await wixData.insert(COLLECTIONS.CONTACT_US_SUBMISSIONS, data);
47
+ return emailTriggered;
48
+ };
49
+
50
+ module.exports = {
51
+ contactSubmission,
52
+ };
@@ -0,0 +1,86 @@
1
+ const { COLLECTIONS } = require('../../public/consts');
2
+ const { clearCollection } = require('../cms-data-methods');
3
+ const { CONFIG_KEYS } = require('../consts');
4
+ const { getSecret, getSiteConfigs } = require('../utils');
5
+
6
+ const { migrateInterests } = require('./interests');
7
+
8
+ const createHTTPFunctionsHelpers = wixHTTPFunctionsMethods => {
9
+ const { created, serverError, forbidden, ok, badRequest } = wixHTTPFunctionsMethods;
10
+ const responseOptions = {
11
+ headers: {
12
+ 'Content-Type': 'application/json',
13
+ },
14
+ };
15
+
16
+ const isRequestAuthenticated = async request => {
17
+ const AUTH_TOKEN = await getSecret('migrate-api-key');
18
+ return request.headers.authorization === 'Bearer ' + AUTH_TOKEN;
19
+ };
20
+
21
+ const withAuth = handler => async request => {
22
+ if (!(await isRequestAuthenticated(request))) {
23
+ return forbidden({
24
+ ...responseOptions,
25
+ body: { error: 'Unauthorized' },
26
+ });
27
+ }
28
+ return handler(request);
29
+ };
30
+
31
+ const migrateInterestsHandler = async _request => {
32
+ try {
33
+ const result = await migrateInterests();
34
+ return created({
35
+ ...responseOptions,
36
+ body: {
37
+ result,
38
+ },
39
+ });
40
+ } catch (error) {
41
+ console.error('Error migrating interests:', error);
42
+ return serverError(error);
43
+ }
44
+ };
45
+
46
+ const clearCollectionHandler = async request => {
47
+ try {
48
+ const collectionName = request.query.collectionName;
49
+ if (!collectionName || !Object.values(COLLECTIONS).includes(collectionName)) {
50
+ return badRequest({
51
+ ...responseOptions,
52
+ body: { error: 'Invalid collection name' },
53
+ });
54
+ }
55
+ const result = await clearCollection(collectionName);
56
+ return ok({
57
+ ...responseOptions,
58
+ body: {
59
+ result,
60
+ },
61
+ });
62
+ } catch (error) {
63
+ return serverError(error);
64
+ }
65
+ };
66
+ const getSiteAssociationHandler = async _request => {
67
+ try {
68
+ const siteAssociation = await getSiteConfigs(CONFIG_KEYS.SITE_ASSOCIATION);
69
+ return ok({
70
+ ...responseOptions,
71
+ body: { siteAssociation },
72
+ });
73
+ } catch (error) {
74
+ console.error('Error getting site association:', error);
75
+ return serverError(error);
76
+ }
77
+ };
78
+
79
+ return {
80
+ post_migrateInterests: withAuth(migrateInterestsHandler),
81
+ delete_clearCollection: withAuth(clearCollectionHandler),
82
+ get_getSiteAssociation: withAuth(getSiteAssociationHandler),
83
+ };
84
+ };
85
+
86
+ module.exports = { createHTTPFunctionsHelpers };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ ...require('./httpFunctions'),
3
+ };
@@ -0,0 +1,35 @@
1
+ const axios = require('axios');
2
+
3
+ const { COLLECTIONS } = require('../../public/consts');
4
+ const { clearCollection } = require('../cms-data-methods');
5
+ const { CONFIG_KEYS } = require('../consts');
6
+ const { wixData } = require('../elevated-modules');
7
+ const { getHeaders } = require('../pac-api-methods');
8
+ const { getSiteConfigs } = require('../utils');
9
+
10
+ const getInterests = async () => {
11
+ const [url, headers] = await Promise.all([
12
+ getSiteConfigs(CONFIG_KEYS.INTERESTS_API_URL),
13
+ getHeaders(),
14
+ ]);
15
+ try {
16
+ const response = await axios.get(url, { headers });
17
+ return response.data;
18
+ } catch (e) {
19
+ console.error('Error getting interests:', e);
20
+ throw e;
21
+ }
22
+ };
23
+
24
+ async function migrateInterests() {
25
+ const [interests, _] = await Promise.all([
26
+ getInterests(),
27
+ clearCollection(COLLECTIONS.INTERESTS),
28
+ ]);
29
+ const interestData = interests.map(val => ({ title: val.interest }));
30
+ return await wixData.bulkInsert(COLLECTIONS.INTERESTS, interestData);
31
+ }
32
+
33
+ module.exports = {
34
+ migrateInterests,
35
+ };
@@ -0,0 +1,19 @@
1
+ module.exports = {
2
+ ...require('./forms-methods'),
3
+ ...require('./search-filters-methods'),
4
+ ...require('./jobs'),
5
+ ...require('./consts'), //TODO: remove it once we finish NPM movement
6
+ ...require('./utils'), //TODO: remove it once we finish NPM movement
7
+ ...require('./daily-pull'), //TODO: remove it once we finish NPM movement
8
+ ...require('./pac-api-methods'), //TODO: remove it once we finish NPM movement
9
+ ...require('./members-area-methods'), //TODO: remove it once we finish NPM movement
10
+ ...require('./members-data-methods'), //TODO: remove it once we finish NPM movement
11
+ ...require('./cms-data-methods'), //TODO: remove it once we finish NPM movement
12
+ ...require('./routers'),
13
+ ...require('./login'),
14
+ ...require('./data-hooks'),
15
+ ...require('./http-functions'),
16
+ ...require('./dev-only-methods'),
17
+ ...require('./tasks/migration-methods'),
18
+ ...require('./tasks/url-migration-methods'),
19
+ };
@@ -0,0 +1,158 @@
1
+ const { taskManager } = require('psdev-task-manager');
2
+
3
+ const { scheduleDailyPullTasks } = require('./daily-pull/schedule-methods');
4
+ const { TASKS_NAMES } = require('./tasks/consts');
5
+ const { dailyPullExecutionCheck } = require('./tasks/daily-pull-check-methods');
6
+ const { TASKS } = require('./tasks/tasks-configs');
7
+
8
+ async function runScheduledTasks() {
9
+ try {
10
+ console.log('runScheduledTasks started');
11
+ return await taskManager().runScheduledTasks(TASKS);
12
+ } catch (error) {
13
+ console.error(`Failed to runScheduledTasks: ${error.message}`);
14
+ throw new Error(`Failed to runScheduledTasks: ${error.message}`);
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Schedule daily pull tasks for all member actions.
20
+ * @param {string|Object} [options] - Optional. Either a backup date (YYYY-MM-DD) or options.
21
+ * @param {string} [options.backupDate] - Optional backup date to pull.
22
+ * @param {boolean} [options.isTestEnvironment=false] - Whether to use test environment.
23
+ * @param {boolean} [options.includeNone=false] - Whether to include NONE action.
24
+ * @returns {Promise<void>}
25
+ */
26
+ async function scheduleDailyPullTask(options = null) {
27
+ try {
28
+ console.log('scheduleDailyPullTask started!');
29
+ const hasOptions = options && typeof options === 'object' && !Array.isArray(options);
30
+ const backupDate = hasOptions ? options.backupDate : options;
31
+ const isTestEnvironment = hasOptions ? Boolean(options.isTestEnvironment) : false;
32
+ const includeNone = hasOptions ? Boolean(options.includeNone) : false;
33
+ console.log(`backupDate: ${backupDate}`);
34
+ console.log(`isTestEnvironment: ${isTestEnvironment}`);
35
+ console.log(`includeNone: ${includeNone}`);
36
+
37
+ return await scheduleDailyPullTasks({ backupDate, isTestEnvironment, includeNone });
38
+ } catch (error) {
39
+ console.error(`Failed to scheduleDailyPullTask: ${error.message}`);
40
+ throw new Error(`Failed to scheduleDailyPullTask: ${error.message}`);
41
+ }
42
+ }
43
+
44
+ async function scheduleCreateContactsFromMembersTask() {
45
+ try {
46
+ console.log('scheduleCreateContactsFromMembers started!');
47
+ return await taskManager().schedule({
48
+ name: TASKS_NAMES.scheduleCreateContactsFromMembers,
49
+ data: {},
50
+ type: 'scheduled',
51
+ });
52
+ } catch (error) {
53
+ console.error(`Failed to scheduleCreateContactsFromMembers: ${error.message}`);
54
+ throw new Error(`Failed to scheduleCreateContactsFromMembers: ${error.message}`);
55
+ }
56
+ }
57
+
58
+ async function scheduleFixPrimaryAddressForMembersTask() {
59
+ try {
60
+ console.log('scheduleFixPrimaryAddressForMembers started!');
61
+ return await taskManager().schedule({
62
+ name: TASKS_NAMES.scheduleFixPrimaryAddressForMembers,
63
+ data: {},
64
+ type: 'scheduled',
65
+ });
66
+ } catch (error) {
67
+ console.error(`Failed to scheduleFixPrimaryAddressForMembers: ${error.message}`);
68
+ throw new Error(`Failed to scheduleFixPrimaryAddressForMembers: ${error.message}`);
69
+ }
70
+ }
71
+
72
+ async function scheduleFixUrlsWithSpacesTask() {
73
+ try {
74
+ console.log('scheduleFixUrlsWithSpaces started!');
75
+ return await taskManager().schedule({
76
+ name: TASKS_NAMES.scheduleFixUrlsWithSpaces,
77
+ data: {},
78
+ type: 'scheduled',
79
+ });
80
+ } catch (error) {
81
+ console.error(`Failed to scheduleFixUrlsWithSpaces: ${error.message}`);
82
+ throw new Error(`Failed to scheduleFixUrlsWithSpaces: ${error.message}`);
83
+ }
84
+ }
85
+
86
+ async function scheduleNormalizeMemberEmailsTask() {
87
+ try {
88
+ console.log('scheduleNormalizeMemberEmails started!');
89
+ return await taskManager().schedule({
90
+ name: TASKS_NAMES.scheduleNormalizeMemberEmails,
91
+ data: {},
92
+ type: 'scheduled',
93
+ });
94
+ } catch (error) {
95
+ console.error(`Failed to scheduleNormalizeMemberEmails: ${error.message}`);
96
+ throw new Error(`Failed to scheduleNormalizeMemberEmails: ${error.message}`);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Schedules setting ALL addresses for ALL members that have any address to STATE_CITY_ZIP
102
+ * (show city/state/zip, hide the street). Manually triggered one-off maintenance task.
103
+ */
104
+ async function scheduleSetAddressesToCityStateTask() {
105
+ try {
106
+ console.log('scheduleSetAddressesToCityState started!');
107
+ return await taskManager().schedule({
108
+ name: TASKS_NAMES.scheduleSetAddressesToCityState,
109
+ data: {},
110
+ type: 'scheduled',
111
+ });
112
+ } catch (error) {
113
+ console.error(`Failed to scheduleSetAddressesToCityState: ${error.message}`);
114
+ throw new Error(`Failed to scheduleSetAddressesToCityState: ${error.message}`);
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Runs the daily pull execution check (watchdog).
120
+ * @param {Object} [options]
121
+ * @param {number} [options.hoursBack=4] - Lookback window in hours
122
+ * @param {boolean} [options.isTestEnvironment=false] - Pull from the test PAC API if the fallback fires
123
+ * @param {boolean} [options.includeNone=false] - Include the NONE action if the fallback fires
124
+ * @returns {Promise<Object>} - Check result
125
+ */
126
+ async function runDailyPullExecutionCheck(options = {}) {
127
+ try {
128
+ console.log('runDailyPullExecutionCheck started!');
129
+ return await dailyPullExecutionCheck(options || {});
130
+ } catch (error) {
131
+ console.error(`Failed to runDailyPullExecutionCheck: ${error.message}`);
132
+ throw new Error(`Failed to runDailyPullExecutionCheck: ${error.message}`);
133
+ }
134
+ }
135
+
136
+ async function updateSiteMapS3() {
137
+ try {
138
+ return await taskManager().schedule({
139
+ name: TASKS_NAMES.updateSiteMapS3,
140
+ data: {},
141
+ type: 'scheduled',
142
+ });
143
+ } catch (error) {
144
+ throw new Error(`Failed to updateSiteMapS3: ${error.message}`);
145
+ }
146
+ }
147
+
148
+ module.exports = {
149
+ runScheduledTasks,
150
+ scheduleDailyPullTask,
151
+ updateSiteMapS3,
152
+ scheduleCreateContactsFromMembersTask,
153
+ scheduleFixPrimaryAddressForMembersTask,
154
+ scheduleFixUrlsWithSpacesTask,
155
+ scheduleNormalizeMemberEmailsTask,
156
+ scheduleSetAddressesToCityStateTask,
157
+ runDailyPullExecutionCheck,
158
+ };
@@ -0,0 +1,27 @@
1
+ const { auth } = require('@wix/essentials');
2
+ const { authentication } = require('@wix/identity');
3
+
4
+ const elevatedSignOn = auth.elevate(authentication.signOn);
5
+
6
+ /**
7
+ * Creates a Wix member session token for SSO / QA login using @wix/identity signOn (elevated).
8
+ * @param {string} email - Member login email
9
+ * @returns {Promise<string>} Session token for authentication.applySessionToken on the client
10
+ */
11
+ async function generateMemberSessionToken(email) {
12
+ const trimmedEmail = (email || '').trim();
13
+ if (!trimmedEmail) {
14
+ throw new Error('Email is required to generate a session token');
15
+ }
16
+
17
+ const response = await elevatedSignOn({ email: trimmedEmail });
18
+ const sessionToken = response?.sessionToken;
19
+ if (!sessionToken) {
20
+ throw new Error('Failed to generate session token: empty response from signOn');
21
+ }
22
+ return sessionToken;
23
+ }
24
+
25
+ module.exports = {
26
+ generateMemberSessionToken,
27
+ };
@@ -0,0 +1,8 @@
1
+ const { loginQAMember } = require('./qa-login-methods');
2
+ const { validateMemberToken, authenticateSSOToken } = require('./sso-methods');
3
+
4
+ module.exports = {
5
+ loginQAMember,
6
+ validateMemberToken,
7
+ authenticateSSOToken,
8
+ };