@hasna/skills 0.1.18 → 0.1.19
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.
- package/README.md +25 -407
- package/bin/index.js +4260 -3040
- package/bin/mcp.js +4608 -3318
- package/package.json +3 -3
- package/skills/skill-academic-journal-matcher/bin/cli.ts +0 -34
- package/skills/skill-action-item-router/bin/cli.ts +0 -34
- package/skills/skill-ad-creative-generator/bin/cli.ts +0 -34
- package/skills/skill-advanced-math/bin/cli.ts +0 -34
- package/skills/skill-analyze-data/bin/cli.ts +0 -19
- package/skills/skill-anomaly-investigator/bin/cli.ts +0 -34
- package/skills/skill-api-test-suite/bin/cli.ts +0 -34
- package/skills/skill-apidocs/bin/cli.ts +0 -87
- package/skills/skill-audio-cleanup-lab/bin/cli.ts +0 -6
- package/skills/skill-audiobook-chapter-proofer/bin/cli.ts +0 -34
- package/skills/skill-banner-ad-suite/bin/cli.ts +0 -34
- package/skills/skill-benchmark-finder/bin/cli.ts +0 -34
- package/skills/skill-bio-sequence-tool/bin/cli.ts +0 -34
- package/skills/skill-blog-topic-cluster/bin/cli.ts +0 -34
- package/skills/skill-brand-style-guide/bin/cli.ts +0 -19
- package/skills/skill-brand-voice-audit/bin/cli.ts +0 -34
- package/skills/skill-budget-variance-analyzer/bin/cli.ts +0 -6
- package/skills/skill-businessactivity/bin/cli.ts +0 -28
- package/skills/skill-calendar-events/bin/cli.ts +0 -34
- package/skills/skill-campaign-metric-brief/bin/cli.ts +0 -34
- package/skills/skill-campaign-moodboard/bin/cli.ts +0 -34
- package/skills/skill-caption-style-stylist/bin/cli.ts +0 -34
- package/skills/skill-chemistry-calculator/bin/cli.ts +0 -34
- package/skills/skill-churn-risk-notifier/bin/cli.ts +0 -34
- package/skills/skill-citation-formatter/bin/cli.ts +0 -34
- package/skills/skill-classroom-newsletter-kit/bin/cli.ts +0 -34
- package/skills/skill-color-palette-harmonizer/bin/cli.ts +0 -34
- package/skills/skill-competitor-ad-analyzer/bin/cli.ts +0 -34
- package/skills/skill-compliance-copy-check/bin/cli.ts +0 -34
- package/skills/skill-compliance-report-pack/bin/cli.ts +0 -34
- package/skills/skill-compress-video/bin/cli.ts +0 -19
- package/skills/skill-consolelog/bin/cli.ts +0 -884
- package/skills/skill-contract-plainlanguage/bin/cli.ts +0 -34
- package/skills/skill-copytone-translator/bin/cli.ts +0 -34
- package/skills/skill-create-blog-article/bin/cli.ts +0 -34
- package/skills/skill-create-ebook/bin/cli.ts +0 -34
- package/skills/skill-crm-note-enhancer/bin/cli.ts +0 -34
- package/skills/skill-customer-journey-mapper/bin/cli.ts +0 -34
- package/skills/skill-dashboard-builder/bin/cli.ts +0 -34
- package/skills/skill-dashboard-narrator/bin/cli.ts +0 -34
- package/skills/skill-data-anonymizer/bin/cli.ts +0 -34
- package/skills/skill-database-explorer/bin/cli.ts +0 -34
- package/skills/skill-dataset-health-check/bin/cli.ts +0 -34
- package/skills/skill-decision-journal/bin/cli.ts +0 -34
- package/skills/skill-delegation-brief-writer/bin/cli.ts +0 -34
- package/skills/skill-destination-briefing/bin/cli.ts +0 -34
- package/skills/skill-diff-viewer/bin/cli.ts +0 -34
- package/skills/skill-domainpurchase/bin/cli.ts +0 -683
- package/skills/skill-domainsearch/bin/cli.ts +0 -410
- package/skills/skill-educational-resource-finder/bin/cli.ts +0 -34
- package/skills/skill-email-campaign/bin/cli.ts +0 -34
- package/skills/skill-exam-readiness-check/bin/cli.ts +0 -34
- package/skills/skill-experiment-power-calculator/bin/cli.ts +0 -34
- package/skills/skill-extract-audio/bin/cli.ts +0 -19
- package/skills/skill-extract-frames/bin/cli.ts +0 -34
- package/skills/skill-extract-invoice/bin/cli.ts +0 -34
- package/skills/skill-family-activity-curator/bin/cli.ts +0 -34
- package/skills/skill-faq-packager/bin/cli.ts +0 -34
- package/skills/skill-feedback-survey-designer/bin/cli.ts +0 -34
- package/skills/skill-field-trip-planner/bin/cli.ts +0 -34
- package/skills/skill-file-organizer/bin/cli.ts +0 -34
- package/skills/skill-folder-tree/bin/cli.ts +0 -34
- package/skills/skill-forecast-scenario-lab/bin/cli.ts +0 -34
- package/skills/skill-form-filler/bin/cli.ts +0 -34
- package/skills/skill-generate-api-client/bin/cli.ts +0 -34
- package/skills/skill-generate-book-cover/bin/cli.ts +0 -34
- package/skills/skill-generate-chart/bin/cli.ts +0 -34
- package/skills/skill-generate-diagram/bin/cli.ts +0 -34
- package/skills/skill-generate-dockerfile/bin/cli.ts +0 -34
- package/skills/skill-generate-documentation/bin/cli.ts +0 -34
- package/skills/skill-generate-docx/bin/cli.ts +0 -6
- package/skills/skill-generate-env/bin/cli.ts +0 -34
- package/skills/skill-generate-excel/bin/cli.ts +0 -34
- package/skills/skill-generate-favicon/bin/cli.ts +0 -34
- package/skills/skill-generate-mock-data/bin/cli.ts +0 -34
- package/skills/skill-generate-pdf/bin/cli.ts +0 -6
- package/skills/skill-generate-pr-description/bin/cli.ts +0 -34
- package/skills/skill-generate-presentation/bin/cli.ts +0 -34
- package/skills/skill-generate-qrcode/bin/cli.ts +0 -34
- package/skills/skill-generate-regex/bin/cli.ts +0 -34
- package/skills/skill-generate-resume/bin/cli.ts +0 -34
- package/skills/skill-generate-sitemap/bin/cli.ts +0 -34
- package/skills/skill-generate-social-posts/bin/cli.ts +0 -34
- package/skills/skill-generate-sql/bin/cli.ts +0 -34
- package/skills/skill-gif-maker/bin/cli.ts +0 -34
- package/skills/skill-github-manager/bin/cli.ts +0 -34
- package/skills/skill-gmail/bin/cli.ts +0 -34
- package/skills/skill-goal-quarterly-roadmap/bin/cli.ts +0 -34
- package/skills/skill-grant-application-drafter/bin/cli.ts +0 -34
- package/skills/skill-grocery-basket-optimizer/bin/cli.ts +0 -34
- package/skills/skill-guest-communication-suite/bin/cli.ts +0 -34
- package/skills/skill-habit-reflection-digest/bin/cli.ts +0 -34
- package/skills/skill-highlight-reel-generator/bin/cli.ts +0 -34
- package/skills/skill-homework-feedback-coach/bin/cli.ts +0 -34
- package/skills/skill-household-maintenance-mgr/bin/cli.ts +0 -34
- package/skills/skill-http-server/bin/cli.ts +0 -34
- package/skills/skill-implementation-agent/bin/cli.ts +0 -34
- package/skills/skill-implementation-plan/bin/cli.ts +0 -34
- package/skills/skill-implementation-todo/bin/cli.ts +0 -34
- package/skills/skill-inbox-priority-planner/bin/cli.ts +0 -34
- package/skills/skill-invoice/bin/cli.ts +0 -20
- package/skills/skill-invoice-dispute-helper/bin/cli.ts +0 -34
- package/skills/skill-itinerary-architect/bin/cli.ts +0 -34
- package/skills/skill-jingle-composer/bin/cli.ts +0 -34
- package/skills/skill-kpi-digest-generator/bin/cli.ts +0 -34
- package/skills/skill-lab-notebook-formatter/bin/cli.ts +0 -34
- package/skills/skill-landing-page-copy/bin/cli.ts +0 -34
- package/skills/skill-latex-table-generator/bin/cli.ts +0 -34
- package/skills/skill-learning-style-profiler/bin/cli.ts +0 -34
- package/skills/skill-lesson-plan-customizer/bin/cli.ts +0 -34
- package/skills/skill-livestream-runofshow/bin/cli.ts +0 -34
- package/skills/skill-longform-structurer/bin/cli.ts +0 -34
- package/skills/skill-lorem-generator/bin/cli.ts +0 -34
- package/skills/skill-managehook/bin/cli.ts +0 -241
- package/skills/skill-managemcp/bin/cli.ts +0 -241
- package/skills/skill-manageskill/bin/cli.ts +0 -241
- package/skills/skill-markdown-validator/bin/cli.ts +0 -34
- package/skills/skill-mcp-builder/bin/cli.ts +0 -34
- package/skills/skill-meal-plan-designer/bin/cli.ts +0 -34
- package/skills/skill-meeting-insight-summarizer/bin/cli.ts +0 -34
- package/skills/skill-merge-pdfs/bin/cli.ts +0 -34
- package/skills/skill-microcopy-generator/bin/cli.ts +0 -34
- package/skills/skill-mindfulness-prompt-cache/bin/cli.ts +0 -34
- package/skills/skill-notion-manager/bin/cli.ts +0 -34
- package/skills/skill-onboarding-sequence-builder/bin/cli.ts +0 -34
- package/skills/skill-onsite-ops-checklist/bin/cli.ts +0 -34
- package/skills/skill-outreach-cadence-designer/bin/cli.ts +0 -34
- package/skills/skill-packaging-concept-studio/bin/cli.ts +0 -34
- package/skills/skill-packing-plan-pro/bin/cli.ts +0 -34
- package/skills/skill-parent-teacher-brief/bin/cli.ts +0 -34
- package/skills/skill-partner-kit-assembler/bin/cli.ts +0 -34
- package/skills/skill-payroll-change-prepper/bin/cli.ts +0 -34
- package/skills/skill-persona-based-adwriter/bin/cli.ts +0 -34
- package/skills/skill-persona-generator/bin/cli.ts +0 -34
- package/skills/skill-personal-daily-ops/bin/cli.ts +0 -34
- package/skills/skill-pet-care-scheduler/bin/cli.ts +0 -34
- package/skills/skill-podcast-show-notes/bin/cli.ts +0 -34
- package/skills/skill-presentation-theme-maker/bin/cli.ts +0 -34
- package/skills/skill-press-release-drafter/bin/cli.ts +0 -34
- package/skills/skill-print-collateral-designer/bin/cli.ts +0 -34
- package/skills/skill-procurement-scorecard/bin/cli.ts +0 -34
- package/skills/skill-product-demo-script/bin/cli.ts +0 -34
- package/skills/skill-product-mockup/bin/cli.ts +0 -34
- package/skills/skill-project-retro-companion/bin/cli.ts +0 -34
- package/skills/skill-proposal-redline-advisor/bin/cli.ts +0 -34
- package/skills/skill-regex-tester/bin/cli.ts +0 -34
- package/skills/skill-remove-background/bin/cli.ts +0 -34
- package/skills/skill-risk-disclosure-kit/bin/cli.ts +0 -34
- package/skills/skill-roi-comparison-tool/bin/cli.ts +0 -34
- package/skills/skill-sales-call-recapper/bin/cli.ts +0 -34
- package/skills/skill-salescopy/bin/cli.ts +0 -20
- package/skills/skill-scaffold-project/bin/cli.ts +0 -34
- package/skills/skill-scholarship-tracker/bin/cli.ts +0 -34
- package/skills/skill-scientific-figure-check/bin/cli.ts +0 -34
- package/skills/skill-seating-chart-maker/bin/cli.ts +0 -34
- package/skills/skill-security-audit/bin/cli.ts +0 -34
- package/skills/skill-seo-brief-builder/bin/cli.ts +0 -34
- package/skills/skill-slack-assistant/bin/cli.ts +0 -34
- package/skills/skill-sleep-routine-analyzer/bin/cli.ts +0 -34
- package/skills/skill-social-media-kit/bin/cli.ts +0 -34
- package/skills/skill-split-pdf/bin/cli.ts +0 -34
- package/skills/skill-sponsorship-proposal-lab/bin/cli.ts +0 -34
- package/skills/skill-spreadsheet-cleanroom/bin/cli.ts +0 -34
- package/skills/skill-statistical-test-selector/bin/cli.ts +0 -34
- package/skills/skill-stress-relief-playbook/bin/cli.ts +0 -34
- package/skills/skill-study-guide-builder/bin/cli.ts +0 -34
- package/skills/skill-subscription-spend-watcher/bin/cli.ts +0 -34
- package/skills/skill-subtitle/bin/cli.ts +0 -20
- package/skills/skill-survey-insight-extractor/bin/cli.ts +0 -34
- package/skills/skill-terraform-generator/bin/cli.ts +0 -34
- package/skills/skill-testimonial-graphics/bin/cli.ts +0 -34
- package/skills/skill-timesheet/bin/cli.ts +0 -47
- package/skills/skill-travel-budget-balancer/bin/cli.ts +0 -34
- package/skills/skill-validate-config/bin/cli.ts +0 -34
- package/skills/skill-video-cut-suggester/bin/cli.ts +0 -34
- package/skills/skill-video-downloader/bin/cli.ts +0 -34
- package/skills/skill-video-thumbnail/bin/cli.ts +0 -34
- package/skills/skill-voiceover-casting-assistant/bin/cli.ts +0 -34
- package/skills/skill-watermark/bin/cli.ts +0 -34
- package/skills/skill-webcrawling/bin/cli.ts +0 -21
- package/skills/skill-webinar-script-coach/bin/cli.ts +0 -34
- package/skills/skill-wellness-progress-reporter/bin/cli.ts +0 -34
- package/skills/skill-workout-cycle-planner/bin/cli.ts +0 -34
|
@@ -1,683 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
import {
|
|
5
|
-
loadConfig,
|
|
6
|
-
saveConfig,
|
|
7
|
-
CONFIG_FILE,
|
|
8
|
-
getApiKey,
|
|
9
|
-
getApiSecret,
|
|
10
|
-
getCustomerId,
|
|
11
|
-
} from "../src/lib/config";
|
|
12
|
-
import { purchaseApi, domainApi, formatPrice, type Contact, type DomainPurchaseRequestV2 } from "../src/lib/api-client";
|
|
13
|
-
import { ensureInstalled } from "../src/lib/installer";
|
|
14
|
-
|
|
15
|
-
// Ensure service directory exists on startup
|
|
16
|
-
ensureInstalled();
|
|
17
|
-
|
|
18
|
-
const program = new Command();
|
|
19
|
-
|
|
20
|
-
program
|
|
21
|
-
.name("service-domainpurchase")
|
|
22
|
-
.description("CLI tool for purchasing and managing domains via Brandsight/GoDaddy API")
|
|
23
|
-
.version("1.0.0");
|
|
24
|
-
|
|
25
|
-
// ============ CONFIG COMMANDS ============
|
|
26
|
-
|
|
27
|
-
program
|
|
28
|
-
.command("config")
|
|
29
|
-
.description("Show or set configuration")
|
|
30
|
-
.option("--api-key <key>", "Set GoDaddy API key (direct mode)")
|
|
31
|
-
.option("--api-secret <secret>", "Set GoDaddy API secret (direct mode)")
|
|
32
|
-
.option("--customer-id <id>", "Set GoDaddy customer ID (direct mode)")
|
|
33
|
-
.option("--api-url <url>", "Set GoDaddy API URL (direct mode)")
|
|
34
|
-
.option("--use-remote <bool>", "Use remote server instead of direct API (true/false)")
|
|
35
|
-
.option("--remote-url <url>", "Set remote server URL")
|
|
36
|
-
.option("--remote-api-key <key>", "Set remote server API key")
|
|
37
|
-
.option("--show", "Show current configuration")
|
|
38
|
-
.action(async (options) => {
|
|
39
|
-
const config = loadConfig();
|
|
40
|
-
|
|
41
|
-
if (options.apiKey) {
|
|
42
|
-
saveConfig({ apiKey: options.apiKey });
|
|
43
|
-
console.log("API key saved");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (options.apiSecret) {
|
|
47
|
-
saveConfig({ apiSecret: options.apiSecret });
|
|
48
|
-
console.log("API secret saved");
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (options.customerId) {
|
|
52
|
-
saveConfig({ customerId: options.customerId });
|
|
53
|
-
console.log("Customer ID saved");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (options.apiUrl) {
|
|
57
|
-
saveConfig({ apiUrl: options.apiUrl });
|
|
58
|
-
console.log(`API URL set to: ${options.apiUrl}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (options.useRemote !== undefined) {
|
|
62
|
-
const useRemote = options.useRemote === "true";
|
|
63
|
-
saveConfig({ useRemoteServer: useRemote });
|
|
64
|
-
console.log(`Remote server mode: ${useRemote ? "ENABLED" : "DISABLED"}`);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (options.remoteUrl) {
|
|
68
|
-
saveConfig({ remoteServerUrl: options.remoteUrl });
|
|
69
|
-
console.log(`Remote server URL set to: ${options.remoteUrl}`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (options.remoteApiKey) {
|
|
73
|
-
saveConfig({ remoteApiKey: options.remoteApiKey });
|
|
74
|
-
console.log("Remote API key saved");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const hasOptions = options.apiKey || options.apiSecret || options.customerId ||
|
|
78
|
-
options.apiUrl || options.useRemote !== undefined ||
|
|
79
|
-
options.remoteUrl || options.remoteApiKey;
|
|
80
|
-
|
|
81
|
-
if (options.show || !hasOptions) {
|
|
82
|
-
const currentConfig = loadConfig();
|
|
83
|
-
console.log("\nConfiguration:");
|
|
84
|
-
console.log(` Config file: ${CONFIG_FILE}`);
|
|
85
|
-
console.log("");
|
|
86
|
-
console.log(" Mode: " + (currentConfig.useRemoteServer ? "REMOTE SERVER" : "DIRECT API"));
|
|
87
|
-
console.log("");
|
|
88
|
-
|
|
89
|
-
if (currentConfig.useRemoteServer) {
|
|
90
|
-
console.log(" Remote Server Settings:");
|
|
91
|
-
console.log(` URL: ${currentConfig.remoteServerUrl}`);
|
|
92
|
-
console.log(` API Key: ${currentConfig.remoteApiKey ? "***" + currentConfig.remoteApiKey.slice(-4) : "(auto from AWS)"}`);
|
|
93
|
-
} else {
|
|
94
|
-
console.log(" Direct API Settings:");
|
|
95
|
-
console.log(` API URL: ${currentConfig.apiUrl}`);
|
|
96
|
-
console.log(` API Key: ${currentConfig.apiKey ? "***" + currentConfig.apiKey.slice(-4) : "(not set)"}`);
|
|
97
|
-
console.log(` API Secret: ${currentConfig.apiSecret ? "***" + currentConfig.apiSecret.slice(-4) : "(not set)"}`);
|
|
98
|
-
console.log(` Customer ID: ${currentConfig.customerId || "(not set)"}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
console.log("\n Tip: Use --use-remote true to switch to remote server mode");
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// ============ CHECK COMMAND ============
|
|
106
|
-
|
|
107
|
-
program
|
|
108
|
-
.command("check <domain>")
|
|
109
|
-
.description("Check domain availability and pricing")
|
|
110
|
-
.option("--transfer", "Check for transfer instead of registration")
|
|
111
|
-
.option("--json", "Output as JSON")
|
|
112
|
-
.action(async (domain, options) => {
|
|
113
|
-
try {
|
|
114
|
-
const result = await domainApi.checkAvailability(domain, options.transfer);
|
|
115
|
-
|
|
116
|
-
if (options.json) {
|
|
117
|
-
console.log(JSON.stringify(result, null, 2));
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const status = result.available ? "AVAILABLE" : "TAKEN";
|
|
122
|
-
const price = result.price
|
|
123
|
-
? formatPrice(result.price, result.currency)
|
|
124
|
-
: "N/A";
|
|
125
|
-
const premium = result.registryPremiumPricing ? " [PREMIUM]" : "";
|
|
126
|
-
|
|
127
|
-
console.log(`\nDomain: ${domain}`);
|
|
128
|
-
console.log(`Status: ${status}`);
|
|
129
|
-
if (result.available) {
|
|
130
|
-
console.log(`Price: ${price}${premium}`);
|
|
131
|
-
console.log(`Period: ${result.period || 1} year(s)`);
|
|
132
|
-
}
|
|
133
|
-
} catch (error) {
|
|
134
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
135
|
-
process.exit(1);
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// ============ AGREEMENTS COMMAND ============
|
|
140
|
-
|
|
141
|
-
program
|
|
142
|
-
.command("agreements <tlds...>")
|
|
143
|
-
.description("Get legal agreements for TLDs (required before purchase)")
|
|
144
|
-
.option("--privacy", "Include privacy agreements")
|
|
145
|
-
.option("--json", "Output as JSON")
|
|
146
|
-
.action(async (tlds, options) => {
|
|
147
|
-
try {
|
|
148
|
-
const agreements = await domainApi.getAgreements(tlds, options.privacy);
|
|
149
|
-
|
|
150
|
-
if (options.json) {
|
|
151
|
-
console.log(JSON.stringify(agreements, null, 2));
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
console.log(`\nAgreements for: ${tlds.join(", ")}\n`);
|
|
156
|
-
|
|
157
|
-
for (const a of agreements) {
|
|
158
|
-
console.log(` [${a.agreementKey}] ${a.title}`);
|
|
159
|
-
console.log(` URL: ${a.url}\n`);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
console.log(`\nTotal: ${agreements.length} agreement(s)`);
|
|
163
|
-
console.log(`\nUse these agreement keys when purchasing domains.`);
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
166
|
-
process.exit(1);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// ============ VALIDATE COMMAND ============
|
|
171
|
-
|
|
172
|
-
program
|
|
173
|
-
.command("validate <domain>")
|
|
174
|
-
.description("Validate a domain purchase request (dry run)")
|
|
175
|
-
.option("--contact-json <path>", "Path to JSON file with contact info")
|
|
176
|
-
.option("--period <years>", "Registration period in years", "1")
|
|
177
|
-
.option("--privacy", "Enable WHOIS privacy")
|
|
178
|
-
.option("--auto-renew", "Enable auto renewal")
|
|
179
|
-
.option("--json", "Output as JSON")
|
|
180
|
-
.action(async (domain, options) => {
|
|
181
|
-
try {
|
|
182
|
-
// Check availability first to get price
|
|
183
|
-
console.log(`Checking availability for ${domain}...`);
|
|
184
|
-
const availability = await domainApi.checkAvailability(domain);
|
|
185
|
-
|
|
186
|
-
if (!availability.available) {
|
|
187
|
-
console.error(`\nError: ${domain} is not available for registration.`);
|
|
188
|
-
process.exit(1);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const price = availability.price || 0;
|
|
192
|
-
const currency = availability.currency || "USD";
|
|
193
|
-
console.log(`Domain available! Price: ${formatPrice(price, currency)}\n`);
|
|
194
|
-
|
|
195
|
-
// Get TLD from domain
|
|
196
|
-
const tld = domain.split(".").slice(1).join(".");
|
|
197
|
-
|
|
198
|
-
// Get agreements
|
|
199
|
-
console.log(`Fetching agreements for .${tld}...`);
|
|
200
|
-
const agreements = await domainApi.getAgreements([tld], options.privacy);
|
|
201
|
-
const agreementKeys = agreements.map((a) => a.agreementKey);
|
|
202
|
-
|
|
203
|
-
// Load contact info
|
|
204
|
-
let contact: Contact;
|
|
205
|
-
if (options.contactJson) {
|
|
206
|
-
const file = await Bun.file(options.contactJson);
|
|
207
|
-
contact = await file.json();
|
|
208
|
-
} else {
|
|
209
|
-
// Use placeholder contact for validation
|
|
210
|
-
contact = {
|
|
211
|
-
nameFirst: "Test",
|
|
212
|
-
nameLast: "User",
|
|
213
|
-
email: "test@example.com",
|
|
214
|
-
phone: "+1.5555555555",
|
|
215
|
-
addressMailing: {
|
|
216
|
-
address1: "123 Test St",
|
|
217
|
-
city: "Test City",
|
|
218
|
-
state: "CA",
|
|
219
|
-
postalCode: "90210",
|
|
220
|
-
country: "US",
|
|
221
|
-
},
|
|
222
|
-
encoding: "ASCII",
|
|
223
|
-
};
|
|
224
|
-
console.log("\nUsing placeholder contact info for validation.");
|
|
225
|
-
console.log("For actual purchase, provide --contact-json <path>\n");
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Ensure contact has encoding
|
|
229
|
-
if (!contact.encoding) {
|
|
230
|
-
contact.encoding = "ASCII";
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Get public IP for consent
|
|
234
|
-
const ipResponse = await fetch("https://api.ipify.org?format=json");
|
|
235
|
-
const ipData = await ipResponse.json() as { ip: string };
|
|
236
|
-
|
|
237
|
-
// Build V2 API request format with all contacts
|
|
238
|
-
const request: DomainPurchaseRequestV2 = {
|
|
239
|
-
domain,
|
|
240
|
-
consent: {
|
|
241
|
-
agreedAt: new Date().toISOString(),
|
|
242
|
-
agreedBy: ipData.ip,
|
|
243
|
-
agreementKeys,
|
|
244
|
-
price,
|
|
245
|
-
currency,
|
|
246
|
-
},
|
|
247
|
-
contacts: {
|
|
248
|
-
registrant: contact,
|
|
249
|
-
admin: contact,
|
|
250
|
-
billing: contact,
|
|
251
|
-
tech: contact,
|
|
252
|
-
},
|
|
253
|
-
period: parseInt(options.period),
|
|
254
|
-
privacy: options.privacy || false,
|
|
255
|
-
renewAuto: options.autoRenew || false,
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
console.log("Validating purchase request...\n");
|
|
259
|
-
const result = await domainApi.validatePurchase(request);
|
|
260
|
-
|
|
261
|
-
if (options.json) {
|
|
262
|
-
console.log(JSON.stringify(result, null, 2));
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (result.valid) {
|
|
267
|
-
console.log("Validation: PASSED");
|
|
268
|
-
console.log("\nThe domain purchase request is valid.");
|
|
269
|
-
console.log("Use the 'purchase' command to complete the purchase.");
|
|
270
|
-
} else {
|
|
271
|
-
console.log("Validation: FAILED");
|
|
272
|
-
console.log(`Status: ${result.status}`);
|
|
273
|
-
console.log(`Response: ${JSON.stringify(result.data, null, 2)}`);
|
|
274
|
-
}
|
|
275
|
-
} catch (error) {
|
|
276
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
277
|
-
process.exit(1);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// ============ PURCHASE COMMAND ============
|
|
282
|
-
|
|
283
|
-
program
|
|
284
|
-
.command("purchase <domain>")
|
|
285
|
-
.description("Purchase a domain")
|
|
286
|
-
.requiredOption("--contact-json <path>", "Path to JSON file with contact info")
|
|
287
|
-
.option("--period <years>", "Registration period in years", "1")
|
|
288
|
-
.option("--privacy", "Enable WHOIS privacy")
|
|
289
|
-
.option("--auto-renew", "Enable auto renewal")
|
|
290
|
-
.option("--nameservers <ns>", "Comma-separated nameservers (max 2)")
|
|
291
|
-
.option("--dry-run", "Validate only, don't actually purchase")
|
|
292
|
-
.option("--json", "Output as JSON")
|
|
293
|
-
.action(async (domain, options) => {
|
|
294
|
-
try {
|
|
295
|
-
// Check availability first
|
|
296
|
-
console.log(`Checking availability for ${domain}...`);
|
|
297
|
-
const availability = await domainApi.checkAvailability(domain);
|
|
298
|
-
|
|
299
|
-
if (!availability.available) {
|
|
300
|
-
console.error(`\nError: ${domain} is not available for registration.`);
|
|
301
|
-
process.exit(1);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const price = availability.price || 0;
|
|
305
|
-
const currency = availability.currency || "USD";
|
|
306
|
-
console.log(`Domain available! Price: ${formatPrice(price, currency)}\n`);
|
|
307
|
-
|
|
308
|
-
// Get TLD from domain
|
|
309
|
-
const tld = domain.split(".").slice(1).join(".");
|
|
310
|
-
|
|
311
|
-
// Get agreements
|
|
312
|
-
console.log(`Fetching agreements for .${tld}...`);
|
|
313
|
-
const agreements = await domainApi.getAgreements([tld], options.privacy);
|
|
314
|
-
const agreementKeys = agreements.map((a) => a.agreementKey);
|
|
315
|
-
console.log(`Found ${agreements.length} agreement(s)\n`);
|
|
316
|
-
|
|
317
|
-
// Load contact info
|
|
318
|
-
const contactFile = await Bun.file(options.contactJson);
|
|
319
|
-
const contact: Contact = await contactFile.json();
|
|
320
|
-
|
|
321
|
-
// Ensure contact has encoding
|
|
322
|
-
if (!contact.encoding) {
|
|
323
|
-
contact.encoding = "ASCII";
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Get public IP for consent
|
|
327
|
-
const ipResponse = await fetch("https://api.ipify.org?format=json");
|
|
328
|
-
const ipData = await ipResponse.json() as { ip: string };
|
|
329
|
-
|
|
330
|
-
// Build V2 API request format with all contacts
|
|
331
|
-
const request: DomainPurchaseRequestV2 = {
|
|
332
|
-
domain,
|
|
333
|
-
consent: {
|
|
334
|
-
agreedAt: new Date().toISOString(),
|
|
335
|
-
agreedBy: ipData.ip,
|
|
336
|
-
agreementKeys,
|
|
337
|
-
price,
|
|
338
|
-
currency,
|
|
339
|
-
},
|
|
340
|
-
contacts: {
|
|
341
|
-
registrant: contact,
|
|
342
|
-
admin: contact,
|
|
343
|
-
billing: contact,
|
|
344
|
-
tech: contact,
|
|
345
|
-
},
|
|
346
|
-
period: parseInt(options.period),
|
|
347
|
-
privacy: options.privacy || false,
|
|
348
|
-
renewAuto: options.autoRenew || false,
|
|
349
|
-
...(options.nameservers && {
|
|
350
|
-
nameServers: options.nameservers.split(",").map((ns: string) => ns.trim()).slice(0, 2),
|
|
351
|
-
}),
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
if (options.dryRun) {
|
|
355
|
-
console.log("Validating purchase request (dry run)...\n");
|
|
356
|
-
const result = await domainApi.validatePurchase(request);
|
|
357
|
-
|
|
358
|
-
if (options.json) {
|
|
359
|
-
console.log(JSON.stringify(result, null, 2));
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (result.valid) {
|
|
364
|
-
console.log("Validation: PASSED");
|
|
365
|
-
console.log("\nRemove --dry-run to complete the purchase.");
|
|
366
|
-
} else {
|
|
367
|
-
console.log("Validation: FAILED");
|
|
368
|
-
console.log(`Response: ${JSON.stringify(result.data, null, 2)}`);
|
|
369
|
-
}
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Actual purchase
|
|
374
|
-
console.log("Processing purchase...\n");
|
|
375
|
-
const result = await domainApi.purchaseDomain(request);
|
|
376
|
-
|
|
377
|
-
if (options.json) {
|
|
378
|
-
console.log(JSON.stringify(result, null, 2));
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
console.log("Purchase completed!");
|
|
383
|
-
console.log(`Domain: ${domain}`);
|
|
384
|
-
console.log(`Order ID: ${result.orderId || "N/A"}`);
|
|
385
|
-
console.log(`\nUse 'service-domainpurchase info ${domain}' to view details.`);
|
|
386
|
-
} catch (error) {
|
|
387
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
388
|
-
process.exit(1);
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// ============ LIST COMMAND ============
|
|
393
|
-
|
|
394
|
-
program
|
|
395
|
-
.command("list")
|
|
396
|
-
.description("List domains owned by your account")
|
|
397
|
-
.option("-l, --limit <count>", "Maximum domains to list", "100")
|
|
398
|
-
.option("--json", "Output as JSON")
|
|
399
|
-
.action(async (options) => {
|
|
400
|
-
try {
|
|
401
|
-
const domains = await domainApi.listOwnedDomains(parseInt(options.limit));
|
|
402
|
-
|
|
403
|
-
if (options.json) {
|
|
404
|
-
console.log(JSON.stringify(domains, null, 2));
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
console.log(`\nOwned Domains (${domains.length}):\n`);
|
|
409
|
-
|
|
410
|
-
for (const d of domains) {
|
|
411
|
-
const expires = d.expires
|
|
412
|
-
? new Date(d.expires).toLocaleDateString()
|
|
413
|
-
: "N/A";
|
|
414
|
-
const autoRenew = d.renewAuto ? "[AUTO]" : "";
|
|
415
|
-
const privacy = d.privacy ? "[PRIVATE]" : "";
|
|
416
|
-
console.log(
|
|
417
|
-
` ${d.domain.padEnd(35)} expires: ${expires} ${autoRenew} ${privacy}`
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
} catch (error) {
|
|
421
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
422
|
-
process.exit(1);
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
// ============ INFO COMMAND ============
|
|
427
|
-
|
|
428
|
-
program
|
|
429
|
-
.command("info <domain>")
|
|
430
|
-
.description("Get detailed information about an owned domain")
|
|
431
|
-
.option("--json", "Output as JSON")
|
|
432
|
-
.action(async (domain, options) => {
|
|
433
|
-
try {
|
|
434
|
-
const details = await domainApi.getDomainDetails(domain);
|
|
435
|
-
|
|
436
|
-
if (options.json) {
|
|
437
|
-
console.log(JSON.stringify(details, null, 2));
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
console.log(`\nDomain: ${details.domain}`);
|
|
442
|
-
console.log(`Status: ${details.status}`);
|
|
443
|
-
console.log(`Created: ${details.createdAt}`);
|
|
444
|
-
console.log(`Expires: ${details.expires}`);
|
|
445
|
-
console.log(`Auto Renew: ${details.renewAuto ? "Yes" : "No"}`);
|
|
446
|
-
console.log(`Privacy: ${details.privacy ? "Yes" : "No"}`);
|
|
447
|
-
|
|
448
|
-
if (details.nameServers?.length) {
|
|
449
|
-
console.log(`\nNameservers:`);
|
|
450
|
-
for (const ns of details.nameServers) {
|
|
451
|
-
console.log(` - ${ns}`);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (details.contactRegistrant) {
|
|
456
|
-
console.log(`\nRegistrant:`);
|
|
457
|
-
console.log(
|
|
458
|
-
` ${details.contactRegistrant.nameFirst} ${details.contactRegistrant.nameLast}`
|
|
459
|
-
);
|
|
460
|
-
console.log(` ${details.contactRegistrant.email}`);
|
|
461
|
-
}
|
|
462
|
-
} catch (error) {
|
|
463
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
464
|
-
process.exit(1);
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
// ============ UPDATE COMMAND ============
|
|
469
|
-
|
|
470
|
-
program
|
|
471
|
-
.command("update <domain>")
|
|
472
|
-
.description("Update domain settings")
|
|
473
|
-
.option("--auto-renew <bool>", "Enable/disable auto renewal (true/false)")
|
|
474
|
-
.option("--privacy <bool>", "Enable/disable WHOIS privacy (true/false)")
|
|
475
|
-
.option("--nameservers <ns>", "Comma-separated nameservers")
|
|
476
|
-
.option("--json", "Output as JSON")
|
|
477
|
-
.action(async (domain, options) => {
|
|
478
|
-
try {
|
|
479
|
-
const updates: any = {};
|
|
480
|
-
|
|
481
|
-
if (options.autoRenew !== undefined) {
|
|
482
|
-
updates.renewAuto = options.autoRenew === "true";
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
if (options.privacy !== undefined) {
|
|
486
|
-
updates.privacy = options.privacy === "true";
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
if (options.nameservers) {
|
|
490
|
-
updates.nameServers = options.nameservers
|
|
491
|
-
.split(",")
|
|
492
|
-
.map((ns: string) => ns.trim());
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
if (Object.keys(updates).length === 0) {
|
|
496
|
-
console.error("Error: No updates specified.");
|
|
497
|
-
console.log("\nOptions:");
|
|
498
|
-
console.log(" --auto-renew <true|false>");
|
|
499
|
-
console.log(" --privacy <true|false>");
|
|
500
|
-
console.log(" --nameservers <ns1,ns2,...>");
|
|
501
|
-
process.exit(1);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
console.log(`Updating ${domain}...`);
|
|
505
|
-
const result = await domainApi.updateDomain(domain, updates);
|
|
506
|
-
|
|
507
|
-
if (options.json) {
|
|
508
|
-
console.log(JSON.stringify(result, null, 2));
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
console.log("\nDomain updated successfully!");
|
|
513
|
-
console.log(`Applied changes: ${JSON.stringify(updates)}`);
|
|
514
|
-
} catch (error) {
|
|
515
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
516
|
-
process.exit(1);
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
// ============ RENEW COMMAND ============
|
|
521
|
-
|
|
522
|
-
program
|
|
523
|
-
.command("renew <domain>")
|
|
524
|
-
.description("Renew a domain registration")
|
|
525
|
-
.option("-p, --period <years>", "Renewal period in years", "1")
|
|
526
|
-
.option("--json", "Output as JSON")
|
|
527
|
-
.action(async (domain, options) => {
|
|
528
|
-
try {
|
|
529
|
-
console.log(`Renewing ${domain} for ${options.period} year(s)...`);
|
|
530
|
-
const result = await domainApi.renewDomain(domain, parseInt(options.period));
|
|
531
|
-
|
|
532
|
-
if (options.json) {
|
|
533
|
-
console.log(JSON.stringify(result, null, 2));
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
console.log("\nRenewal completed!");
|
|
538
|
-
console.log(`Domain: ${domain}`);
|
|
539
|
-
console.log(`Period: ${options.period} year(s)`);
|
|
540
|
-
} catch (error) {
|
|
541
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
542
|
-
process.exit(1);
|
|
543
|
-
}
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// ============ TRANSFER COMMAND ============
|
|
547
|
-
|
|
548
|
-
program
|
|
549
|
-
.command("transfer <domain>")
|
|
550
|
-
.description("Transfer a domain to your account")
|
|
551
|
-
.requiredOption("--auth-code <code>", "Authorization/EPP code from current registrar")
|
|
552
|
-
.requiredOption("--contact-json <path>", "Path to JSON file with contact info")
|
|
553
|
-
.option("--json", "Output as JSON")
|
|
554
|
-
.action(async (domain, options) => {
|
|
555
|
-
try {
|
|
556
|
-
// Get TLD from domain
|
|
557
|
-
const tld = domain.split(".").slice(1).join(".");
|
|
558
|
-
|
|
559
|
-
// Get agreements
|
|
560
|
-
console.log(`Fetching transfer agreements for .${tld}...`);
|
|
561
|
-
const agreements = await purchaseApi.getAgreements([tld], false);
|
|
562
|
-
const agreementKeys = agreements.map((a) => a.agreementKey);
|
|
563
|
-
|
|
564
|
-
// Load contact info
|
|
565
|
-
const contactFile = await Bun.file(options.contactJson);
|
|
566
|
-
const contact: Contact = await contactFile.json();
|
|
567
|
-
|
|
568
|
-
// Get public IP for consent
|
|
569
|
-
const ipResponse = await fetch("https://api.ipify.org?format=json");
|
|
570
|
-
const ipData = await ipResponse.json() as { ip: string };
|
|
571
|
-
|
|
572
|
-
const consent = {
|
|
573
|
-
agreedAt: new Date().toISOString(),
|
|
574
|
-
agreedBy: ipData.ip,
|
|
575
|
-
agreementKeys,
|
|
576
|
-
};
|
|
577
|
-
|
|
578
|
-
console.log(`Initiating transfer of ${domain}...`);
|
|
579
|
-
const result = await purchaseApi.initiateTransfer(
|
|
580
|
-
domain,
|
|
581
|
-
options.authCode,
|
|
582
|
-
consent,
|
|
583
|
-
contact
|
|
584
|
-
);
|
|
585
|
-
|
|
586
|
-
if (options.json) {
|
|
587
|
-
console.log(JSON.stringify(result, null, 2));
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
console.log("\nTransfer initiated!");
|
|
592
|
-
console.log(`Domain: ${domain}`);
|
|
593
|
-
console.log(
|
|
594
|
-
"\nNote: The transfer may take several days to complete."
|
|
595
|
-
);
|
|
596
|
-
console.log("Check your email for any required confirmations.");
|
|
597
|
-
} catch (error) {
|
|
598
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
599
|
-
process.exit(1);
|
|
600
|
-
}
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
// ============ CONTACT-TEMPLATE COMMAND ============
|
|
604
|
-
|
|
605
|
-
program
|
|
606
|
-
.command("contact-template")
|
|
607
|
-
.description("Generate a contact info JSON template")
|
|
608
|
-
.option("-o, --output <path>", "Output file path")
|
|
609
|
-
.action(async (options) => {
|
|
610
|
-
const template = {
|
|
611
|
-
nameFirst: "John",
|
|
612
|
-
nameLast: "Doe",
|
|
613
|
-
email: "john.doe@example.com",
|
|
614
|
-
phone: "+1.5551234567",
|
|
615
|
-
organization: "Example Corp",
|
|
616
|
-
addressMailing: {
|
|
617
|
-
address1: "123 Main Street",
|
|
618
|
-
address2: "Suite 100",
|
|
619
|
-
city: "San Francisco",
|
|
620
|
-
state: "CA",
|
|
621
|
-
postalCode: "94102",
|
|
622
|
-
country: "US",
|
|
623
|
-
},
|
|
624
|
-
encoding: "UTF-8",
|
|
625
|
-
};
|
|
626
|
-
|
|
627
|
-
const json = JSON.stringify(template, null, 2);
|
|
628
|
-
|
|
629
|
-
if (options.output) {
|
|
630
|
-
await Bun.write(options.output, json);
|
|
631
|
-
console.log(`Contact template saved to: ${options.output}`);
|
|
632
|
-
} else {
|
|
633
|
-
console.log("\nContact Info Template:\n");
|
|
634
|
-
console.log(json);
|
|
635
|
-
console.log("\nSave this to a file and use with --contact-json <path>");
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
// ============ SETUP COMMAND ============
|
|
640
|
-
|
|
641
|
-
program
|
|
642
|
-
.command("setup")
|
|
643
|
-
.description("Interactive setup for service-domainpurchase")
|
|
644
|
-
.action(async () => {
|
|
645
|
-
console.log("\nservice-domainpurchase Setup\n");
|
|
646
|
-
console.log("This will configure your Brandsight/GoDaddy API credentials.\n");
|
|
647
|
-
|
|
648
|
-
const config = loadConfig();
|
|
649
|
-
|
|
650
|
-
if (!config.apiKey || !config.apiSecret) {
|
|
651
|
-
console.log("API credentials not configured.\n");
|
|
652
|
-
console.log("Get your API key and secret from:");
|
|
653
|
-
console.log(" https://developer.godaddy.com/keys\n");
|
|
654
|
-
console.log("Then run:");
|
|
655
|
-
console.log(" service-domainpurchase config --api-key <key> --api-secret <secret>");
|
|
656
|
-
console.log(" service-domainpurchase config --customer-id <id>\n");
|
|
657
|
-
} else {
|
|
658
|
-
console.log(`API Key: ***${config.apiKey.slice(-4)}`);
|
|
659
|
-
console.log(`API Secret: ***${config.apiSecret.slice(-4)}`);
|
|
660
|
-
console.log(`Customer ID: ${config.customerId || "(not set)"}`);
|
|
661
|
-
console.log(`API URL: ${config.apiUrl}\n`);
|
|
662
|
-
|
|
663
|
-
// Test connection
|
|
664
|
-
console.log("Testing connection...");
|
|
665
|
-
try {
|
|
666
|
-
const domains = await domainApi.listOwnedDomains(5);
|
|
667
|
-
console.log(` Connected! Found ${domains.length} domains in your account.\n`);
|
|
668
|
-
|
|
669
|
-
console.log("Quick commands:");
|
|
670
|
-
console.log(" service-domainpurchase check example.com");
|
|
671
|
-
console.log(" service-domainpurchase list");
|
|
672
|
-
console.log(" service-domainpurchase contact-template -o contact.json");
|
|
673
|
-
console.log(" service-domainpurchase purchase example.com --contact-json contact.json --dry-run");
|
|
674
|
-
} catch (error) {
|
|
675
|
-
console.error(
|
|
676
|
-
" Connection failed:",
|
|
677
|
-
error instanceof Error ? error.message : error
|
|
678
|
-
);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
program.parse();
|