@hasna/domains 0.0.21 → 0.0.22
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 +4 -3
- package/dist/cli/commands/provider.d.ts.map +1 -1
- package/dist/cli/commands/providers.d.ts.map +1 -1
- package/dist/cli/index.js +584 -112
- package/dist/db/domain-records.d.ts +2 -2
- package/dist/db/domain-records.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +520 -104
- package/dist/lib/brandsight.d.ts +46 -2
- package/dist/lib/brandsight.d.ts.map +1 -1
- package/dist/lib/capability.d.ts +5 -3
- package/dist/lib/capability.d.ts.map +1 -1
- package/dist/lib/cloudflare.d.ts +2 -2
- package/dist/lib/cloudflare.d.ts.map +1 -1
- package/dist/lib/godaddy.d.ts +4 -4
- package/dist/lib/registrar.d.ts +13 -3
- package/dist/lib/registrar.d.ts.map +1 -1
- package/dist/lib/route53.d.ts +2 -0
- package/dist/lib/route53.d.ts.map +1 -1
- package/dist/mcp/index.js +510 -91
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -3664,7 +3664,7 @@ function godaddyCapability(env = process.env) {
|
|
|
3664
3664
|
return {
|
|
3665
3665
|
configured,
|
|
3666
3666
|
gated: true,
|
|
3667
|
-
notes: configured ? "Credentials present;
|
|
3667
|
+
notes: configured ? "Credentials present; DNS/domain management may work with qualifying account access, but availability remains threshold-gated and direct automated purchase is not exposed here. Prefer Route53 for purchases." : "Not configured; GoDaddy production availability remains threshold-gated and DNS/domain management requires qualifying account access."
|
|
3668
3668
|
};
|
|
3669
3669
|
}
|
|
3670
3670
|
var GoDaddyApiError, _overriddenFetch = null, GODADDY_API_BASE = "https://api.godaddy.com";
|
|
@@ -34425,11 +34425,32 @@ var init_dist_es14 = __esm(() => {
|
|
|
34425
34425
|
});
|
|
34426
34426
|
|
|
34427
34427
|
// src/lib/route53.ts
|
|
34428
|
+
var exports_route53 = {};
|
|
34429
|
+
__export(exports_route53, {
|
|
34430
|
+
upsertRecords: () => upsertRecords,
|
|
34431
|
+
upsertRecord: () => upsertRecord,
|
|
34432
|
+
updateNameservers: () => updateNameservers2,
|
|
34433
|
+
registerDomain: () => registerDomain2,
|
|
34434
|
+
listRegisteredDomains: () => listRegisteredDomains,
|
|
34435
|
+
listRecords: () => listRecords,
|
|
34436
|
+
listHostedZones: () => listHostedZones,
|
|
34437
|
+
getRegistrationStatus: () => getRegistrationStatus,
|
|
34438
|
+
getHostedZone: () => getHostedZone,
|
|
34439
|
+
getDomainDetail: () => getDomainDetail,
|
|
34440
|
+
getConfig: () => getConfig2,
|
|
34441
|
+
findHostedZoneByDomain: () => findHostedZoneByDomain,
|
|
34442
|
+
deleteRecord: () => deleteRecord,
|
|
34443
|
+
deleteHostedZone: () => deleteHostedZone,
|
|
34444
|
+
createRoute53Provider: () => createRoute53Provider,
|
|
34445
|
+
createHostedZone: () => createHostedZone,
|
|
34446
|
+
checkAvailability: () => checkAvailability3
|
|
34447
|
+
});
|
|
34428
34448
|
function getConfig2() {
|
|
34429
34449
|
return {
|
|
34430
34450
|
region: process.env["AWS_REGION"] || "us-east-1",
|
|
34431
34451
|
accessKeyId: process.env["AWS_ACCESS_KEY_ID"],
|
|
34432
|
-
secretAccessKey: process.env["AWS_SECRET_ACCESS_KEY"]
|
|
34452
|
+
secretAccessKey: process.env["AWS_SECRET_ACCESS_KEY"],
|
|
34453
|
+
sessionToken: process.env["AWS_SESSION_TOKEN"]
|
|
34433
34454
|
};
|
|
34434
34455
|
}
|
|
34435
34456
|
function checkCredentials(cfg) {
|
|
@@ -34445,7 +34466,7 @@ function makeClients(config) {
|
|
|
34445
34466
|
const cfg = config ?? getConfig2();
|
|
34446
34467
|
checkCredentials(cfg);
|
|
34447
34468
|
const region = cfg.region || "us-east-1";
|
|
34448
|
-
const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey } : undefined;
|
|
34469
|
+
const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey, sessionToken: cfg.sessionToken } : undefined;
|
|
34449
34470
|
return {
|
|
34450
34471
|
route53: new Route53Client({ region, credentials }),
|
|
34451
34472
|
domains: new Route53DomainsClient({ region: "us-east-1", credentials })
|
|
@@ -34585,7 +34606,8 @@ async function listHostedZones(config) {
|
|
|
34585
34606
|
id: cleanZoneId(z2.Id ?? ""),
|
|
34586
34607
|
name: z2.Name ?? "",
|
|
34587
34608
|
record_count: z2.ResourceRecordSetCount ?? 0,
|
|
34588
|
-
comment: z2.Config?.Comment
|
|
34609
|
+
comment: z2.Config?.Comment,
|
|
34610
|
+
private_zone: z2.Config?.PrivateZone
|
|
34589
34611
|
});
|
|
34590
34612
|
}
|
|
34591
34613
|
marker = result.IsTruncated ? result.NextMarker : undefined;
|
|
@@ -34600,7 +34622,8 @@ async function getHostedZone(hostedZoneId, config) {
|
|
|
34600
34622
|
name: result.HostedZone?.Name ?? "",
|
|
34601
34623
|
record_count: result.HostedZone?.ResourceRecordSetCount ?? 0,
|
|
34602
34624
|
comment: result.HostedZone?.Config?.Comment,
|
|
34603
|
-
name_servers: result.DelegationSet?.NameServers ?? []
|
|
34625
|
+
name_servers: result.DelegationSet?.NameServers ?? [],
|
|
34626
|
+
private_zone: result.HostedZone?.Config?.PrivateZone
|
|
34604
34627
|
};
|
|
34605
34628
|
}
|
|
34606
34629
|
async function deleteHostedZone(hostedZoneId, config) {
|
|
@@ -34610,7 +34633,15 @@ async function deleteHostedZone(hostedZoneId, config) {
|
|
|
34610
34633
|
async function findHostedZoneByDomain(domain, config) {
|
|
34611
34634
|
const zones = await listHostedZones(config);
|
|
34612
34635
|
const normalized = domain.endsWith(".") ? domain : `${domain}.`;
|
|
34613
|
-
|
|
34636
|
+
const matches = zones.filter((z2) => z2.name === normalized);
|
|
34637
|
+
if (matches.length === 0)
|
|
34638
|
+
return null;
|
|
34639
|
+
const publicMatches = matches.filter((z2) => !z2.private_zone);
|
|
34640
|
+
const candidates = publicMatches.length > 0 ? publicMatches : matches;
|
|
34641
|
+
if (candidates.length > 1) {
|
|
34642
|
+
throw new Error(`Multiple Route 53 hosted zones found for ${domain}; specify hosted zone id`);
|
|
34643
|
+
}
|
|
34644
|
+
return candidates[0] ?? null;
|
|
34614
34645
|
}
|
|
34615
34646
|
function rrsToRecord(rrs) {
|
|
34616
34647
|
if (rrs.AliasTarget) {
|
|
@@ -34710,19 +34741,53 @@ function createRoute53Provider(config) {
|
|
|
34710
34741
|
const cfg = config ?? getConfig2();
|
|
34711
34742
|
const registerWithRoute53 = registerDomain2;
|
|
34712
34743
|
const updateRoute53Nameservers = updateNameservers2;
|
|
34744
|
+
async function listDomainInventory() {
|
|
34745
|
+
const byDomain = new Map;
|
|
34746
|
+
try {
|
|
34747
|
+
const registered = await listRegisteredDomains(cfg);
|
|
34748
|
+
for (const d3 of registered) {
|
|
34749
|
+
byDomain.set(d3.domain, {
|
|
34750
|
+
domain: d3.domain,
|
|
34751
|
+
registrar: "AWS Route 53",
|
|
34752
|
+
created: "",
|
|
34753
|
+
expires: d3.expiry,
|
|
34754
|
+
nameservers: [],
|
|
34755
|
+
status: "active",
|
|
34756
|
+
auto_renew: d3.auto_renew
|
|
34757
|
+
});
|
|
34758
|
+
}
|
|
34759
|
+
} catch (error) {
|
|
34760
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34761
|
+
if (!message.includes("route53domains:ListDomains") && !message.includes("AccessDenied")) {
|
|
34762
|
+
throw error;
|
|
34763
|
+
}
|
|
34764
|
+
}
|
|
34765
|
+
const zones = await listHostedZones(cfg);
|
|
34766
|
+
for (const z2 of zones) {
|
|
34767
|
+
const zone = z2.name_servers?.length ? z2 : await getHostedZone(z2.id, cfg).catch(() => z2);
|
|
34768
|
+
const domain = zone.name.replace(/\.$/, "");
|
|
34769
|
+
const nameservers = zone.name_servers ?? [];
|
|
34770
|
+
const existing = byDomain.get(domain);
|
|
34771
|
+
if (existing) {
|
|
34772
|
+
existing.nameservers = nameservers.length > 0 ? nameservers : existing.nameservers;
|
|
34773
|
+
continue;
|
|
34774
|
+
}
|
|
34775
|
+
byDomain.set(domain, {
|
|
34776
|
+
domain,
|
|
34777
|
+
registrar: "AWS Route 53 DNS",
|
|
34778
|
+
created: "",
|
|
34779
|
+
expires: "",
|
|
34780
|
+
nameservers,
|
|
34781
|
+
status: "active",
|
|
34782
|
+
auto_renew: false
|
|
34783
|
+
});
|
|
34784
|
+
}
|
|
34785
|
+
return Array.from(byDomain.values());
|
|
34786
|
+
}
|
|
34713
34787
|
return {
|
|
34714
34788
|
name: "route53",
|
|
34715
34789
|
async listDomains() {
|
|
34716
|
-
|
|
34717
|
-
return domains.map((d3) => ({
|
|
34718
|
-
domain: d3.domain,
|
|
34719
|
-
registrar: "AWS Route 53",
|
|
34720
|
-
created: "",
|
|
34721
|
-
expires: d3.expiry,
|
|
34722
|
-
nameservers: [],
|
|
34723
|
-
status: "active",
|
|
34724
|
-
auto_renew: d3.auto_renew
|
|
34725
|
-
}));
|
|
34790
|
+
return listDomainInventory();
|
|
34726
34791
|
},
|
|
34727
34792
|
async getDomainInfo(domain) {
|
|
34728
34793
|
const detail = await getDomainDetail(domain, cfg);
|
|
@@ -34791,7 +34856,7 @@ function createRoute53Provider(config) {
|
|
|
34791
34856
|
};
|
|
34792
34857
|
},
|
|
34793
34858
|
async syncToLocalDb(dbFns) {
|
|
34794
|
-
const domains = await
|
|
34859
|
+
const domains = await listDomainInventory();
|
|
34795
34860
|
let synced = 0;
|
|
34796
34861
|
let created = 0;
|
|
34797
34862
|
let updated = 0;
|
|
@@ -34800,20 +34865,39 @@ function createRoute53Provider(config) {
|
|
|
34800
34865
|
try {
|
|
34801
34866
|
const existing = dbFns.getDomainByName(d3.domain);
|
|
34802
34867
|
if (existing) {
|
|
34868
|
+
const existingRoute53 = existing.metadata["route53"];
|
|
34869
|
+
const staleDnsOnlyRegistrar = d3.registrar !== "AWS Route 53" && (existing.registrar === "AWS Route 53 DNS" || existing.registrar === "AWS Route 53" && existingRoute53?.source === "route53:hosted_zones");
|
|
34803
34870
|
dbFns.updateDomain(existing.id, {
|
|
34804
|
-
registrar: "AWS Route 53",
|
|
34805
|
-
|
|
34871
|
+
...d3.registrar === "AWS Route 53" ? { registrar: "AWS Route 53" } : {},
|
|
34872
|
+
...staleDnsOnlyRegistrar ? { registrar: null } : {},
|
|
34873
|
+
expires_at: d3.expires || undefined,
|
|
34806
34874
|
auto_renew: d3.auto_renew,
|
|
34875
|
+
nameservers: d3.nameservers.length > 0 ? d3.nameservers : existing.nameservers,
|
|
34876
|
+
metadata: {
|
|
34877
|
+
...existing.metadata,
|
|
34878
|
+
route53: {
|
|
34879
|
+
source: d3.registrar === "AWS Route 53" ? "route53domains+hosted_zones" : "route53:hosted_zones",
|
|
34880
|
+
synced_at: new Date().toISOString()
|
|
34881
|
+
}
|
|
34882
|
+
},
|
|
34807
34883
|
status: "active"
|
|
34808
34884
|
});
|
|
34809
34885
|
updated++;
|
|
34810
34886
|
} else {
|
|
34811
34887
|
dbFns.createDomain({
|
|
34812
34888
|
name: d3.domain,
|
|
34813
|
-
registrar: "AWS Route 53",
|
|
34814
|
-
expires_at: d3.
|
|
34889
|
+
...d3.registrar === "AWS Route 53" ? { registrar: "AWS Route 53" } : {},
|
|
34890
|
+
expires_at: d3.expires || undefined,
|
|
34815
34891
|
auto_renew: d3.auto_renew,
|
|
34816
|
-
|
|
34892
|
+
nameservers: d3.nameservers,
|
|
34893
|
+
status: "active",
|
|
34894
|
+
notes: d3.registrar === "AWS Route 53 DNS" ? "Discovered from Route 53 hosted zones; registrar ownership was not inferred." : undefined,
|
|
34895
|
+
metadata: {
|
|
34896
|
+
route53: {
|
|
34897
|
+
source: d3.registrar === "AWS Route 53" ? "route53domains+hosted_zones" : "route53:hosted_zones",
|
|
34898
|
+
synced_at: new Date().toISOString()
|
|
34899
|
+
}
|
|
34900
|
+
}
|
|
34817
34901
|
});
|
|
34818
34902
|
created++;
|
|
34819
34903
|
}
|
|
@@ -35055,26 +35139,111 @@ async function listRecords2(zoneId, config) {
|
|
|
35055
35139
|
}
|
|
35056
35140
|
return records;
|
|
35057
35141
|
}
|
|
35058
|
-
async function
|
|
35059
|
-
const
|
|
35060
|
-
|
|
35061
|
-
|
|
35062
|
-
|
|
35063
|
-
|
|
35064
|
-
|
|
35065
|
-
|
|
35066
|
-
|
|
35067
|
-
|
|
35068
|
-
|
|
35069
|
-
|
|
35070
|
-
|
|
35071
|
-
|
|
35142
|
+
async function listRecordsByNameType(zoneId, type, name, config) {
|
|
35143
|
+
const result = await cfFetch(`/zones/${zoneId}/dns_records?type=${encodeURIComponent(type)}&name=${encodeURIComponent(name)}`, { config });
|
|
35144
|
+
return (result ?? []).map((r3) => ({
|
|
35145
|
+
id: r3.id,
|
|
35146
|
+
type: r3.type,
|
|
35147
|
+
name: r3.name,
|
|
35148
|
+
content: r3.content,
|
|
35149
|
+
ttl: r3.ttl,
|
|
35150
|
+
priority: r3.priority,
|
|
35151
|
+
proxied: r3.proxied
|
|
35152
|
+
}));
|
|
35153
|
+
}
|
|
35154
|
+
async function replaceRecordsByNameType(zoneId, records, config) {
|
|
35155
|
+
if (records.length === 0)
|
|
35156
|
+
return;
|
|
35157
|
+
const { type, name } = records[0];
|
|
35158
|
+
const existing = await listRecordsByNameType(zoneId, type, name, config);
|
|
35159
|
+
for (const record of existing) {
|
|
35160
|
+
if (record.id)
|
|
35161
|
+
await deleteRecord2(zoneId, record.id, config);
|
|
35162
|
+
}
|
|
35163
|
+
for (const record of records) {
|
|
35164
|
+
await cfFetch(`/zones/${zoneId}/dns_records`, {
|
|
35165
|
+
method: "POST",
|
|
35166
|
+
body: {
|
|
35167
|
+
type: record.type,
|
|
35168
|
+
name: record.name,
|
|
35169
|
+
content: record.content,
|
|
35170
|
+
ttl: record.ttl ?? 1,
|
|
35171
|
+
priority: record.priority,
|
|
35172
|
+
proxied: record.proxied ?? false
|
|
35173
|
+
},
|
|
35174
|
+
config
|
|
35175
|
+
});
|
|
35072
35176
|
}
|
|
35073
35177
|
}
|
|
35178
|
+
async function deleteRecord2(zoneId, recordId, config) {
|
|
35179
|
+
await cfFetch(`/zones/${zoneId}/dns_records/${recordId}`, { method: "DELETE", config });
|
|
35180
|
+
}
|
|
35181
|
+
function zoneToDomainInfo(zone) {
|
|
35182
|
+
return {
|
|
35183
|
+
domain: zone.name,
|
|
35184
|
+
registrar: "Cloudflare DNS",
|
|
35185
|
+
created: "",
|
|
35186
|
+
expires: "",
|
|
35187
|
+
nameservers: zone.nameservers,
|
|
35188
|
+
status: zone.status === "active" ? "active" : "discovered",
|
|
35189
|
+
auto_renew: false
|
|
35190
|
+
};
|
|
35191
|
+
}
|
|
35192
|
+
function withCloudflareMetadata(existing, zone) {
|
|
35193
|
+
return {
|
|
35194
|
+
...existing,
|
|
35195
|
+
cloudflare: {
|
|
35196
|
+
zone_id: zone.id,
|
|
35197
|
+
zone_status: zone.status,
|
|
35198
|
+
source: "cloudflare:zones",
|
|
35199
|
+
synced_at: new Date().toISOString()
|
|
35200
|
+
}
|
|
35201
|
+
};
|
|
35202
|
+
}
|
|
35074
35203
|
function createCloudflareProvider(config) {
|
|
35075
35204
|
const cfg = config ?? getConfig3();
|
|
35076
35205
|
return {
|
|
35077
35206
|
name: "cloudflare",
|
|
35207
|
+
async listDomains() {
|
|
35208
|
+
const zones = await listZones(cfg);
|
|
35209
|
+
return zones.map(zoneToDomainInfo);
|
|
35210
|
+
},
|
|
35211
|
+
async syncToLocalDb(dbFns) {
|
|
35212
|
+
const zones = await listZones(cfg);
|
|
35213
|
+
let synced = 0;
|
|
35214
|
+
let created = 0;
|
|
35215
|
+
let updated = 0;
|
|
35216
|
+
const errors3 = [];
|
|
35217
|
+
for (const zone of zones) {
|
|
35218
|
+
try {
|
|
35219
|
+
const info = zoneToDomainInfo(zone);
|
|
35220
|
+
const existing = dbFns.getDomainByName(zone.name);
|
|
35221
|
+
if (existing) {
|
|
35222
|
+
dbFns.updateDomain(existing.id, {
|
|
35223
|
+
...existing.registrar === "Cloudflare DNS" ? { registrar: null } : {},
|
|
35224
|
+
status: existing.status === "discovered" && info.status === "active" ? "active" : existing.status,
|
|
35225
|
+
nameservers: zone.nameservers,
|
|
35226
|
+
metadata: withCloudflareMetadata(existing.metadata, zone)
|
|
35227
|
+
});
|
|
35228
|
+
updated++;
|
|
35229
|
+
} else {
|
|
35230
|
+
dbFns.createDomain({
|
|
35231
|
+
name: zone.name,
|
|
35232
|
+
status: info.status === "active" ? "active" : "discovered",
|
|
35233
|
+
auto_renew: false,
|
|
35234
|
+
nameservers: zone.nameservers,
|
|
35235
|
+
notes: "Discovered from Cloudflare zones; registrar ownership was not inferred.",
|
|
35236
|
+
metadata: withCloudflareMetadata({}, zone)
|
|
35237
|
+
});
|
|
35238
|
+
created++;
|
|
35239
|
+
}
|
|
35240
|
+
synced++;
|
|
35241
|
+
} catch (err) {
|
|
35242
|
+
errors3.push(`${zone.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
35243
|
+
}
|
|
35244
|
+
}
|
|
35245
|
+
return { synced, created, updated, errors: errors3 };
|
|
35246
|
+
},
|
|
35078
35247
|
async getDnsRecords(domain) {
|
|
35079
35248
|
const zone = await getZone(domain, cfg);
|
|
35080
35249
|
if (!zone)
|
|
@@ -35092,8 +35261,15 @@ function createCloudflareProvider(config) {
|
|
|
35092
35261
|
const zone = await getZone(domain, cfg);
|
|
35093
35262
|
if (!zone)
|
|
35094
35263
|
throw new Error(`No Cloudflare zone found for ${domain}`);
|
|
35264
|
+
const grouped = new Map;
|
|
35095
35265
|
for (const r3 of records) {
|
|
35096
|
-
|
|
35266
|
+
const key = `${r3.type}|${r3.name}`;
|
|
35267
|
+
const existing = grouped.get(key) ?? [];
|
|
35268
|
+
existing.push({ type: r3.type, name: r3.name, content: r3.value, ttl: r3.ttl || 1, priority: r3.priority });
|
|
35269
|
+
grouped.set(key, existing);
|
|
35270
|
+
}
|
|
35271
|
+
for (const group of grouped.values()) {
|
|
35272
|
+
await replaceRecordsByNameType(zone.id, group, cfg);
|
|
35097
35273
|
}
|
|
35098
35274
|
return true;
|
|
35099
35275
|
}
|
|
@@ -35139,7 +35315,7 @@ function getApiKey() {
|
|
|
35139
35315
|
function getConfig4() {
|
|
35140
35316
|
return resolveBrandsightConfig();
|
|
35141
35317
|
}
|
|
35142
|
-
async function
|
|
35318
|
+
async function apiGet(path, apiKey, baseUrl = BRANDSIGHT_BASE) {
|
|
35143
35319
|
const fetchFn = _fetchFn || globalThis.fetch;
|
|
35144
35320
|
const url = `${baseUrl}${path}`;
|
|
35145
35321
|
const headers = {
|
|
@@ -35150,13 +35326,12 @@ async function apiRequest3(method, path, apiKey, body, baseUrl = BRANDSIGHT_BASE
|
|
|
35150
35326
|
};
|
|
35151
35327
|
try {
|
|
35152
35328
|
const response = await fetchFn(url, {
|
|
35153
|
-
method,
|
|
35329
|
+
method: "GET",
|
|
35154
35330
|
headers,
|
|
35155
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
35156
35331
|
signal: AbortSignal.timeout(15000)
|
|
35157
35332
|
});
|
|
35158
35333
|
if (!response.ok) {
|
|
35159
|
-
throw new BrandsightApiError(`Brandsight API
|
|
35334
|
+
throw new BrandsightApiError(`Brandsight API GET ${path} failed with status ${response.status}`, response.status, await response.text());
|
|
35160
35335
|
}
|
|
35161
35336
|
const data = await response.json();
|
|
35162
35337
|
return { data, stub: false };
|
|
@@ -35166,31 +35341,102 @@ async function apiRequest3(method, path, apiKey, body, baseUrl = BRANDSIGHT_BASE
|
|
|
35166
35341
|
return { data: null, stub: true };
|
|
35167
35342
|
}
|
|
35168
35343
|
}
|
|
35169
|
-
|
|
35170
|
-
const
|
|
35171
|
-
|
|
35172
|
-
|
|
35173
|
-
|
|
35344
|
+
function requireDomainConfig(config) {
|
|
35345
|
+
const cfg = config ?? getConfig4();
|
|
35346
|
+
if (!cfg.apiKey || !cfg.apiSecret || !cfg.customerId) {
|
|
35347
|
+
throw new BrandsightApiError("Brandsight Domain API credentials are not configured. Set BRANDSIGHT_API_KEY, BRANDSIGHT_API_SECRET, and BRANDSIGHT_CUSTOMER_ID (or HASNAXYZ_BRANDSIGHT_LIVE_* aliases).");
|
|
35348
|
+
}
|
|
35349
|
+
return cfg;
|
|
35350
|
+
}
|
|
35351
|
+
function domainBaseUrl(cfg) {
|
|
35352
|
+
return cfg.baseUrl ?? BRANDSIGHT_DOMAIN_BASE;
|
|
35353
|
+
}
|
|
35354
|
+
function domainHeaders(cfg) {
|
|
35355
|
+
return {
|
|
35356
|
+
Authorization: `sso-key ${cfg.apiKey}:${cfg.apiSecret}`,
|
|
35174
35357
|
"Content-Type": "application/json",
|
|
35175
35358
|
Accept: "application/json",
|
|
35176
35359
|
"User-Agent": USER_AGENT
|
|
35177
35360
|
};
|
|
35178
|
-
|
|
35179
|
-
|
|
35180
|
-
|
|
35181
|
-
|
|
35182
|
-
|
|
35183
|
-
|
|
35184
|
-
|
|
35185
|
-
|
|
35186
|
-
|
|
35187
|
-
|
|
35188
|
-
|
|
35189
|
-
|
|
35190
|
-
|
|
35191
|
-
throw error;
|
|
35192
|
-
return { data: null, stub: true };
|
|
35361
|
+
}
|
|
35362
|
+
async function domainApiRequest(method, path, config, body) {
|
|
35363
|
+
const cfg = requireDomainConfig(config);
|
|
35364
|
+
const fetchFn = _fetchFn || globalThis.fetch;
|
|
35365
|
+
const response = await fetchFn(`${domainBaseUrl(cfg)}${path}`, {
|
|
35366
|
+
method,
|
|
35367
|
+
headers: domainHeaders(cfg),
|
|
35368
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
35369
|
+
signal: AbortSignal.timeout(30000)
|
|
35370
|
+
});
|
|
35371
|
+
const text = await response.text();
|
|
35372
|
+
if (!response.ok) {
|
|
35373
|
+
throw new BrandsightApiError(`Brandsight Domain API ${method} ${path} failed with status ${response.status}`, response.status, text);
|
|
35193
35374
|
}
|
|
35375
|
+
if (!text.trim())
|
|
35376
|
+
return {};
|
|
35377
|
+
return JSON.parse(text);
|
|
35378
|
+
}
|
|
35379
|
+
function normalizeBrandsightDomain(raw) {
|
|
35380
|
+
const nameServers = raw.nameServers ?? raw.nameservers ?? [];
|
|
35381
|
+
const expiresAt = raw.expiresAt ?? raw.expires ?? "";
|
|
35382
|
+
const createdAt = raw.createdAt ?? raw.created ?? "";
|
|
35383
|
+
const renewAuto = raw.renewAuto ?? raw.auto_renew ?? false;
|
|
35384
|
+
return {
|
|
35385
|
+
...raw,
|
|
35386
|
+
domain: String(raw.domain ?? ""),
|
|
35387
|
+
status: String(raw.status ?? "UNKNOWN"),
|
|
35388
|
+
created: createdAt,
|
|
35389
|
+
expires: expiresAt,
|
|
35390
|
+
auto_renew: renewAuto,
|
|
35391
|
+
locked: Boolean(raw.locked),
|
|
35392
|
+
nameservers: nameServers,
|
|
35393
|
+
createdAt,
|
|
35394
|
+
expiresAt,
|
|
35395
|
+
nameServers,
|
|
35396
|
+
renewAuto
|
|
35397
|
+
};
|
|
35398
|
+
}
|
|
35399
|
+
function customerPath(cfg, path) {
|
|
35400
|
+
return `/customers/${encodeURIComponent(cfg.customerId)}${path}`;
|
|
35401
|
+
}
|
|
35402
|
+
function domainTld(domain) {
|
|
35403
|
+
const parts = domain.split(".").filter(Boolean);
|
|
35404
|
+
if (parts.length < 2)
|
|
35405
|
+
throw new BrandsightApiError(`Invalid domain name: ${domain}`);
|
|
35406
|
+
return parts.slice(1).join(".");
|
|
35407
|
+
}
|
|
35408
|
+
function brandsightContact(contact) {
|
|
35409
|
+
return {
|
|
35410
|
+
addressMailing: {
|
|
35411
|
+
address1: contact.address_line_1,
|
|
35412
|
+
city: contact.city,
|
|
35413
|
+
country: contact.country_code,
|
|
35414
|
+
postalCode: contact.zip_code,
|
|
35415
|
+
state: contact.state
|
|
35416
|
+
},
|
|
35417
|
+
email: contact.email,
|
|
35418
|
+
encoding: "ASCII",
|
|
35419
|
+
nameFirst: contact.first_name,
|
|
35420
|
+
nameLast: contact.last_name,
|
|
35421
|
+
organization: contact.organization_name,
|
|
35422
|
+
phone: contact.phone
|
|
35423
|
+
};
|
|
35424
|
+
}
|
|
35425
|
+
async function domainAvailability(domain, cfg, type, period = 1) {
|
|
35426
|
+
const params = new URLSearchParams({
|
|
35427
|
+
domain,
|
|
35428
|
+
period: String(period),
|
|
35429
|
+
type,
|
|
35430
|
+
optimizeFor: "ACCURACY"
|
|
35431
|
+
});
|
|
35432
|
+
const result = await domainApiRequest("GET", `/domains/available?${params.toString()}`, cfg);
|
|
35433
|
+
return {
|
|
35434
|
+
domain: result.domain ?? domain,
|
|
35435
|
+
available: Boolean(result.available),
|
|
35436
|
+
price: result.price,
|
|
35437
|
+
currency: result.currency,
|
|
35438
|
+
registryPremiumPricing: result.registryPremiumPricing
|
|
35439
|
+
};
|
|
35194
35440
|
}
|
|
35195
35441
|
function generateStubAlerts(brandName) {
|
|
35196
35442
|
const now2 = new Date().toISOString();
|
|
@@ -35244,32 +35490,160 @@ async function getThreatAssessment(domain) {
|
|
|
35244
35490
|
return { ...result.data, stub: false };
|
|
35245
35491
|
}
|
|
35246
35492
|
async function listDomains2(config) {
|
|
35247
|
-
const cfg = config
|
|
35248
|
-
const
|
|
35249
|
-
|
|
35250
|
-
|
|
35251
|
-
|
|
35493
|
+
const cfg = requireDomainConfig(config);
|
|
35494
|
+
const domains = [];
|
|
35495
|
+
const seenMarkers = new Set;
|
|
35496
|
+
let marker;
|
|
35497
|
+
while (true) {
|
|
35498
|
+
const params = new URLSearchParams({ limit: "500" });
|
|
35499
|
+
if (marker)
|
|
35500
|
+
params.set("marker", marker);
|
|
35501
|
+
const batch = await domainApiRequest("GET", customerPath(cfg, `/domains?${params.toString()}`), cfg);
|
|
35502
|
+
if (!Array.isArray(batch) || batch.length === 0)
|
|
35503
|
+
break;
|
|
35504
|
+
domains.push(...batch.map(normalizeBrandsightDomain).filter((d3) => d3.domain));
|
|
35505
|
+
if (batch.length < 500)
|
|
35506
|
+
break;
|
|
35507
|
+
const nextMarker = String(batch[batch.length - 1]?.domain ?? "");
|
|
35508
|
+
if (!nextMarker || seenMarkers.has(nextMarker))
|
|
35509
|
+
break;
|
|
35510
|
+
seenMarkers.add(nextMarker);
|
|
35511
|
+
marker = nextMarker;
|
|
35512
|
+
}
|
|
35513
|
+
return domains;
|
|
35252
35514
|
}
|
|
35253
35515
|
async function getDomainInfo3(domain, config) {
|
|
35254
|
-
const cfg = config
|
|
35255
|
-
const result = await
|
|
35256
|
-
|
|
35257
|
-
return null;
|
|
35258
|
-
return result.data;
|
|
35516
|
+
const cfg = requireDomainConfig(config);
|
|
35517
|
+
const result = await domainApiRequest("GET", customerPath(cfg, `/domains/${encodeURIComponent(domain)}`), cfg);
|
|
35518
|
+
return normalizeBrandsightDomain(result);
|
|
35259
35519
|
}
|
|
35260
35520
|
async function checkAvailability4(domain, config) {
|
|
35261
|
-
const cfg = config
|
|
35262
|
-
|
|
35263
|
-
if (result.stub)
|
|
35264
|
-
return { domain, available: false };
|
|
35265
|
-
return result.data;
|
|
35521
|
+
const cfg = requireDomainConfig(config);
|
|
35522
|
+
return domainAvailability(domain, cfg, "REGISTRATION", 1);
|
|
35266
35523
|
}
|
|
35267
35524
|
async function renewDomain3(domain, years = 1, config) {
|
|
35268
|
-
const cfg = config
|
|
35269
|
-
const
|
|
35270
|
-
if (
|
|
35271
|
-
|
|
35272
|
-
|
|
35525
|
+
const cfg = requireDomainConfig(config);
|
|
35526
|
+
const current = await getDomainInfo3(domain, cfg);
|
|
35527
|
+
if (!current?.expires)
|
|
35528
|
+
throw new BrandsightApiError(`Cannot renew ${domain}: current expiry is unavailable`);
|
|
35529
|
+
const quote = await domainAvailability(domain, cfg, "RENEWAL", years);
|
|
35530
|
+
const price = quote.price ?? current.renewal?.price;
|
|
35531
|
+
const currency = quote.currency ?? current.renewal?.currency;
|
|
35532
|
+
if (price == null || !currency) {
|
|
35533
|
+
throw new BrandsightApiError(`Cannot renew ${domain}: renewal quote did not include an exact price and currency`);
|
|
35534
|
+
}
|
|
35535
|
+
const result = await domainApiRequest("POST", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/renew`), cfg, {
|
|
35536
|
+
consent: {
|
|
35537
|
+
agreedAt: new Date().toISOString(),
|
|
35538
|
+
agreedBy: cfg.shopperId ?? "domains-cli",
|
|
35539
|
+
currency,
|
|
35540
|
+
price,
|
|
35541
|
+
registryPremiumPricing: quote.registryPremiumPricing ?? false
|
|
35542
|
+
},
|
|
35543
|
+
expires: current.expires,
|
|
35544
|
+
period: years
|
|
35545
|
+
});
|
|
35546
|
+
return { success: true, orderId: result.orderId ?? result.id };
|
|
35547
|
+
}
|
|
35548
|
+
async function getLegalAgreements(tld, privacy = false, config) {
|
|
35549
|
+
const cfg = requireDomainConfig(config);
|
|
35550
|
+
const params = new URLSearchParams({
|
|
35551
|
+
privacy: String(privacy),
|
|
35552
|
+
tlds: tld
|
|
35553
|
+
});
|
|
35554
|
+
return domainApiRequest("GET", customerPath(cfg, `/domains/agreements?${params.toString()}`), cfg);
|
|
35555
|
+
}
|
|
35556
|
+
async function getRegistrationSchema(tld, config) {
|
|
35557
|
+
const cfg = requireDomainConfig(config);
|
|
35558
|
+
return domainApiRequest("GET", customerPath(cfg, `/domains/register/schema/${encodeURIComponent(tld)}`), cfg);
|
|
35559
|
+
}
|
|
35560
|
+
async function validateRegistrationRequest(payload, config) {
|
|
35561
|
+
const cfg = requireDomainConfig(config);
|
|
35562
|
+
await domainApiRequest("POST", customerPath(cfg, "/domains/register/validate"), cfg, payload);
|
|
35563
|
+
return true;
|
|
35564
|
+
}
|
|
35565
|
+
async function registerBrandsightDomain(domain, contact, options = {}, config) {
|
|
35566
|
+
const cfg = requireDomainConfig(config);
|
|
35567
|
+
const period = options.years ?? 1;
|
|
35568
|
+
const availability = await domainAvailability(domain, cfg, "REGISTRATION", period);
|
|
35569
|
+
if (!availability.available)
|
|
35570
|
+
throw new BrandsightApiError(`${domain} is not available for registration`);
|
|
35571
|
+
const price = options.premiumPrice ?? availability.price;
|
|
35572
|
+
if (price == null || !availability.currency) {
|
|
35573
|
+
throw new BrandsightApiError(`Cannot register ${domain}: availability quote did not include an exact price and currency`);
|
|
35574
|
+
}
|
|
35575
|
+
const tld = domainTld(domain);
|
|
35576
|
+
const schema = await getRegistrationSchema(tld, cfg);
|
|
35577
|
+
const required = Array.isArray(schema["required"]) ? schema["required"] : [];
|
|
35578
|
+
if (required.includes("metadata") && !options.metadata) {
|
|
35579
|
+
throw new BrandsightApiError(`Cannot register ${domain}: ${tld} requires TLD-specific metadata; pass registration metadata before validation`);
|
|
35580
|
+
}
|
|
35581
|
+
const privacy = options.privacy ?? false;
|
|
35582
|
+
const agreements = await getLegalAgreements(tld, privacy, cfg);
|
|
35583
|
+
const agreementKeys = agreements.map((a3) => a3.agreementKey).filter(Boolean);
|
|
35584
|
+
const c3 = brandsightContact(contact);
|
|
35585
|
+
const payload = {
|
|
35586
|
+
consent: {
|
|
35587
|
+
agreedAt: new Date().toISOString(),
|
|
35588
|
+
agreedBy: contact.email || cfg.shopperId || "domains-cli",
|
|
35589
|
+
agreementKeys,
|
|
35590
|
+
currency: availability.currency,
|
|
35591
|
+
price,
|
|
35592
|
+
registryPremiumPricing: availability.registryPremiumPricing ?? !!options.premiumPrice
|
|
35593
|
+
},
|
|
35594
|
+
contacts: {
|
|
35595
|
+
admin: c3,
|
|
35596
|
+
billing: c3,
|
|
35597
|
+
registrant: c3,
|
|
35598
|
+
tech: c3
|
|
35599
|
+
},
|
|
35600
|
+
domain,
|
|
35601
|
+
metadata: options.metadata ?? {},
|
|
35602
|
+
nameServers: options.nameservers ?? [],
|
|
35603
|
+
period,
|
|
35604
|
+
privacy,
|
|
35605
|
+
renewAuto: options.autoRenew ?? true
|
|
35606
|
+
};
|
|
35607
|
+
await validateRegistrationRequest(payload, cfg);
|
|
35608
|
+
const result = await domainApiRequest("POST", customerPath(cfg, "/domains/register"), cfg, payload);
|
|
35609
|
+
return {
|
|
35610
|
+
success: true,
|
|
35611
|
+
orderId: result.orderId ?? result.id,
|
|
35612
|
+
operationId: result.operationId ?? result.id,
|
|
35613
|
+
chargedAmount: String(price)
|
|
35614
|
+
};
|
|
35615
|
+
}
|
|
35616
|
+
async function updateNameservers3(domain, nameservers, config) {
|
|
35617
|
+
const cfg = requireDomainConfig(config);
|
|
35618
|
+
const result = await domainApiRequest("PUT", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/nameServers`), cfg, { nameServers: nameservers });
|
|
35619
|
+
return { success: true, operationId: result.operationId ?? result.id };
|
|
35620
|
+
}
|
|
35621
|
+
async function getDnsRecords3(domain, config) {
|
|
35622
|
+
const cfg = requireDomainConfig(config);
|
|
35623
|
+
const records = [];
|
|
35624
|
+
let offset = 0;
|
|
35625
|
+
const limit = 1000;
|
|
35626
|
+
while (true) {
|
|
35627
|
+
const batch = await domainApiRequest("GET", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/records?offset=${offset}&limit=${limit}`), cfg);
|
|
35628
|
+
if (!Array.isArray(batch) || batch.length === 0)
|
|
35629
|
+
break;
|
|
35630
|
+
records.push(...batch);
|
|
35631
|
+
if (batch.length < limit)
|
|
35632
|
+
break;
|
|
35633
|
+
offset++;
|
|
35634
|
+
}
|
|
35635
|
+
return records;
|
|
35636
|
+
}
|
|
35637
|
+
function normalizeBrandsightDnsRecord(record) {
|
|
35638
|
+
return {
|
|
35639
|
+
...record,
|
|
35640
|
+
ttl: Math.max(record.ttl || 600, 600)
|
|
35641
|
+
};
|
|
35642
|
+
}
|
|
35643
|
+
async function setDnsRecords3(domain, records, config) {
|
|
35644
|
+
const cfg = requireDomainConfig(config);
|
|
35645
|
+
await domainApiRequest("PUT", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/records`), cfg, records.map(normalizeBrandsightDnsRecord));
|
|
35646
|
+
return true;
|
|
35273
35647
|
}
|
|
35274
35648
|
async function syncToLocalDb3(dbFns, config) {
|
|
35275
35649
|
const domains = await listDomains2(config);
|
|
@@ -35314,7 +35688,7 @@ function createBrandsightProvider(config) {
|
|
|
35314
35688
|
return domains.map((d3) => ({
|
|
35315
35689
|
domain: d3.domain,
|
|
35316
35690
|
registrar: "Brandsight",
|
|
35317
|
-
created: "",
|
|
35691
|
+
created: d3.created ?? "",
|
|
35318
35692
|
expires: d3.expires,
|
|
35319
35693
|
nameservers: d3.nameservers,
|
|
35320
35694
|
status: d3.status === "ACTIVE" ? "active" : d3.status.toLowerCase(),
|
|
@@ -35328,7 +35702,7 @@ function createBrandsightProvider(config) {
|
|
|
35328
35702
|
return {
|
|
35329
35703
|
domain: d3.domain,
|
|
35330
35704
|
registrar: "Brandsight",
|
|
35331
|
-
created: "",
|
|
35705
|
+
created: d3.created ?? "",
|
|
35332
35706
|
expires: d3.expires,
|
|
35333
35707
|
nameservers: d3.nameservers,
|
|
35334
35708
|
status: d3.status === "ACTIVE" ? "active" : d3.status.toLowerCase(),
|
|
@@ -35339,12 +35713,47 @@ function createBrandsightProvider(config) {
|
|
|
35339
35713
|
const result = await renewDomain3(domain, years, cfg);
|
|
35340
35714
|
return { domain, success: result.success, orderId: result.orderId };
|
|
35341
35715
|
},
|
|
35716
|
+
async registerDomain(domain, contact, options) {
|
|
35717
|
+
const result = await registerBrandsightDomain(domain, contact, options, cfg);
|
|
35718
|
+
return {
|
|
35719
|
+
domain,
|
|
35720
|
+
success: result.success,
|
|
35721
|
+
orderId: result.orderId,
|
|
35722
|
+
operationId: result.operationId,
|
|
35723
|
+
chargedAmount: result.chargedAmount
|
|
35724
|
+
};
|
|
35725
|
+
},
|
|
35726
|
+
async updateNameservers(domain, nameservers) {
|
|
35727
|
+
const result = await updateNameservers3(domain, nameservers, cfg);
|
|
35728
|
+
return { domain, success: result.success, operationId: result.operationId };
|
|
35729
|
+
},
|
|
35730
|
+
async getDnsRecords(domain) {
|
|
35731
|
+
const records = await getDnsRecords3(domain, cfg);
|
|
35732
|
+
return records.map((r3) => ({
|
|
35733
|
+
type: r3.type,
|
|
35734
|
+
name: r3.name,
|
|
35735
|
+
value: r3.data,
|
|
35736
|
+
ttl: r3.ttl,
|
|
35737
|
+
priority: r3.priority
|
|
35738
|
+
}));
|
|
35739
|
+
},
|
|
35740
|
+
async setDnsRecords(domain, records) {
|
|
35741
|
+
return setDnsRecords3(domain, records.map((r3) => ({
|
|
35742
|
+
type: r3.type,
|
|
35743
|
+
name: r3.name,
|
|
35744
|
+
data: r3.value,
|
|
35745
|
+
ttl: r3.ttl,
|
|
35746
|
+
priority: r3.priority
|
|
35747
|
+
})), cfg);
|
|
35748
|
+
},
|
|
35342
35749
|
async checkAvailability(domain) {
|
|
35343
35750
|
const result = await checkAvailability4(domain, cfg);
|
|
35344
35751
|
return {
|
|
35345
35752
|
domain: result.domain,
|
|
35346
35753
|
available: result.available,
|
|
35347
|
-
|
|
35754
|
+
is_premium: result.registryPremiumPricing,
|
|
35755
|
+
premium_price: result.registryPremiumPricing ? result.price : undefined,
|
|
35756
|
+
standard_price: result.registryPremiumPricing ? undefined : result.price,
|
|
35348
35757
|
currency: result.currency
|
|
35349
35758
|
};
|
|
35350
35759
|
},
|
|
@@ -35353,7 +35762,7 @@ function createBrandsightProvider(config) {
|
|
|
35353
35762
|
}
|
|
35354
35763
|
};
|
|
35355
35764
|
}
|
|
35356
|
-
var BrandsightApiError, _fetchFn = null, BRANDSIGHT_BASE = "https://api.brandsight.com/v1";
|
|
35765
|
+
var BrandsightApiError, _fetchFn = null, BRANDSIGHT_BASE = "https://api.brandsight.com/v1", BRANDSIGHT_DOMAIN_BASE = "https://api.godaddy.com/v2";
|
|
35357
35766
|
var init_brandsight = __esm(() => {
|
|
35358
35767
|
init_env_aliases();
|
|
35359
35768
|
init_version();
|
|
@@ -42048,6 +42457,7 @@ var providerRegistry = new Map([
|
|
|
42048
42457
|
configured: false,
|
|
42049
42458
|
envVars: providerEnvNames("namecheap")
|
|
42050
42459
|
},
|
|
42460
|
+
createInventory: createNamecheapProvider,
|
|
42051
42461
|
createRegistrar: createNamecheapProvider,
|
|
42052
42462
|
createDns: createNamecheapProvider
|
|
42053
42463
|
}],
|
|
@@ -42058,6 +42468,7 @@ var providerRegistry = new Map([
|
|
|
42058
42468
|
configured: false,
|
|
42059
42469
|
envVars: providerEnvNames("godaddy")
|
|
42060
42470
|
},
|
|
42471
|
+
createInventory: createGoDaddyProvider,
|
|
42061
42472
|
createRegistrar: createGoDaddyProvider,
|
|
42062
42473
|
createDns: createGoDaddyProvider
|
|
42063
42474
|
}],
|
|
@@ -42068,6 +42479,7 @@ var providerRegistry = new Map([
|
|
|
42068
42479
|
configured: false,
|
|
42069
42480
|
envVars: providerEnvNames("route53")
|
|
42070
42481
|
},
|
|
42482
|
+
createInventory: () => createRoute53Provider(),
|
|
42071
42483
|
createRegistrar: () => createRoute53Provider(),
|
|
42072
42484
|
createDns: () => createRoute53Provider()
|
|
42073
42485
|
}],
|
|
@@ -42078,16 +42490,19 @@ var providerRegistry = new Map([
|
|
|
42078
42490
|
configured: false,
|
|
42079
42491
|
envVars: providerEnvNames("cloudflare")
|
|
42080
42492
|
},
|
|
42493
|
+
createInventory: () => createCloudflareProvider(),
|
|
42081
42494
|
createDns: createCloudflareProvider
|
|
42082
42495
|
}],
|
|
42083
42496
|
["brandsight", {
|
|
42084
42497
|
info: {
|
|
42085
42498
|
name: "brandsight",
|
|
42086
|
-
type: "
|
|
42499
|
+
type: "full",
|
|
42087
42500
|
configured: false,
|
|
42088
42501
|
envVars: providerEnvNames("brandsight")
|
|
42089
42502
|
},
|
|
42090
|
-
|
|
42503
|
+
createInventory: createBrandsightProvider,
|
|
42504
|
+
createRegistrar: createBrandsightProvider,
|
|
42505
|
+
createDns: createBrandsightProvider
|
|
42091
42506
|
}],
|
|
42092
42507
|
["sedo", {
|
|
42093
42508
|
info: {
|
|
@@ -42104,18 +42519,28 @@ function isConfigured(providerName) {
|
|
|
42104
42519
|
function getAvailableProviders() {
|
|
42105
42520
|
return Array.from(providerRegistry.values()).map((e3) => ({
|
|
42106
42521
|
...e3.info,
|
|
42107
|
-
configured: isConfigured(e3.info.name)
|
|
42522
|
+
configured: isConfigured(e3.info.name),
|
|
42523
|
+
inventory: !!e3.createInventory
|
|
42108
42524
|
}));
|
|
42109
42525
|
}
|
|
42110
42526
|
function getProviderInfo(name) {
|
|
42111
42527
|
const entry = providerRegistry.get(name.toLowerCase());
|
|
42112
42528
|
if (!entry)
|
|
42113
42529
|
return null;
|
|
42114
|
-
return { ...entry.info, configured: isConfigured(entry.info.name) };
|
|
42530
|
+
return { ...entry.info, configured: isConfigured(entry.info.name), inventory: !!entry.createInventory };
|
|
42115
42531
|
}
|
|
42116
42532
|
function providerHasRegistrar(name) {
|
|
42117
42533
|
return !!providerRegistry.get(name.toLowerCase())?.createRegistrar;
|
|
42118
42534
|
}
|
|
42535
|
+
function providerHasInventory(name) {
|
|
42536
|
+
return !!providerRegistry.get(name.toLowerCase())?.createInventory;
|
|
42537
|
+
}
|
|
42538
|
+
function getDomainInventoryProvider(name) {
|
|
42539
|
+
const entry = providerRegistry.get(name.toLowerCase());
|
|
42540
|
+
if (!entry?.createInventory)
|
|
42541
|
+
throw new Error(`No domain inventory provider: ${name}`);
|
|
42542
|
+
return entry.createInventory();
|
|
42543
|
+
}
|
|
42119
42544
|
function getRegistrarProvider(name) {
|
|
42120
42545
|
const entry = providerRegistry.get(name.toLowerCase());
|
|
42121
42546
|
if (!entry?.createRegistrar)
|
|
@@ -42129,11 +42554,11 @@ function getDnsProvider(name) {
|
|
|
42129
42554
|
return entry.createDns();
|
|
42130
42555
|
}
|
|
42131
42556
|
async function syncAll(dbFns) {
|
|
42132
|
-
const available = getAvailableProviders().filter((p3) => p3.configured &&
|
|
42557
|
+
const available = getAvailableProviders().filter((p3) => p3.configured && providerHasInventory(p3.name));
|
|
42133
42558
|
const result = { providers: [], totalSynced: 0, totalErrors: [] };
|
|
42134
42559
|
for (const info of available) {
|
|
42135
42560
|
try {
|
|
42136
|
-
const provider =
|
|
42561
|
+
const provider = getDomainInventoryProvider(info.name);
|
|
42137
42562
|
const syncResult = await provider.syncToLocalDb(dbFns);
|
|
42138
42563
|
result.providers.push({ name: info.name, result: syncResult });
|
|
42139
42564
|
result.totalSynced += syncResult.synced;
|
|
@@ -42151,14 +42576,16 @@ function autoDetectRegistrar(domain, getDomainByName2) {
|
|
|
42151
42576
|
if (!dbDomain?.registrar)
|
|
42152
42577
|
return null;
|
|
42153
42578
|
const r3 = dbDomain.registrar.toLowerCase();
|
|
42579
|
+
if (r3.includes("cloudflare dns") || r3.includes("route 53 dns") || r3.includes("route53 dns"))
|
|
42580
|
+
return null;
|
|
42154
42581
|
if (r3.includes("namecheap"))
|
|
42155
42582
|
return "namecheap";
|
|
42156
42583
|
if (r3.includes("godaddy"))
|
|
42157
42584
|
return "godaddy";
|
|
42158
|
-
if (r3.includes("route 53") || r3.includes("route53")
|
|
42585
|
+
if (r3.includes("route 53") || r3.includes("route53"))
|
|
42159
42586
|
return "route53";
|
|
42160
42587
|
if (r3.includes("cloudflare"))
|
|
42161
|
-
return
|
|
42588
|
+
return null;
|
|
42162
42589
|
if (r3.includes("brandsight"))
|
|
42163
42590
|
return "brandsight";
|
|
42164
42591
|
return null;
|
|
@@ -42498,10 +42925,10 @@ WHOIS for ${result.domain} [${result.source}]:`);
|
|
|
42498
42925
|
process.exit(1);
|
|
42499
42926
|
});
|
|
42500
42927
|
domain.command("sync").description("Sync domains from a provider to the local DB").option("--provider <name>", "Provider name (default: all configured)").action(async (opts) => {
|
|
42501
|
-
const providers = opts.provider ? [opts.provider] : getAvailableProviders().filter((p3) => p3.configured && (p3.
|
|
42928
|
+
const providers = opts.provider ? [opts.provider] : getAvailableProviders().filter((p3) => p3.configured && providerHasInventory(p3.name)).map((p3) => p3.name);
|
|
42502
42929
|
for (const name of providers) {
|
|
42503
42930
|
try {
|
|
42504
|
-
const provider =
|
|
42931
|
+
const provider = getDomainInventoryProvider(name);
|
|
42505
42932
|
const result = await provider.syncToLocalDb({ getDomainByName, createDomain, updateDomain });
|
|
42506
42933
|
console.log(`\u2713 [${name}] Synced ${result.synced} (${result.created} new, ${result.updated} updated)`);
|
|
42507
42934
|
if (result.errors.length > 0)
|
|
@@ -43354,6 +43781,10 @@ function registerMonitorCommand(program2) {
|
|
|
43354
43781
|
}
|
|
43355
43782
|
|
|
43356
43783
|
// src/cli/commands/provider.ts
|
|
43784
|
+
function isAwsAccessDenied(error) {
|
|
43785
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
43786
|
+
return msg.includes("AccessDenied") || msg.includes("route53domains:ListDomains");
|
|
43787
|
+
}
|
|
43357
43788
|
function registerProviderCommand(program2) {
|
|
43358
43789
|
const provider = program2.command("provider").description("Configure and test registrar/DNS providers");
|
|
43359
43790
|
provider.command("list").description("Show all providers and their configuration status").option("-j, --json", "Output JSON").action((opts) => {
|
|
@@ -43367,7 +43798,8 @@ Registrar / DNS Providers:`);
|
|
|
43367
43798
|
for (const p3 of providers) {
|
|
43368
43799
|
const status = p3.configured ? "\u2713 configured" : "\u2717 not configured";
|
|
43369
43800
|
const type = p3.type === "full" ? "registrar + dns" : p3.type;
|
|
43370
|
-
|
|
43801
|
+
const capabilities = [type, p3.inventory ? "inventory" : null].filter(Boolean).join(", ");
|
|
43802
|
+
console.log(` ${p3.name.padEnd(12)} [${capabilities}] ${status}`);
|
|
43371
43803
|
if (!p3.configured) {
|
|
43372
43804
|
console.log(` Missing: ${p3.envVars.join(", ")}`);
|
|
43373
43805
|
}
|
|
@@ -43408,20 +43840,45 @@ Registrar / DNS Providers:`);
|
|
|
43408
43840
|
let registrarOk = null;
|
|
43409
43841
|
let dnsOk = null;
|
|
43410
43842
|
let marketplaceOk = null;
|
|
43843
|
+
const notes = [];
|
|
43411
43844
|
try {
|
|
43412
43845
|
if (info.type === "registrar" || info.type === "full") {
|
|
43413
|
-
|
|
43414
|
-
|
|
43415
|
-
|
|
43416
|
-
|
|
43417
|
-
|
|
43846
|
+
if (providerName === "route53") {
|
|
43847
|
+
try {
|
|
43848
|
+
const { listRegisteredDomains: listRegisteredDomains2 } = await Promise.resolve().then(() => (init_route53(), exports_route53));
|
|
43849
|
+
await listRegisteredDomains2();
|
|
43850
|
+
registrarOk = true;
|
|
43851
|
+
if (!opts.json)
|
|
43852
|
+
console.log("\u2713 Registrar connection OK");
|
|
43853
|
+
} catch (error) {
|
|
43854
|
+
if (!isAwsAccessDenied(error))
|
|
43855
|
+
throw error;
|
|
43856
|
+
registrarOk = false;
|
|
43857
|
+
notes.push("route53domains-listdomains-access-denied");
|
|
43858
|
+
if (!opts.json)
|
|
43859
|
+
console.log("\u2022 Route53 Domains registrar API is not available for these AWS credentials");
|
|
43860
|
+
}
|
|
43861
|
+
} else {
|
|
43862
|
+
const reg = getRegistrarProvider(providerName);
|
|
43863
|
+
await reg.listDomains();
|
|
43864
|
+
registrarOk = true;
|
|
43865
|
+
if (!opts.json)
|
|
43866
|
+
console.log("\u2713 Registrar connection OK");
|
|
43867
|
+
}
|
|
43418
43868
|
}
|
|
43419
43869
|
if (info.type === "dns" || info.type === "full") {
|
|
43420
|
-
|
|
43421
|
-
|
|
43422
|
-
|
|
43423
|
-
|
|
43424
|
-
|
|
43870
|
+
if (providerName === "brandsight" && registrarOk) {
|
|
43871
|
+
dnsOk = null;
|
|
43872
|
+
notes.push("dns-not-probed-with-synthetic-invalid-domain");
|
|
43873
|
+
if (!opts.json)
|
|
43874
|
+
console.log("\u2022 DNS not probed with synthetic invalid domain");
|
|
43875
|
+
} else {
|
|
43876
|
+
const dns = getDnsProvider(providerName);
|
|
43877
|
+
await dns.getDnsRecords("__test_nonexistent_domain__.invalid");
|
|
43878
|
+
dnsOk = true;
|
|
43879
|
+
if (!opts.json)
|
|
43880
|
+
console.log("\u2713 DNS connection OK");
|
|
43881
|
+
}
|
|
43425
43882
|
}
|
|
43426
43883
|
if (info.type === "marketplace") {
|
|
43427
43884
|
if (providerName !== "sedo")
|
|
@@ -43440,7 +43897,8 @@ Registrar / DNS Providers:`);
|
|
|
43440
43897
|
type: info.type,
|
|
43441
43898
|
registrar_ok: registrarOk,
|
|
43442
43899
|
dns_ok: dnsOk,
|
|
43443
|
-
marketplace_ok: marketplaceOk
|
|
43900
|
+
marketplace_ok: marketplaceOk,
|
|
43901
|
+
...notes.length > 0 ? { notes } : {}
|
|
43444
43902
|
}, null, 2));
|
|
43445
43903
|
}
|
|
43446
43904
|
} catch (e3) {
|
|
@@ -43455,7 +43913,8 @@ Registrar / DNS Providers:`);
|
|
|
43455
43913
|
registrar_ok: registrarOk,
|
|
43456
43914
|
dns_ok: true,
|
|
43457
43915
|
marketplace_ok: marketplaceOk,
|
|
43458
|
-
note: "connection-ok-no-domains-yet"
|
|
43916
|
+
note: "connection-ok-no-domains-yet",
|
|
43917
|
+
...notes.length > 0 ? { notes } : {}
|
|
43459
43918
|
}, null, 2));
|
|
43460
43919
|
} else {
|
|
43461
43920
|
console.log("\u2713 Connection OK (no domains yet)");
|
|
@@ -43487,6 +43946,18 @@ init_domains();
|
|
|
43487
43946
|
function registrarProviderNames() {
|
|
43488
43947
|
return getAvailableProviders().filter((p3) => providerHasRegistrar(p3.name)).map((p3) => p3.name).join(", ");
|
|
43489
43948
|
}
|
|
43949
|
+
function inventoryProviderNames() {
|
|
43950
|
+
return getAvailableProviders().filter((p3) => providerHasInventory(p3.name)).map((p3) => p3.name).join(", ");
|
|
43951
|
+
}
|
|
43952
|
+
function requireInventoryProvider(name) {
|
|
43953
|
+
const info = getProviderInfo(name);
|
|
43954
|
+
if (!info) {
|
|
43955
|
+
throw new Error(`Unknown provider: ${name}. Supported domain inventory providers: ${inventoryProviderNames()}`);
|
|
43956
|
+
}
|
|
43957
|
+
if (!providerHasInventory(name)) {
|
|
43958
|
+
throw new Error(`${name} is a ${info.type} provider without domain inventory sync. Supported domain inventory providers: ${inventoryProviderNames()}`);
|
|
43959
|
+
}
|
|
43960
|
+
}
|
|
43490
43961
|
function requireRegistrarProvider(name) {
|
|
43491
43962
|
const info = getProviderInfo(name);
|
|
43492
43963
|
if (!info) {
|
|
@@ -43505,14 +43976,15 @@ function registerProviderCommands(program2) {
|
|
|
43505
43976
|
console.log("Providers:");
|
|
43506
43977
|
for (const p3 of providers) {
|
|
43507
43978
|
const status = p3.configured ? "CONFIGURED" : "not configured";
|
|
43508
|
-
|
|
43979
|
+
const capabilities = [p3.type, p3.inventory ? "inventory" : null].filter(Boolean).join(", ");
|
|
43980
|
+
console.log(` ${p3.name} [${capabilities}]: ${status}`);
|
|
43509
43981
|
if (!p3.configured) {
|
|
43510
43982
|
console.log(` Accepted env: ${p3.envVars.join(", ")}`);
|
|
43511
43983
|
}
|
|
43512
43984
|
}
|
|
43513
43985
|
}
|
|
43514
43986
|
});
|
|
43515
|
-
program2.command("sync").description("Sync domains from a
|
|
43987
|
+
program2.command("sync").description("Sync domains from a domain inventory provider to local DB").option("--provider <provider>", "Provider name").option("--all", "Sync from all configured domain inventory providers").option("--json", "Output as JSON", false).action(async (opts) => {
|
|
43516
43988
|
if (opts.all) {
|
|
43517
43989
|
try {
|
|
43518
43990
|
const result = await syncAll({
|
|
@@ -43546,8 +44018,8 @@ function registerProviderCommands(program2) {
|
|
|
43546
44018
|
process.exit(1);
|
|
43547
44019
|
}
|
|
43548
44020
|
try {
|
|
43549
|
-
|
|
43550
|
-
const result = await
|
|
44021
|
+
requireInventoryProvider(provider);
|
|
44022
|
+
const result = await getDomainInventoryProvider(provider).syncToLocalDb({
|
|
43551
44023
|
getDomainByName,
|
|
43552
44024
|
createDomain,
|
|
43553
44025
|
updateDomain
|