1const PRODUCT_TYPES = { 2 DOMAIN_NAME: 'DomainName', 3 ALL_IN_ONE_PLAN: 'AllInOnePlan', 4 ORDER_PRODUCT: 'OrderProduct', 5 EXTERNAL_DOMAIN_NAME: 'ExternalDomainName', 6}; 7 8const createEmptyDomainInfo = () => ({ 9 activeDomains: [], 10 transferDomains: [], 11 failedDomains: [], 12 extraDomains: [], 13 processDomains: [], 14 expiredDomains: [], 15 activePlans: [], 16 expiredPlans: [], 17 externalDomains: [], 18}); 19 20const setPlanRelation = (items, itemId, planId) => 21 items.map((item) => { 22 if (item?.id !== itemId) { 23 return item; 24 } 25 26 return { 27 ...item, 28 planId, 29 }; 30 }); 31 32const toTagIds = (tags) => 33 (Array.isArray(tags) ? tags : []).map((tag) => (typeof tag === 'string' || typeof tag === 'number' ? tag : tag?.id)); 34 35const parseSidebarProduct = ({ type, item }) => { 36 if (!item || typeof item !== 'object') { 37 return null; 38 } 39 40 switch (type) { 41 case 'active': 42 return { 43 name: item.full_domain_name, 44 id: item.id, 45 tags: toTagIds(item.domain_name_tags), 46 type: 'active', 47 createdAt: item.registration_date, 48 status: item.status?.name, 49 dnsEnabled: item.dns_control_enabled, 50 dnssecEnabled: item.is_dnssec_enabled, 51 privacyProtection: item.privacy_protection === 1, 52 contactId: item.domain_name_owner?.contact?.id, 53 expiresAt: item.expiration_date, 54 orderedAt: item.order_date, 55 registeredAt: item.registration_date, 56 planId: item.customer_plan?.id, 57 autoRenew: item.auto_renew === 1, 58 advancedSettings: item.access_to_advanced_settings, 59 emailEnabled: item.is_email_enabled, 60 siteBuilderEnabled: item.is_site_builder_enabled, 61 webHostingEnabled: item.is_webhosting_enabled, 62 }; 63 case 'transfer_pending': 64 return { 65 name: `${item.name}.${item.domain_top_level?.top_level_domain}`, 66 id: item.id, 67 type: 'transfer', 68 tags: toTagIds(item.domain_name_tags || item.order_product?.domain_name_tags), 69 createdAt: item.registration_date, 70 status: item.status?.name, 71 updatedAt: item.order_product?.order_product_domain_name_history?.updated_at || item.order_date, 72 extraInfo: { 73 history: { 74 createdAt: item.order_product?.order_product_domain_name_history?.created_at || item.order_date, 75 logs: item.order_product?.order_product_domain_name_history?.log || [], 76 }, 77 }, 78 }; 79 case 'manually_expired': 80 case 'expired': 81 return { 82 name: `${item.name}.${item.domain_top_level?.top_level_domain}`, 83 id: item.id, 84 type: 'expired', 85 tags: toTagIds(item.domain_name_tags), 86 createdAt: item.registration_date, 87 status: item.status?.name, 88 expiredAt: item.expiration_date, 89 contactId: item.domain_name_owner?.contact?.id, 90 orderedAt: item.order_date, 91 registeredAt: item.registration_date, 92 }; 93 case 'active-plan': 94 return { 95 name: item.name || '', 96 planName: item.plan?.name, 97 planType: item.plan?.type?.type || item.plan?.type || '', 98 id: item.id, 99 type: 'active-plan', 100 createdAt: item.created_at, 101 status: item.status, 102 planId: item.plan?.id, 103 expiresAt: item.expires_at, 104 orderedAt: item.created_at, 105 autoRenew: item.is_auto_renew, 106 linkedDomains: item.number_of_domains, 107 webHostingEnabled: item.is_webhosting_enabled, 108 webhostingAccount: item.webhosting_account || null, 109 emailEnabled: item.is_email_enabled, 110 siteBuilderEnabled: item.is_site_builder_enabled, 111 }; 112 case 'expired-plan': 113 return { 114 name: item.name || '', 115 planName: item.plan?.name, 116 planType: item.plan?.type?.type || item.plan?.type || '', 117 id: item.id, 118 type: 'expired-plan', 119 createdAt: item.created_at, 120 status: item.status, 121 expiredAt: item.cancelled_at || item.expired_at || item.expires_at || '', 122 planId: item.plan?.id, 123 }; 124 case 'transfer_failed': 125 return { 126 name: item.full_domain_name || '', 127 id: item.id, 128 type: 'failed', 129 tags: toTagIds(item.domain_name_tags), 130 status: item.status?.status, 131 updatedAt: item.order_product_domain_name_history?.updated_at || '', 132 extraInfo: { 133 history: { 134 createdAt: item.order_product_domain_name_history?.created_at, 135 logs: item.order_product_domain_name_history?.log || [], 136 }, 137 }, 138 }; 139 case 'awaiting_required_info': 140 return { 141 name: 142 item.full_domain_name || 143 item.order_product?.full_domain_name || 144 item.request_data_information?.domainName || 145 '', 146 id: item.id, 147 type: 'extra', 148 tags: toTagIds(item.domain_name_tags), 149 status: item.status?.status, 150 extraInfo: { 151 requestedData: item.request_data_information?.message, 152 }, 153 }; 154 case 'registration_pending': 155 case 'processing': 156 return { 157 name: item.full_domain_name || '', 158 id: item.id, 159 type: 'process', 160 tags: toTagIds(item.domain_name_tags), 161 status: item.status?.status || item.status?.name, 162 }; 163 case 'external': 164 return { 165 name: item.name, 166 id: item.id, 167 type: 'external', 168 createdAt: item.created_at, 169 status: 'active', 170 planId: item.customer_plan?.id, 171 dnsEnabled: item.is_dns_control_enabled, 172 advancedSettings: item.access_to_advanced_settings, 173 emailEnabled: item.is_email_enabled, 174 siteBuilderEnabled: item.is_site_builder_enabled, 175 webHostingEnabled: item.is_webhosting_enabled, 176 }; 177 default: 178 return null; 179 } 180}; 181 182const removeOldDomainNames = (domainInfo, payload) => { 183 if (payload.old_status === 'active') { 184 domainInfo.activeDomains = domainInfo.activeDomains.filter( 185 (item) => item.id !== (payload.data?.id || payload.domain_name_id), 186 ); 187 } 188 189 if (payload.old_status === 'expired' || payload.old_status === 'manually_expired') { 190 domainInfo.expiredDomains = domainInfo.expiredDomains.filter( 191 (item) => item.id !== (payload.data?.id || payload.domain_name_id), 192 ); 193 } 194 195 if (payload.old_status === 'transfer_pending') { 196 domainInfo.transferDomains = domainInfo.transferDomains.filter( 197 (item) => item.id !== (payload.data?.id || payload.domain_name_id), 198 ); 199 } 200 201 if (payload.old_status === 'registration_pending') { 202 domainInfo.processDomains = domainInfo.processDomains.filter( 203 (item) => item.id !== (payload.data?.id || payload.domain_name_id), 204 ); 205 } 206 207 return domainInfo; 208}; 209 210const updateDomainNames = (domainInfo, payload) => { 211 if (payload.old_status) { 212 domainInfo = removeOldDomainNames(domainInfo, payload); 213 } 214 215 if (payload.new_status === 'unlinked_from_all_in_one_plan') { 216 domainInfo.activeDomains = setPlanRelation(domainInfo.activeDomains, payload.data?.id, undefined); 217 return domainInfo; 218 } 219 220 if (payload.new_status === 'linked_to_all_in_one_plan') { 221 domainInfo.activeDomains = setPlanRelation( 222 domainInfo.activeDomains, 223 payload.data?.id, 224 payload.data?.customer_plan?.id, 225 ); 226 return domainInfo; 227 } 228 229 if (!payload.data?.status) { 230 return domainInfo; 231 } 232 233 const item = parseSidebarProduct({ 234 type: payload.data.status.name, 235 item: payload.data, 236 }); 237 if (!item) { 238 return domainInfo; 239 } 240 241 if (payload.new_status === 'active' && !domainInfo.activeDomains.some((entry) => entry.id === item.id)) { 242 domainInfo.activeDomains.push(item); 243 } 244 245 if ( 246 (payload.new_status === 'expired' || payload.new_status === 'manually_expired') && 247 !domainInfo.expiredDomains.some((entry) => entry.id === item.id) 248 ) { 249 domainInfo.expiredDomains.push(item); 250 } 251 252 if (payload.new_status === 'transfer_pending' && !domainInfo.transferDomains.some((entry) => entry.id === item.id)) { 253 domainInfo.transferDomains.push(item); 254 } 255 256 if ( 257 payload.new_status === 'registration_pending' && 258 !domainInfo.processDomains.some((entry) => entry.id === item.id) 259 ) { 260 domainInfo.processDomains.push(item); 261 } 262 263 return domainInfo; 264}; 265
266const updateExternalDomains = (domainInfo, payload) => { 267 if (payload.new_status === 'deleted') { 268 domainInfo.externalDomains = domainInfo.externalDomains.filter((item) => item.id !== payload.id); 269 return domainInfo; 270 } 271 272 if (payload.new_status === 'unlinked_from_all_in_one_plan') { 273 domainInfo.externalDomains = setPlanRelation(domainInfo.externalDomains, payload.data?.id, undefined); 274 return domainInfo; 275 } 276 277 if (payload.new_status === 'linked_to_all_in_one_plan') { 278 domainInfo.externalDomains = setPlanRelation( 279 domainInfo.externalDomains, 280 payload.data?.id, 281 payload.data?.customer_plan?.id, 282 ); 283 return domainInfo; 284 } 285 286 const item = parseSidebarProduct({ 287 type: 'external', 288 item: payload.data, 289 }); 290 if (item && !domainInfo.externalDomains.some((entry) => entry.id === item.id)) { 291 domainInfo.externalDomains.push(item); 292 } 293 294 return domainInfo; 295}; 296 297const updatePlans = (domainInfo, payload) => { 298 if (payload.old_status) { 299 if (payload.old_status === 'active') { 300 domainInfo.activePlans = domainInfo.activePlans.filter((item) => item.id !== payload.data?.id); 301 } else { 302 domainInfo.expiredPlans = domainInfo.expiredPlans.filter((item) => item.id !== payload.data?.id); 303 } 304 } 305 306 const type = payload.new_status === 'active' ? 'active-plan' : 'expired-plan'; 307 const item = parseSidebarProduct({ type, item: payload.data }); 308 if (!item) { 309 return domainInfo; 310 } 311 312 if (payload.new_status === 'active') { 313 if (!domainInfo.activePlans.some((entry) => entry.id === item.id)) { 314 domainInfo.activePlans.push(item); 315 } 316 return domainInfo; 317 } 318 319 if (!domainInfo.expiredPlans.some((entry) => entry.id === item.id)) { 320 domainInfo.expiredPlans.push(item); 321 } 322 323 return domainInfo; 324}; 325 326const removeOldOrderProducts = (domainInfo, payload) => { 327 if (payload.old_status === 'transfer_failed') { 328 domainInfo.failedDomains = domainInfo.failedDomains.filter((item) => item.id !== payload.data?.id); 329 } 330 331 if (payload.old_status === 'awaiting_required_info') { 332 domainInfo.extraDomains = domainInfo.extraDomains.filter((item) => item.id !== payload.data?.id); 333 } 334 335 if (payload.old_status === 'processing') { 336 domainInfo.processDomains = domainInfo.processDomains.filter((item) => item.id !== payload.data?.id); 337 } 338 339 return domainInfo; 340}; 341 342const updateOrderProducts = (domainInfo, payload) => { 343 if (payload.old_status) { 344 domainInfo = removeOldOrderProducts(domainInfo, payload); 345 } 346 347 const item = parseSidebarProduct({ 348 type: payload.data?.status?.status, 349 item: payload.data, 350 }); 351 if (!item) { 352 return domainInfo; 353 } 354 355 if (payload.new_status === 'transfer_failed' && !domainInfo.failedDomains.some((entry) => entry.id === item.id)) { 356 domainInfo.failedDomains.push(item); 357 } 358 359 if ( 360 payload.new_status === 'awaiting_required_info' && 361 !domainInfo.extraDomains.some((entry) => entry.id === item.id) 362 ) { 363 domainInfo.extraDomains.push(item); 364 } 365 366 if (payload.new_status === 'processing' && !domainInfo.processDomains.some((entry) => entry.id === item.id)) { 367 domainInfo.processDomains.push(item); 368 } 369 370 return domainInfo; 371}; 372 373// Shared product decoding; each consumer owns its own data and stream lifecycle. 374const applySidebarProductEvent = (data, payload) => { 375 if (!payload || typeof payload !== 'object') return data; 376 switch (payload.type) { 377 case PRODUCT_TYPES.DOMAIN_NAME: 378 return updateDomainNames(data, payload); 379 case PRODUCT_TYPES.EXTERNAL_DOMAIN_NAME: 380 return payload.data ? updateExternalDomains(data, payload) : data; 381 case PRODUCT_TYPES.ALL_IN_ONE_PLAN: 382 return payload.data ? updatePlans(data, payload) : data; 383 case PRODUCT_TYPES.ORDER_PRODUCT: 384 return updateOrderProducts(data, payload); 385 default: 386 return data; 387 } 388}; 389 390const resolveSidebarDomainName = async (fullDomainName, apiFetcher) => { 391 if (!String(fullDomainName || '').startsWith('xn--')) { 392 return fullDomainName; 393 } 394 395 if (!apiFetcher || typeof apiFetcher.postJson !== 'function') { 396 return fullDomainName; 397 } 398 399 try { 400 const response = await apiFetcher.postJson('/v2/domain_names/unicode', { 401 body: { 402 input: fullDomainName, 403 }, 404 credentials: 'include', 405 }); 406 return response?.unicode || fullDomainName; 407 } catch { 408 return fullDomainName; 409 } 410}; 411 412export { applySidebarProductEvent, createEmptyDomainInfo, resolveSidebarDomainName };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.