EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
moniker.js
Go to the documentation of this file.
1// services/moniker.js
2// Moniker Domain Registration API
3// Documentation: https://testapi.moniker.com
4
5const axios = require('axios');
6
7// Configure API credentials and base URL
8/**
9 *
10 */
11function getConfig() {
12 const isProduction = process.env.NODE_ENV === 'production';
13
14 // Moniker requires UserKey and ApiKey for authentication
15 const userKey = process.env.MONIKER_USER_KEY || 'monikeruser';
16 const apiKey = process.env.MONIKER_API_KEY || 'monikerapi';
17 const apiPassword = process.env.MONIKER_API_PASSWORD;
18 const baseURL = process.env.MONIKER_BASE_URL || 'https://testapi.moniker.com';
19
20 if (userKey === 'monikeruser' && apiKey === 'monikerapi') {
21 console.log('[Moniker] Using TEST API with default credentials');
22 } else if (isProduction) {
23 console.log('[Moniker] Using PRODUCTION API');
24 } else {
25 console.log('[Moniker] Using configured API credentials');
26 }
27
28 return {
29 baseURL,
30 userKey,
31 apiKey,
32 apiPassword
33 };
34}
35
36/**
37 * Make a request to the Moniker API
38 * @param {string} endpoint - API endpoint (e.g., 'Domain/Check')
39 * @param {object} params - Additional query parameters
40 * @returns {Promise<object>} - API response
41 */
42async function makeRequest(endpoint, params = {}) {
43 const config = getConfig();
44
45 try {
46 const requestParams = {
47 UserKey: config.userKey,
48 ApiKey: config.apiKey,
49 ...params
50 };
51
52 // Add ApiPassword if available (some endpoints may need it)
53 if (config.apiPassword) {
54 requestParams.ApiPassword = config.apiPassword;
55 }
56
57 const response = await axios.get(`${config.baseURL}/${endpoint}`, {
58 params: requestParams,
59 timeout: 10000
60 });
61
62 // Moniker API returns key=value pairs, one per line
63 // Parse this format into an object
64 const data = {};
65 const lines = response.data.split('\n');
66
67 for (const line of lines) {
68 const trimmed = line.trim();
69 if (trimmed && trimmed.includes('=')) {
70 const [key, ...valueParts] = trimmed.split('=');
71 data[key] = valueParts.join('='); // Rejoin in case value contains =
72 }
73 }
74
75 return data;
76 } catch (error) {
77 console.error(`[Moniker] API Error on ${endpoint}:`, error.message);
78 if (error.response) {
79 console.error('[Moniker] Response:', error.response.data);
80 }
81 throw error;
82 }
83}
84
85
86/**
87 * Check domain availability
88 * @param {string} domain - Domain name to check
89 * @returns {Promise<object>} - Availability info
90 */
91async function checkDomain(domain) {
92 try {
93 const result = await makeRequest('Domain/Check', {
94 Domain: domain
95 });
96
97 // Moniker API response fields:
98 // status=AVAILABLE or UNAVAILABLE
99 // domain=example.com
100 // price_ispremium=YES/NO
101 const available = result.status === 'AVAILABLE';
102
103 return {
104 domain: result.domain || domain,
105 available: available,
106 status: result.status || 'unknown',
107 isPremium: result.price_ispremium === 'YES',
108 minRegPeriod: result.minregperiod,
109 maxRegPeriod: result.maxregperiod,
110 price: null, // Pricing requires separate API call
111 currency: 'USD',
112 raw: result
113 };
114 } catch (error) {
115 console.error('[Moniker] Error checking domain:', error.message);
116 throw error;
117 }
118}
119
120/**
121 * Check multiple domains at once
122 * @param {Array<string>} domains - Array of domain names
123 * @returns {Promise<Array<object>>} - Array of availability info
124 */
125async function checkDomains(domains) {
126 try {
127 // Check domains sequentially for test API
128 const results = await Promise.all(
129 domains.map(domain => checkDomain(domain))
130 );
131 return results;
132 } catch (error) {
133 console.error('[Moniker] Error checking multiple domains:', error.message);
134 throw error;
135 }
136}
137
138/**
139 * Register a domain
140 * @param {object} params - Registration parameters
141 * @returns {Promise<object>} - Registration result
142 */
143async function registerDomain(params) {
144 const {
145 domain,
146 years = 1,
147 nameservers = [],
148 ownercontact,
149 admincontact,
150 techcontact,
151 billingcontact
152 } = params;
153
154 if (!ownercontact) {
155 throw new Error('Owner contact information is required');
156 }
157
158 try {
159 // Note: Test API may not support actual registration
160 // This is a placeholder for the production implementation
161 const result = await makeRequest('Domain/Register', {
162 Domain: domain,
163 Period: years,
164 // Add contact and nameserver parameters based on Moniker API docs
165 });
166
167 return {
168 domain: domain,
169 status: result.Status || 'pending',
170 registration_date: new Date().toISOString(),
171 expiration_date: new Date(Date.now() + (years * 365 * 24 * 60 * 60 * 1000)).toISOString(),
172 registrar: 'moniker',
173 raw: result
174 };
175 } catch (error) {
176 console.error('[Moniker] Error registering domain:', error.message);
177 throw error;
178 }
179}
180
181
182/**
183 * Get domain info
184 * @param {string} domain - Domain name
185 * @returns {Promise<object>} - Domain information
186 */
187async function getDomainInfo(domain) {
188 try {
189 const result = await makeRequest('Domain/Info', {
190 Domain: domain
191 });
192
193 return {
194 domain: domain,
195 status: result.Status || 'unknown',
196 registration_date: result.CreatedDate || null,
197 expiration_date: result.ExpirationDate || null,
198 nameservers: result.Nameservers || [],
199 registrar: 'moniker',
200 raw: result
201 };
202 } catch (error) {
203 console.error('[Moniker] Error getting domain info:', error.message);
204 throw error;
205 }
206}
207
208/**
209 * Update domain nameservers
210 * @param {string} domain - Domain name
211 * @param {Array<string>} nameservers - Array of nameserver hostnames
212 * @returns {Promise<object>} - Update result
213 */
214async function updateNameservers(domain, nameservers) {
215 try {
216 const result = await makeRequest('Domain/UpdateNameservers', {
217 Domain: domain,
218 Nameservers: nameservers.join(',')
219 });
220
221 return {
222 domain: domain,
223 nameservers: nameservers,
224 updated: true,
225 raw: result
226 };
227 } catch (error) {
228 console.error('[Moniker] Error updating nameservers:', error.message);
229 throw error;
230 }
231}
232
233/**
234 * Get DNS zone records
235 * @param {string} domain - Domain name
236 * @returns {Promise<Array>} - DNS records
237 */
238async function getDNSRecords(domain) {
239 try {
240 const result = await makeRequest('DNS/List', {
241 Domain: domain
242 });
243
244 // Convert API response to standard format
245 return result.Records || [];
246 } catch (error) {
247 console.error('[Moniker] Error getting DNS records:', error.message);
248 // Return empty array if zone doesn't exist
249 return [];
250 }
251}
252
253/**
254 * Update DNS zone record
255 * @param {string} domain - Domain name
256 * @param {object} record - DNS record
257 * @returns {Promise<object>} - Update result
258 */
259async function updateDNSRecord(domain, record) {
260 try {
261 const result = await makeRequest('DNS/Update', {
262 Domain: domain,
263 Type: record.type,
264 Name: record.name,
265 Value: record.value,
266 TTL: record.ttl || 3600,
267 Priority: record.priority
268 });
269
270 return {
271 domain: domain,
272 record: record,
273 updated: true,
274 raw: result
275 };
276 } catch (error) {
277 console.error('[Moniker] Error updating DNS record:', error.message);
278 throw error;
279 }
280}
281
282/**
283 * Transfer domain in
284 * @param {object} params - Transfer parameters
285 * @returns {Promise<object>} - Transfer result
286 */
287async function transferDomain(params) {
288 const {
289 domain,
290 authcode,
291 years = 1,
292 ownercontact
293 } = params;
294
295 if (!authcode) {
296 throw new Error('Authorization code (EPP code) is required for transfer');
297 }
298
299 try {
300 const result = await makeRequest('Domain/Transfer', {
301 Domain: domain,
302 AuthCode: authcode,
303 Period: years
304 });
305
306 return {
307 domain: domain,
308 status: 'transfer_pending',
309 registrar: 'moniker',
310 raw: result
311 };
312 } catch (error) {
313 console.error('[Moniker] Error transferring domain:', error.message);
314 throw error;
315 }
316}
317
318/**
319 * Renew domain
320 * @param {string} domain - Domain name
321 * @param {number} years - Years to renew for
322 * @returns {Promise<object>} - Renewal result
323 */
324async function renewDomain(domain, years = 1) {
325 try {
326 const result = await makeRequest('Domain/Renew', {
327 Domain: domain,
328 Period: years
329 });
330
331 return {
332 domain: domain,
333 renewed: true,
334 expiration_date: result.ExpirationDate || null,
335 raw: result
336 };
337 } catch (error) {
338 console.error('[Moniker] Error renewing domain:', error.message);
339 throw error;
340 }
341}
342
343/**
344 * Lock domain (enable transfer lock)
345 * @param {string} domain - Domain name
346 * @returns {Promise<object>} - Lock result
347 */
348async function lockDomain(domain) {
349 try {
350 const result = await makeRequest('Domain/SetLock', {
351 Domain: domain,
352 LockStatus: 'true'
353 });
354
355 return {
356 domain: domain,
357 locked: true,
358 success: true,
359 raw: result
360 };
361 } catch (error) {
362 console.error('[Moniker] Error locking domain:', error.message);
363 throw error;
364 }
365}
366
367/**
368 * Unlock domain (disable transfer lock)
369 * @param {string} domain - Domain name
370 * @returns {Promise<object>} - Unlock result
371 */
372async function unlockDomain(domain) {
373 try {
374 const result = await makeRequest('Domain/SetLock', {
375 Domain: domain,
376 LockStatus: 'false'
377 });
378
379 return {
380 domain: domain,
381 locked: false,
382 success: true,
383 raw: result
384 };
385 } catch (error) {
386 console.error('[Moniker] Error unlocking domain:', error.message);
387 throw error;
388 }
389}
390
391/**
392 * Get domain auth/transfer code (EPP code)
393 * @param {string} domain - Domain name
394 * @returns {Promise<object>} - Auth code result
395 */
396async function getAuthCode(domain) {
397 try {
398 const result = await makeRequest('Domain/GetAuthCode', {
399 Domain: domain
400 });
401
402 return {
403 domain: domain,
404 auth_code: result.AuthCode || result.EPPCode || null,
405 success: true,
406 raw: result
407 };
408 } catch (error) {
409 console.error('[Moniker] Error getting auth code:', error.message);
410 throw error;
411 }
412}
413
414/**
415 * Enable/disable auto-renew
416 * @param {string} domain - Domain name
417 * @param {boolean} enabled - Enable or disable auto-renew
418 * @returns {Promise<object>} - Auto-renew update result
419 */
420async function setAutoRenew(domain, enabled) {
421 try {
422 const result = await makeRequest('Domain/SetAutoRenew', {
423 Domain: domain,
424 AutoRenew: enabled ? 'true' : 'false'
425 });
426
427 return {
428 domain: domain,
429 auto_renew: enabled,
430 success: true,
431 raw: result
432 };
433 } catch (error) {
434 console.error('[Moniker] Error setting auto-renew:', error.message);
435 throw error;
436 }
437}
438
439/**
440 * Get domain contact information
441 * @param {string} domain - Domain name
442 * @returns {Promise<object>} - Contact information
443 */
444async function getContacts(domain) {
445 try {
446 const result = await makeRequest('Domain/GetContacts', {
447 Domain: domain
448 });
449
450 return {
451 domain: domain,
452 registrant: result.Registrant || null,
453 admin: result.Admin || null,
454 tech: result.Tech || null,
455 billing: result.Billing || null,
456 raw: result
457 };
458 } catch (error) {
459 console.error('[Moniker] Error getting contacts:', error.message);
460 throw error;
461 }
462}
463
464/**
465 * Get all domains in the Moniker account
466 * @returns {Promise<Array>} - List of all domains
467 */
468async function getAllDomains() {
469 try {
470 console.log('[Moniker] Fetching all domains from account');
471
472 // Moniker API endpoint to list all domains
473 const result = await makeRequest('Domain/GetDomains', {});
474
475 if (!result || !result.Domains) {
476 console.log('[Moniker] No domains found or unexpected response format');
477 return [];
478 }
479
480 // Handle both single domain (object) and multiple domains (array)
481 let domains = [];
482 if (Array.isArray(result.Domains.Domain)) {
483 domains = result.Domains.Domain;
484 } else if (result.Domains.Domain) {
485 domains = [result.Domains.Domain];
486 }
487
488 console.log(`[Moniker] Found ${domains.length} domains`);
489
490 // Map to consistent format with domain name
491 return domains.map(domain => ({
492 name: domain.Name || domain.DomainName,
493 status: domain.Status,
494 expiration_date: domain.ExpirationDate,
495 registration_date: domain.RegistrationDate,
496 auto_renew: domain.AutoRenew === 'true',
497 locked: domain.Locked === 'true',
498 raw: domain
499 }));
500 } catch (error) {
501 console.error('[Moniker] Error getting all domains:', error.message);
502 // Return empty array on error rather than throwing
503 return [];
504 }
505}
506
507module.exports = {
508 checkDomain,
509 checkDomains,
510 registerDomain,
511 getDomainInfo,
512 updateNameservers,
513 getDNSRecords,
514 updateDNSRecord,
515 transferDomain,
516 renewDomain,
517 lockDomain,
518 unlockDomain,
519 getAuthCode,
520 setAutoRenew,
521 getContacts,
522 getAllDomains
523};