@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/index.js
CHANGED
|
@@ -35717,7 +35717,8 @@ function getConfig2() {
|
|
|
35717
35717
|
return {
|
|
35718
35718
|
region: process.env["AWS_REGION"] || "us-east-1",
|
|
35719
35719
|
accessKeyId: process.env["AWS_ACCESS_KEY_ID"],
|
|
35720
|
-
secretAccessKey: process.env["AWS_SECRET_ACCESS_KEY"]
|
|
35720
|
+
secretAccessKey: process.env["AWS_SECRET_ACCESS_KEY"],
|
|
35721
|
+
sessionToken: process.env["AWS_SESSION_TOKEN"]
|
|
35721
35722
|
};
|
|
35722
35723
|
}
|
|
35723
35724
|
function checkCredentials(cfg) {
|
|
@@ -35733,7 +35734,7 @@ function makeClients(config) {
|
|
|
35733
35734
|
const cfg = config ?? getConfig2();
|
|
35734
35735
|
checkCredentials(cfg);
|
|
35735
35736
|
const region = cfg.region || "us-east-1";
|
|
35736
|
-
const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey } : undefined;
|
|
35737
|
+
const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey, sessionToken: cfg.sessionToken } : undefined;
|
|
35737
35738
|
return {
|
|
35738
35739
|
route53: new Route53Client({ region, credentials }),
|
|
35739
35740
|
domains: new Route53DomainsClient({ region: "us-east-1", credentials })
|
|
@@ -35873,7 +35874,8 @@ async function listHostedZones(config) {
|
|
|
35873
35874
|
id: cleanZoneId(z2.Id ?? ""),
|
|
35874
35875
|
name: z2.Name ?? "",
|
|
35875
35876
|
record_count: z2.ResourceRecordSetCount ?? 0,
|
|
35876
|
-
comment: z2.Config?.Comment
|
|
35877
|
+
comment: z2.Config?.Comment,
|
|
35878
|
+
private_zone: z2.Config?.PrivateZone
|
|
35877
35879
|
});
|
|
35878
35880
|
}
|
|
35879
35881
|
marker = result.IsTruncated ? result.NextMarker : undefined;
|
|
@@ -35888,7 +35890,8 @@ async function getHostedZone(hostedZoneId, config) {
|
|
|
35888
35890
|
name: result.HostedZone?.Name ?? "",
|
|
35889
35891
|
record_count: result.HostedZone?.ResourceRecordSetCount ?? 0,
|
|
35890
35892
|
comment: result.HostedZone?.Config?.Comment,
|
|
35891
|
-
name_servers: result.DelegationSet?.NameServers ?? []
|
|
35893
|
+
name_servers: result.DelegationSet?.NameServers ?? [],
|
|
35894
|
+
private_zone: result.HostedZone?.Config?.PrivateZone
|
|
35892
35895
|
};
|
|
35893
35896
|
}
|
|
35894
35897
|
async function deleteHostedZone(hostedZoneId, config) {
|
|
@@ -35898,7 +35901,15 @@ async function deleteHostedZone(hostedZoneId, config) {
|
|
|
35898
35901
|
async function findHostedZoneByDomain(domain, config) {
|
|
35899
35902
|
const zones = await listHostedZones(config);
|
|
35900
35903
|
const normalized = domain.endsWith(".") ? domain : `${domain}.`;
|
|
35901
|
-
|
|
35904
|
+
const matches = zones.filter((z2) => z2.name === normalized);
|
|
35905
|
+
if (matches.length === 0)
|
|
35906
|
+
return null;
|
|
35907
|
+
const publicMatches = matches.filter((z2) => !z2.private_zone);
|
|
35908
|
+
const candidates = publicMatches.length > 0 ? publicMatches : matches;
|
|
35909
|
+
if (candidates.length > 1) {
|
|
35910
|
+
throw new Error(`Multiple Route 53 hosted zones found for ${domain}; specify hosted zone id`);
|
|
35911
|
+
}
|
|
35912
|
+
return candidates[0] ?? null;
|
|
35902
35913
|
}
|
|
35903
35914
|
function rrsToRecord(rrs) {
|
|
35904
35915
|
if (rrs.AliasTarget) {
|
|
@@ -35998,19 +36009,53 @@ function createRoute53Provider(config) {
|
|
|
35998
36009
|
const cfg = config ?? getConfig2();
|
|
35999
36010
|
const registerWithRoute53 = registerDomain2;
|
|
36000
36011
|
const updateRoute53Nameservers = updateNameservers2;
|
|
36012
|
+
async function listDomainInventory() {
|
|
36013
|
+
const byDomain = new Map;
|
|
36014
|
+
try {
|
|
36015
|
+
const registered = await listRegisteredDomains(cfg);
|
|
36016
|
+
for (const d3 of registered) {
|
|
36017
|
+
byDomain.set(d3.domain, {
|
|
36018
|
+
domain: d3.domain,
|
|
36019
|
+
registrar: "AWS Route 53",
|
|
36020
|
+
created: "",
|
|
36021
|
+
expires: d3.expiry,
|
|
36022
|
+
nameservers: [],
|
|
36023
|
+
status: "active",
|
|
36024
|
+
auto_renew: d3.auto_renew
|
|
36025
|
+
});
|
|
36026
|
+
}
|
|
36027
|
+
} catch (error) {
|
|
36028
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
36029
|
+
if (!message.includes("route53domains:ListDomains") && !message.includes("AccessDenied")) {
|
|
36030
|
+
throw error;
|
|
36031
|
+
}
|
|
36032
|
+
}
|
|
36033
|
+
const zones = await listHostedZones(cfg);
|
|
36034
|
+
for (const z2 of zones) {
|
|
36035
|
+
const zone = z2.name_servers?.length ? z2 : await getHostedZone(z2.id, cfg).catch(() => z2);
|
|
36036
|
+
const domain = zone.name.replace(/\.$/, "");
|
|
36037
|
+
const nameservers = zone.name_servers ?? [];
|
|
36038
|
+
const existing = byDomain.get(domain);
|
|
36039
|
+
if (existing) {
|
|
36040
|
+
existing.nameservers = nameservers.length > 0 ? nameservers : existing.nameservers;
|
|
36041
|
+
continue;
|
|
36042
|
+
}
|
|
36043
|
+
byDomain.set(domain, {
|
|
36044
|
+
domain,
|
|
36045
|
+
registrar: "AWS Route 53 DNS",
|
|
36046
|
+
created: "",
|
|
36047
|
+
expires: "",
|
|
36048
|
+
nameservers,
|
|
36049
|
+
status: "active",
|
|
36050
|
+
auto_renew: false
|
|
36051
|
+
});
|
|
36052
|
+
}
|
|
36053
|
+
return Array.from(byDomain.values());
|
|
36054
|
+
}
|
|
36001
36055
|
return {
|
|
36002
36056
|
name: "route53",
|
|
36003
36057
|
async listDomains() {
|
|
36004
|
-
|
|
36005
|
-
return domains.map((d3) => ({
|
|
36006
|
-
domain: d3.domain,
|
|
36007
|
-
registrar: "AWS Route 53",
|
|
36008
|
-
created: "",
|
|
36009
|
-
expires: d3.expiry,
|
|
36010
|
-
nameservers: [],
|
|
36011
|
-
status: "active",
|
|
36012
|
-
auto_renew: d3.auto_renew
|
|
36013
|
-
}));
|
|
36058
|
+
return listDomainInventory();
|
|
36014
36059
|
},
|
|
36015
36060
|
async getDomainInfo(domain) {
|
|
36016
36061
|
const detail = await getDomainDetail(domain, cfg);
|
|
@@ -36079,7 +36124,7 @@ function createRoute53Provider(config) {
|
|
|
36079
36124
|
};
|
|
36080
36125
|
},
|
|
36081
36126
|
async syncToLocalDb(dbFns) {
|
|
36082
|
-
const domains = await
|
|
36127
|
+
const domains = await listDomainInventory();
|
|
36083
36128
|
let synced = 0;
|
|
36084
36129
|
let created = 0;
|
|
36085
36130
|
let updated = 0;
|
|
@@ -36088,20 +36133,39 @@ function createRoute53Provider(config) {
|
|
|
36088
36133
|
try {
|
|
36089
36134
|
const existing = dbFns.getDomainByName(d3.domain);
|
|
36090
36135
|
if (existing) {
|
|
36136
|
+
const existingRoute53 = existing.metadata["route53"];
|
|
36137
|
+
const staleDnsOnlyRegistrar = d3.registrar !== "AWS Route 53" && (existing.registrar === "AWS Route 53 DNS" || existing.registrar === "AWS Route 53" && existingRoute53?.source === "route53:hosted_zones");
|
|
36091
36138
|
dbFns.updateDomain(existing.id, {
|
|
36092
|
-
registrar: "AWS Route 53",
|
|
36093
|
-
|
|
36139
|
+
...d3.registrar === "AWS Route 53" ? { registrar: "AWS Route 53" } : {},
|
|
36140
|
+
...staleDnsOnlyRegistrar ? { registrar: null } : {},
|
|
36141
|
+
expires_at: d3.expires || undefined,
|
|
36094
36142
|
auto_renew: d3.auto_renew,
|
|
36143
|
+
nameservers: d3.nameservers.length > 0 ? d3.nameservers : existing.nameservers,
|
|
36144
|
+
metadata: {
|
|
36145
|
+
...existing.metadata,
|
|
36146
|
+
route53: {
|
|
36147
|
+
source: d3.registrar === "AWS Route 53" ? "route53domains+hosted_zones" : "route53:hosted_zones",
|
|
36148
|
+
synced_at: new Date().toISOString()
|
|
36149
|
+
}
|
|
36150
|
+
},
|
|
36095
36151
|
status: "active"
|
|
36096
36152
|
});
|
|
36097
36153
|
updated++;
|
|
36098
36154
|
} else {
|
|
36099
36155
|
dbFns.createDomain({
|
|
36100
36156
|
name: d3.domain,
|
|
36101
|
-
registrar: "AWS Route 53",
|
|
36102
|
-
expires_at: d3.
|
|
36157
|
+
...d3.registrar === "AWS Route 53" ? { registrar: "AWS Route 53" } : {},
|
|
36158
|
+
expires_at: d3.expires || undefined,
|
|
36103
36159
|
auto_renew: d3.auto_renew,
|
|
36104
|
-
|
|
36160
|
+
nameservers: d3.nameservers,
|
|
36161
|
+
status: "active",
|
|
36162
|
+
notes: d3.registrar === "AWS Route 53 DNS" ? "Discovered from Route 53 hosted zones; registrar ownership was not inferred." : undefined,
|
|
36163
|
+
metadata: {
|
|
36164
|
+
route53: {
|
|
36165
|
+
source: d3.registrar === "AWS Route 53" ? "route53domains+hosted_zones" : "route53:hosted_zones",
|
|
36166
|
+
synced_at: new Date().toISOString()
|
|
36167
|
+
}
|
|
36168
|
+
}
|
|
36105
36169
|
});
|
|
36106
36170
|
created++;
|
|
36107
36171
|
}
|
|
@@ -36274,6 +36338,22 @@ async function cfFetch(path, opts = {}) {
|
|
|
36274
36338
|
}
|
|
36275
36339
|
return json.result;
|
|
36276
36340
|
}
|
|
36341
|
+
async function listZones(config) {
|
|
36342
|
+
const zones = [];
|
|
36343
|
+
let page = 1;
|
|
36344
|
+
while (true) {
|
|
36345
|
+
const result = await cfFetch(`/zones?per_page=50&page=${page}`, { config });
|
|
36346
|
+
if (!result || result.length === 0)
|
|
36347
|
+
break;
|
|
36348
|
+
for (const z2 of result) {
|
|
36349
|
+
zones.push({ id: z2.id, name: z2.name, status: z2.status, nameservers: z2.name_servers, original_nameservers: z2.original_name_servers });
|
|
36350
|
+
}
|
|
36351
|
+
if (result.length < 50)
|
|
36352
|
+
break;
|
|
36353
|
+
page++;
|
|
36354
|
+
}
|
|
36355
|
+
return zones;
|
|
36356
|
+
}
|
|
36277
36357
|
async function getZone(domain, config) {
|
|
36278
36358
|
const result = await cfFetch(`/zones?name=${encodeURIComponent(domain)}`, { config });
|
|
36279
36359
|
if (!result || result.length === 0)
|
|
@@ -36315,8 +36395,20 @@ async function listRecords2(zoneId, config) {
|
|
|
36315
36395
|
}
|
|
36316
36396
|
return records;
|
|
36317
36397
|
}
|
|
36398
|
+
async function listRecordsByNameType(zoneId, type, name, config) {
|
|
36399
|
+
const result = await cfFetch(`/zones/${zoneId}/dns_records?type=${encodeURIComponent(type)}&name=${encodeURIComponent(name)}`, { config });
|
|
36400
|
+
return (result ?? []).map((r3) => ({
|
|
36401
|
+
id: r3.id,
|
|
36402
|
+
type: r3.type,
|
|
36403
|
+
name: r3.name,
|
|
36404
|
+
content: r3.content,
|
|
36405
|
+
ttl: r3.ttl,
|
|
36406
|
+
priority: r3.priority,
|
|
36407
|
+
proxied: r3.proxied
|
|
36408
|
+
}));
|
|
36409
|
+
}
|
|
36318
36410
|
async function upsertRecord2(zoneId, record, config) {
|
|
36319
|
-
const existing = await
|
|
36411
|
+
const existing = await listRecordsByNameType(zoneId, record.type, record.name, config);
|
|
36320
36412
|
const body = {
|
|
36321
36413
|
type: record.type,
|
|
36322
36414
|
name: record.name,
|
|
@@ -36325,16 +36417,106 @@ async function upsertRecord2(zoneId, record, config) {
|
|
|
36325
36417
|
priority: record.priority,
|
|
36326
36418
|
proxied: record.proxied ?? false
|
|
36327
36419
|
};
|
|
36328
|
-
|
|
36329
|
-
|
|
36420
|
+
const sameRecord = existing.find((r3) => r3.content === record.content && (r3.priority ?? undefined) === (record.priority ?? undefined) && (r3.proxied ?? false) === (record.proxied ?? false));
|
|
36421
|
+
if (sameRecord?.id) {
|
|
36422
|
+
await cfFetch(`/zones/${zoneId}/dns_records/${sameRecord.id}`, { method: "PUT", body, config });
|
|
36330
36423
|
} else {
|
|
36331
36424
|
await cfFetch(`/zones/${zoneId}/dns_records`, { method: "POST", body, config });
|
|
36332
36425
|
}
|
|
36333
36426
|
}
|
|
36427
|
+
async function replaceRecordsByNameType(zoneId, records, config) {
|
|
36428
|
+
if (records.length === 0)
|
|
36429
|
+
return;
|
|
36430
|
+
const { type, name } = records[0];
|
|
36431
|
+
const existing = await listRecordsByNameType(zoneId, type, name, config);
|
|
36432
|
+
for (const record of existing) {
|
|
36433
|
+
if (record.id)
|
|
36434
|
+
await deleteRecord2(zoneId, record.id, config);
|
|
36435
|
+
}
|
|
36436
|
+
for (const record of records) {
|
|
36437
|
+
await cfFetch(`/zones/${zoneId}/dns_records`, {
|
|
36438
|
+
method: "POST",
|
|
36439
|
+
body: {
|
|
36440
|
+
type: record.type,
|
|
36441
|
+
name: record.name,
|
|
36442
|
+
content: record.content,
|
|
36443
|
+
ttl: record.ttl ?? 1,
|
|
36444
|
+
priority: record.priority,
|
|
36445
|
+
proxied: record.proxied ?? false
|
|
36446
|
+
},
|
|
36447
|
+
config
|
|
36448
|
+
});
|
|
36449
|
+
}
|
|
36450
|
+
}
|
|
36451
|
+
async function deleteRecord2(zoneId, recordId, config) {
|
|
36452
|
+
await cfFetch(`/zones/${zoneId}/dns_records/${recordId}`, { method: "DELETE", config });
|
|
36453
|
+
}
|
|
36454
|
+
function zoneToDomainInfo(zone) {
|
|
36455
|
+
return {
|
|
36456
|
+
domain: zone.name,
|
|
36457
|
+
registrar: "Cloudflare DNS",
|
|
36458
|
+
created: "",
|
|
36459
|
+
expires: "",
|
|
36460
|
+
nameservers: zone.nameservers,
|
|
36461
|
+
status: zone.status === "active" ? "active" : "discovered",
|
|
36462
|
+
auto_renew: false
|
|
36463
|
+
};
|
|
36464
|
+
}
|
|
36465
|
+
function withCloudflareMetadata(existing, zone) {
|
|
36466
|
+
return {
|
|
36467
|
+
...existing,
|
|
36468
|
+
cloudflare: {
|
|
36469
|
+
zone_id: zone.id,
|
|
36470
|
+
zone_status: zone.status,
|
|
36471
|
+
source: "cloudflare:zones",
|
|
36472
|
+
synced_at: new Date().toISOString()
|
|
36473
|
+
}
|
|
36474
|
+
};
|
|
36475
|
+
}
|
|
36334
36476
|
function createCloudflareProvider(config) {
|
|
36335
36477
|
const cfg = config ?? getConfig3();
|
|
36336
36478
|
return {
|
|
36337
36479
|
name: "cloudflare",
|
|
36480
|
+
async listDomains() {
|
|
36481
|
+
const zones = await listZones(cfg);
|
|
36482
|
+
return zones.map(zoneToDomainInfo);
|
|
36483
|
+
},
|
|
36484
|
+
async syncToLocalDb(dbFns) {
|
|
36485
|
+
const zones = await listZones(cfg);
|
|
36486
|
+
let synced = 0;
|
|
36487
|
+
let created = 0;
|
|
36488
|
+
let updated = 0;
|
|
36489
|
+
const errors = [];
|
|
36490
|
+
for (const zone of zones) {
|
|
36491
|
+
try {
|
|
36492
|
+
const info = zoneToDomainInfo(zone);
|
|
36493
|
+
const existing = dbFns.getDomainByName(zone.name);
|
|
36494
|
+
if (existing) {
|
|
36495
|
+
dbFns.updateDomain(existing.id, {
|
|
36496
|
+
...existing.registrar === "Cloudflare DNS" ? { registrar: null } : {},
|
|
36497
|
+
status: existing.status === "discovered" && info.status === "active" ? "active" : existing.status,
|
|
36498
|
+
nameservers: zone.nameservers,
|
|
36499
|
+
metadata: withCloudflareMetadata(existing.metadata, zone)
|
|
36500
|
+
});
|
|
36501
|
+
updated++;
|
|
36502
|
+
} else {
|
|
36503
|
+
dbFns.createDomain({
|
|
36504
|
+
name: zone.name,
|
|
36505
|
+
status: info.status === "active" ? "active" : "discovered",
|
|
36506
|
+
auto_renew: false,
|
|
36507
|
+
nameservers: zone.nameservers,
|
|
36508
|
+
notes: "Discovered from Cloudflare zones; registrar ownership was not inferred.",
|
|
36509
|
+
metadata: withCloudflareMetadata({}, zone)
|
|
36510
|
+
});
|
|
36511
|
+
created++;
|
|
36512
|
+
}
|
|
36513
|
+
synced++;
|
|
36514
|
+
} catch (err) {
|
|
36515
|
+
errors.push(`${zone.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
36516
|
+
}
|
|
36517
|
+
}
|
|
36518
|
+
return { synced, created, updated, errors };
|
|
36519
|
+
},
|
|
36338
36520
|
async getDnsRecords(domain) {
|
|
36339
36521
|
const zone = await getZone(domain, cfg);
|
|
36340
36522
|
if (!zone)
|
|
@@ -36352,8 +36534,15 @@ function createCloudflareProvider(config) {
|
|
|
36352
36534
|
const zone = await getZone(domain, cfg);
|
|
36353
36535
|
if (!zone)
|
|
36354
36536
|
throw new Error(`No Cloudflare zone found for ${domain}`);
|
|
36537
|
+
const grouped = new Map;
|
|
36355
36538
|
for (const r3 of records) {
|
|
36356
|
-
|
|
36539
|
+
const key = `${r3.type}|${r3.name}`;
|
|
36540
|
+
const existing = grouped.get(key) ?? [];
|
|
36541
|
+
existing.push({ type: r3.type, name: r3.name, content: r3.value, ttl: r3.ttl || 1, priority: r3.priority });
|
|
36542
|
+
grouped.set(key, existing);
|
|
36543
|
+
}
|
|
36544
|
+
for (const group of grouped.values()) {
|
|
36545
|
+
await replaceRecordsByNameType(zone.id, group, cfg);
|
|
36357
36546
|
}
|
|
36358
36547
|
return true;
|
|
36359
36548
|
}
|
|
@@ -36390,87 +36579,259 @@ var _fetchFn = null;
|
|
|
36390
36579
|
function getConfig4() {
|
|
36391
36580
|
return resolveBrandsightConfig();
|
|
36392
36581
|
}
|
|
36393
|
-
var
|
|
36394
|
-
|
|
36395
|
-
const
|
|
36396
|
-
|
|
36397
|
-
|
|
36398
|
-
Authorization: `Bearer ${apiKey}`,
|
|
36399
|
-
"Content-Type": "application/json",
|
|
36400
|
-
Accept: "application/json",
|
|
36401
|
-
"User-Agent": USER_AGENT
|
|
36402
|
-
};
|
|
36403
|
-
try {
|
|
36404
|
-
const response = await fetchFn(url, {
|
|
36405
|
-
method,
|
|
36406
|
-
headers,
|
|
36407
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
36408
|
-
signal: AbortSignal.timeout(15000)
|
|
36409
|
-
});
|
|
36410
|
-
if (!response.ok) {
|
|
36411
|
-
throw new BrandsightApiError(`Brandsight API ${method} ${path} failed with status ${response.status}`, response.status, await response.text());
|
|
36412
|
-
}
|
|
36413
|
-
const data = await response.json();
|
|
36414
|
-
return { data, stub: false };
|
|
36415
|
-
} catch (error) {
|
|
36416
|
-
if (error instanceof BrandsightApiError)
|
|
36417
|
-
throw error;
|
|
36418
|
-
return { data: null, stub: true };
|
|
36582
|
+
var BRANDSIGHT_DOMAIN_BASE = "https://api.godaddy.com/v2";
|
|
36583
|
+
function requireDomainConfig(config) {
|
|
36584
|
+
const cfg = config ?? getConfig4();
|
|
36585
|
+
if (!cfg.apiKey || !cfg.apiSecret || !cfg.customerId) {
|
|
36586
|
+
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).");
|
|
36419
36587
|
}
|
|
36588
|
+
return cfg;
|
|
36420
36589
|
}
|
|
36421
|
-
|
|
36422
|
-
|
|
36423
|
-
|
|
36424
|
-
|
|
36425
|
-
|
|
36590
|
+
function domainBaseUrl(cfg) {
|
|
36591
|
+
return cfg.baseUrl ?? BRANDSIGHT_DOMAIN_BASE;
|
|
36592
|
+
}
|
|
36593
|
+
function domainHeaders(cfg) {
|
|
36594
|
+
return {
|
|
36595
|
+
Authorization: `sso-key ${cfg.apiKey}:${cfg.apiSecret}`,
|
|
36426
36596
|
"Content-Type": "application/json",
|
|
36427
36597
|
Accept: "application/json",
|
|
36428
36598
|
"User-Agent": USER_AGENT
|
|
36429
36599
|
};
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36436
|
-
|
|
36437
|
-
|
|
36438
|
-
|
|
36439
|
-
|
|
36440
|
-
|
|
36441
|
-
|
|
36442
|
-
|
|
36443
|
-
throw error;
|
|
36444
|
-
return { data: null, stub: true };
|
|
36600
|
+
}
|
|
36601
|
+
async function domainApiRequest(method, path, config, body) {
|
|
36602
|
+
const cfg = requireDomainConfig(config);
|
|
36603
|
+
const fetchFn = _fetchFn || globalThis.fetch;
|
|
36604
|
+
const response = await fetchFn(`${domainBaseUrl(cfg)}${path}`, {
|
|
36605
|
+
method,
|
|
36606
|
+
headers: domainHeaders(cfg),
|
|
36607
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
36608
|
+
signal: AbortSignal.timeout(30000)
|
|
36609
|
+
});
|
|
36610
|
+
const text = await response.text();
|
|
36611
|
+
if (!response.ok) {
|
|
36612
|
+
throw new BrandsightApiError(`Brandsight Domain API ${method} ${path} failed with status ${response.status}`, response.status, text);
|
|
36445
36613
|
}
|
|
36614
|
+
if (!text.trim())
|
|
36615
|
+
return {};
|
|
36616
|
+
return JSON.parse(text);
|
|
36617
|
+
}
|
|
36618
|
+
function normalizeBrandsightDomain(raw) {
|
|
36619
|
+
const nameServers = raw.nameServers ?? raw.nameservers ?? [];
|
|
36620
|
+
const expiresAt = raw.expiresAt ?? raw.expires ?? "";
|
|
36621
|
+
const createdAt = raw.createdAt ?? raw.created ?? "";
|
|
36622
|
+
const renewAuto = raw.renewAuto ?? raw.auto_renew ?? false;
|
|
36623
|
+
return {
|
|
36624
|
+
...raw,
|
|
36625
|
+
domain: String(raw.domain ?? ""),
|
|
36626
|
+
status: String(raw.status ?? "UNKNOWN"),
|
|
36627
|
+
created: createdAt,
|
|
36628
|
+
expires: expiresAt,
|
|
36629
|
+
auto_renew: renewAuto,
|
|
36630
|
+
locked: Boolean(raw.locked),
|
|
36631
|
+
nameservers: nameServers,
|
|
36632
|
+
createdAt,
|
|
36633
|
+
expiresAt,
|
|
36634
|
+
nameServers,
|
|
36635
|
+
renewAuto
|
|
36636
|
+
};
|
|
36637
|
+
}
|
|
36638
|
+
function customerPath(cfg, path) {
|
|
36639
|
+
return `/customers/${encodeURIComponent(cfg.customerId)}${path}`;
|
|
36640
|
+
}
|
|
36641
|
+
function domainTld(domain) {
|
|
36642
|
+
const parts = domain.split(".").filter(Boolean);
|
|
36643
|
+
if (parts.length < 2)
|
|
36644
|
+
throw new BrandsightApiError(`Invalid domain name: ${domain}`);
|
|
36645
|
+
return parts.slice(1).join(".");
|
|
36646
|
+
}
|
|
36647
|
+
function brandsightContact(contact) {
|
|
36648
|
+
return {
|
|
36649
|
+
addressMailing: {
|
|
36650
|
+
address1: contact.address_line_1,
|
|
36651
|
+
city: contact.city,
|
|
36652
|
+
country: contact.country_code,
|
|
36653
|
+
postalCode: contact.zip_code,
|
|
36654
|
+
state: contact.state
|
|
36655
|
+
},
|
|
36656
|
+
email: contact.email,
|
|
36657
|
+
encoding: "ASCII",
|
|
36658
|
+
nameFirst: contact.first_name,
|
|
36659
|
+
nameLast: contact.last_name,
|
|
36660
|
+
organization: contact.organization_name,
|
|
36661
|
+
phone: contact.phone
|
|
36662
|
+
};
|
|
36663
|
+
}
|
|
36664
|
+
async function domainAvailability(domain, cfg, type, period = 1) {
|
|
36665
|
+
const params = new URLSearchParams({
|
|
36666
|
+
domain,
|
|
36667
|
+
period: String(period),
|
|
36668
|
+
type,
|
|
36669
|
+
optimizeFor: "ACCURACY"
|
|
36670
|
+
});
|
|
36671
|
+
const result = await domainApiRequest("GET", `/domains/available?${params.toString()}`, cfg);
|
|
36672
|
+
return {
|
|
36673
|
+
domain: result.domain ?? domain,
|
|
36674
|
+
available: Boolean(result.available),
|
|
36675
|
+
price: result.price,
|
|
36676
|
+
currency: result.currency,
|
|
36677
|
+
registryPremiumPricing: result.registryPremiumPricing
|
|
36678
|
+
};
|
|
36446
36679
|
}
|
|
36447
36680
|
async function listDomains2(config) {
|
|
36448
|
-
const cfg = config
|
|
36449
|
-
const
|
|
36450
|
-
|
|
36451
|
-
|
|
36452
|
-
|
|
36681
|
+
const cfg = requireDomainConfig(config);
|
|
36682
|
+
const domains = [];
|
|
36683
|
+
const seenMarkers = new Set;
|
|
36684
|
+
let marker;
|
|
36685
|
+
while (true) {
|
|
36686
|
+
const params = new URLSearchParams({ limit: "500" });
|
|
36687
|
+
if (marker)
|
|
36688
|
+
params.set("marker", marker);
|
|
36689
|
+
const batch = await domainApiRequest("GET", customerPath(cfg, `/domains?${params.toString()}`), cfg);
|
|
36690
|
+
if (!Array.isArray(batch) || batch.length === 0)
|
|
36691
|
+
break;
|
|
36692
|
+
domains.push(...batch.map(normalizeBrandsightDomain).filter((d3) => d3.domain));
|
|
36693
|
+
if (batch.length < 500)
|
|
36694
|
+
break;
|
|
36695
|
+
const nextMarker = String(batch[batch.length - 1]?.domain ?? "");
|
|
36696
|
+
if (!nextMarker || seenMarkers.has(nextMarker))
|
|
36697
|
+
break;
|
|
36698
|
+
seenMarkers.add(nextMarker);
|
|
36699
|
+
marker = nextMarker;
|
|
36700
|
+
}
|
|
36701
|
+
return domains;
|
|
36453
36702
|
}
|
|
36454
36703
|
async function getDomainInfo3(domain, config) {
|
|
36455
|
-
const cfg = config
|
|
36456
|
-
const result = await
|
|
36457
|
-
|
|
36458
|
-
return null;
|
|
36459
|
-
return result.data;
|
|
36704
|
+
const cfg = requireDomainConfig(config);
|
|
36705
|
+
const result = await domainApiRequest("GET", customerPath(cfg, `/domains/${encodeURIComponent(domain)}`), cfg);
|
|
36706
|
+
return normalizeBrandsightDomain(result);
|
|
36460
36707
|
}
|
|
36461
36708
|
async function checkAvailability4(domain, config) {
|
|
36462
|
-
const cfg = config
|
|
36463
|
-
|
|
36464
|
-
if (result.stub)
|
|
36465
|
-
return { domain, available: false };
|
|
36466
|
-
return result.data;
|
|
36709
|
+
const cfg = requireDomainConfig(config);
|
|
36710
|
+
return domainAvailability(domain, cfg, "REGISTRATION", 1);
|
|
36467
36711
|
}
|
|
36468
36712
|
async function renewDomain3(domain, years = 1, config) {
|
|
36469
|
-
const cfg = config
|
|
36470
|
-
const
|
|
36471
|
-
if (
|
|
36472
|
-
|
|
36473
|
-
|
|
36713
|
+
const cfg = requireDomainConfig(config);
|
|
36714
|
+
const current = await getDomainInfo3(domain, cfg);
|
|
36715
|
+
if (!current?.expires)
|
|
36716
|
+
throw new BrandsightApiError(`Cannot renew ${domain}: current expiry is unavailable`);
|
|
36717
|
+
const quote = await domainAvailability(domain, cfg, "RENEWAL", years);
|
|
36718
|
+
const price = quote.price ?? current.renewal?.price;
|
|
36719
|
+
const currency = quote.currency ?? current.renewal?.currency;
|
|
36720
|
+
if (price == null || !currency) {
|
|
36721
|
+
throw new BrandsightApiError(`Cannot renew ${domain}: renewal quote did not include an exact price and currency`);
|
|
36722
|
+
}
|
|
36723
|
+
const result = await domainApiRequest("POST", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/renew`), cfg, {
|
|
36724
|
+
consent: {
|
|
36725
|
+
agreedAt: new Date().toISOString(),
|
|
36726
|
+
agreedBy: cfg.shopperId ?? "domains-cli",
|
|
36727
|
+
currency,
|
|
36728
|
+
price,
|
|
36729
|
+
registryPremiumPricing: quote.registryPremiumPricing ?? false
|
|
36730
|
+
},
|
|
36731
|
+
expires: current.expires,
|
|
36732
|
+
period: years
|
|
36733
|
+
});
|
|
36734
|
+
return { success: true, orderId: result.orderId ?? result.id };
|
|
36735
|
+
}
|
|
36736
|
+
async function getLegalAgreements(tld, privacy = false, config) {
|
|
36737
|
+
const cfg = requireDomainConfig(config);
|
|
36738
|
+
const params = new URLSearchParams({
|
|
36739
|
+
privacy: String(privacy),
|
|
36740
|
+
tlds: tld
|
|
36741
|
+
});
|
|
36742
|
+
return domainApiRequest("GET", customerPath(cfg, `/domains/agreements?${params.toString()}`), cfg);
|
|
36743
|
+
}
|
|
36744
|
+
async function getRegistrationSchema(tld, config) {
|
|
36745
|
+
const cfg = requireDomainConfig(config);
|
|
36746
|
+
return domainApiRequest("GET", customerPath(cfg, `/domains/register/schema/${encodeURIComponent(tld)}`), cfg);
|
|
36747
|
+
}
|
|
36748
|
+
async function validateRegistrationRequest(payload, config) {
|
|
36749
|
+
const cfg = requireDomainConfig(config);
|
|
36750
|
+
await domainApiRequest("POST", customerPath(cfg, "/domains/register/validate"), cfg, payload);
|
|
36751
|
+
return true;
|
|
36752
|
+
}
|
|
36753
|
+
async function registerBrandsightDomain(domain, contact, options = {}, config) {
|
|
36754
|
+
const cfg = requireDomainConfig(config);
|
|
36755
|
+
const period = options.years ?? 1;
|
|
36756
|
+
const availability = await domainAvailability(domain, cfg, "REGISTRATION", period);
|
|
36757
|
+
if (!availability.available)
|
|
36758
|
+
throw new BrandsightApiError(`${domain} is not available for registration`);
|
|
36759
|
+
const price = options.premiumPrice ?? availability.price;
|
|
36760
|
+
if (price == null || !availability.currency) {
|
|
36761
|
+
throw new BrandsightApiError(`Cannot register ${domain}: availability quote did not include an exact price and currency`);
|
|
36762
|
+
}
|
|
36763
|
+
const tld = domainTld(domain);
|
|
36764
|
+
const schema = await getRegistrationSchema(tld, cfg);
|
|
36765
|
+
const required = Array.isArray(schema["required"]) ? schema["required"] : [];
|
|
36766
|
+
if (required.includes("metadata") && !options.metadata) {
|
|
36767
|
+
throw new BrandsightApiError(`Cannot register ${domain}: ${tld} requires TLD-specific metadata; pass registration metadata before validation`);
|
|
36768
|
+
}
|
|
36769
|
+
const privacy = options.privacy ?? false;
|
|
36770
|
+
const agreements = await getLegalAgreements(tld, privacy, cfg);
|
|
36771
|
+
const agreementKeys = agreements.map((a3) => a3.agreementKey).filter(Boolean);
|
|
36772
|
+
const c3 = brandsightContact(contact);
|
|
36773
|
+
const payload = {
|
|
36774
|
+
consent: {
|
|
36775
|
+
agreedAt: new Date().toISOString(),
|
|
36776
|
+
agreedBy: contact.email || cfg.shopperId || "domains-cli",
|
|
36777
|
+
agreementKeys,
|
|
36778
|
+
currency: availability.currency,
|
|
36779
|
+
price,
|
|
36780
|
+
registryPremiumPricing: availability.registryPremiumPricing ?? !!options.premiumPrice
|
|
36781
|
+
},
|
|
36782
|
+
contacts: {
|
|
36783
|
+
admin: c3,
|
|
36784
|
+
billing: c3,
|
|
36785
|
+
registrant: c3,
|
|
36786
|
+
tech: c3
|
|
36787
|
+
},
|
|
36788
|
+
domain,
|
|
36789
|
+
metadata: options.metadata ?? {},
|
|
36790
|
+
nameServers: options.nameservers ?? [],
|
|
36791
|
+
period,
|
|
36792
|
+
privacy,
|
|
36793
|
+
renewAuto: options.autoRenew ?? true
|
|
36794
|
+
};
|
|
36795
|
+
await validateRegistrationRequest(payload, cfg);
|
|
36796
|
+
const result = await domainApiRequest("POST", customerPath(cfg, "/domains/register"), cfg, payload);
|
|
36797
|
+
return {
|
|
36798
|
+
success: true,
|
|
36799
|
+
orderId: result.orderId ?? result.id,
|
|
36800
|
+
operationId: result.operationId ?? result.id,
|
|
36801
|
+
chargedAmount: String(price)
|
|
36802
|
+
};
|
|
36803
|
+
}
|
|
36804
|
+
async function updateNameservers3(domain, nameservers, config) {
|
|
36805
|
+
const cfg = requireDomainConfig(config);
|
|
36806
|
+
const result = await domainApiRequest("PUT", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/nameServers`), cfg, { nameServers: nameservers });
|
|
36807
|
+
return { success: true, operationId: result.operationId ?? result.id };
|
|
36808
|
+
}
|
|
36809
|
+
async function getDnsRecords3(domain, config) {
|
|
36810
|
+
const cfg = requireDomainConfig(config);
|
|
36811
|
+
const records = [];
|
|
36812
|
+
let offset = 0;
|
|
36813
|
+
const limit = 1000;
|
|
36814
|
+
while (true) {
|
|
36815
|
+
const batch = await domainApiRequest("GET", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/records?offset=${offset}&limit=${limit}`), cfg);
|
|
36816
|
+
if (!Array.isArray(batch) || batch.length === 0)
|
|
36817
|
+
break;
|
|
36818
|
+
records.push(...batch);
|
|
36819
|
+
if (batch.length < limit)
|
|
36820
|
+
break;
|
|
36821
|
+
offset++;
|
|
36822
|
+
}
|
|
36823
|
+
return records;
|
|
36824
|
+
}
|
|
36825
|
+
function normalizeBrandsightDnsRecord(record) {
|
|
36826
|
+
return {
|
|
36827
|
+
...record,
|
|
36828
|
+
ttl: Math.max(record.ttl || 600, 600)
|
|
36829
|
+
};
|
|
36830
|
+
}
|
|
36831
|
+
async function setDnsRecords3(domain, records, config) {
|
|
36832
|
+
const cfg = requireDomainConfig(config);
|
|
36833
|
+
await domainApiRequest("PUT", customerPath(cfg, `/domains/${encodeURIComponent(domain)}/records`), cfg, records.map(normalizeBrandsightDnsRecord));
|
|
36834
|
+
return true;
|
|
36474
36835
|
}
|
|
36475
36836
|
async function syncToLocalDb3(dbFns, config) {
|
|
36476
36837
|
const domains = await listDomains2(config);
|
|
@@ -36515,7 +36876,7 @@ function createBrandsightProvider(config) {
|
|
|
36515
36876
|
return domains.map((d3) => ({
|
|
36516
36877
|
domain: d3.domain,
|
|
36517
36878
|
registrar: "Brandsight",
|
|
36518
|
-
created: "",
|
|
36879
|
+
created: d3.created ?? "",
|
|
36519
36880
|
expires: d3.expires,
|
|
36520
36881
|
nameservers: d3.nameservers,
|
|
36521
36882
|
status: d3.status === "ACTIVE" ? "active" : d3.status.toLowerCase(),
|
|
@@ -36529,7 +36890,7 @@ function createBrandsightProvider(config) {
|
|
|
36529
36890
|
return {
|
|
36530
36891
|
domain: d3.domain,
|
|
36531
36892
|
registrar: "Brandsight",
|
|
36532
|
-
created: "",
|
|
36893
|
+
created: d3.created ?? "",
|
|
36533
36894
|
expires: d3.expires,
|
|
36534
36895
|
nameservers: d3.nameservers,
|
|
36535
36896
|
status: d3.status === "ACTIVE" ? "active" : d3.status.toLowerCase(),
|
|
@@ -36540,12 +36901,47 @@ function createBrandsightProvider(config) {
|
|
|
36540
36901
|
const result = await renewDomain3(domain, years, cfg);
|
|
36541
36902
|
return { domain, success: result.success, orderId: result.orderId };
|
|
36542
36903
|
},
|
|
36904
|
+
async registerDomain(domain, contact, options) {
|
|
36905
|
+
const result = await registerBrandsightDomain(domain, contact, options, cfg);
|
|
36906
|
+
return {
|
|
36907
|
+
domain,
|
|
36908
|
+
success: result.success,
|
|
36909
|
+
orderId: result.orderId,
|
|
36910
|
+
operationId: result.operationId,
|
|
36911
|
+
chargedAmount: result.chargedAmount
|
|
36912
|
+
};
|
|
36913
|
+
},
|
|
36914
|
+
async updateNameservers(domain, nameservers) {
|
|
36915
|
+
const result = await updateNameservers3(domain, nameservers, cfg);
|
|
36916
|
+
return { domain, success: result.success, operationId: result.operationId };
|
|
36917
|
+
},
|
|
36918
|
+
async getDnsRecords(domain) {
|
|
36919
|
+
const records = await getDnsRecords3(domain, cfg);
|
|
36920
|
+
return records.map((r3) => ({
|
|
36921
|
+
type: r3.type,
|
|
36922
|
+
name: r3.name,
|
|
36923
|
+
value: r3.data,
|
|
36924
|
+
ttl: r3.ttl,
|
|
36925
|
+
priority: r3.priority
|
|
36926
|
+
}));
|
|
36927
|
+
},
|
|
36928
|
+
async setDnsRecords(domain, records) {
|
|
36929
|
+
return setDnsRecords3(domain, records.map((r3) => ({
|
|
36930
|
+
type: r3.type,
|
|
36931
|
+
name: r3.name,
|
|
36932
|
+
data: r3.value,
|
|
36933
|
+
ttl: r3.ttl,
|
|
36934
|
+
priority: r3.priority
|
|
36935
|
+
})), cfg);
|
|
36936
|
+
},
|
|
36543
36937
|
async checkAvailability(domain) {
|
|
36544
36938
|
const result = await checkAvailability4(domain, cfg);
|
|
36545
36939
|
return {
|
|
36546
36940
|
domain: result.domain,
|
|
36547
36941
|
available: result.available,
|
|
36548
|
-
|
|
36942
|
+
is_premium: result.registryPremiumPricing,
|
|
36943
|
+
premium_price: result.registryPremiumPricing ? result.price : undefined,
|
|
36944
|
+
standard_price: result.registryPremiumPricing ? undefined : result.price,
|
|
36549
36945
|
currency: result.currency
|
|
36550
36946
|
};
|
|
36551
36947
|
},
|
|
@@ -36743,6 +37139,7 @@ var providerRegistry = new Map([
|
|
|
36743
37139
|
configured: false,
|
|
36744
37140
|
envVars: providerEnvNames("namecheap")
|
|
36745
37141
|
},
|
|
37142
|
+
createInventory: createNamecheapProvider,
|
|
36746
37143
|
createRegistrar: createNamecheapProvider,
|
|
36747
37144
|
createDns: createNamecheapProvider
|
|
36748
37145
|
}],
|
|
@@ -36753,6 +37150,7 @@ var providerRegistry = new Map([
|
|
|
36753
37150
|
configured: false,
|
|
36754
37151
|
envVars: providerEnvNames("godaddy")
|
|
36755
37152
|
},
|
|
37153
|
+
createInventory: createGoDaddyProvider,
|
|
36756
37154
|
createRegistrar: createGoDaddyProvider,
|
|
36757
37155
|
createDns: createGoDaddyProvider
|
|
36758
37156
|
}],
|
|
@@ -36763,6 +37161,7 @@ var providerRegistry = new Map([
|
|
|
36763
37161
|
configured: false,
|
|
36764
37162
|
envVars: providerEnvNames("route53")
|
|
36765
37163
|
},
|
|
37164
|
+
createInventory: () => createRoute53Provider(),
|
|
36766
37165
|
createRegistrar: () => createRoute53Provider(),
|
|
36767
37166
|
createDns: () => createRoute53Provider()
|
|
36768
37167
|
}],
|
|
@@ -36773,16 +37172,19 @@ var providerRegistry = new Map([
|
|
|
36773
37172
|
configured: false,
|
|
36774
37173
|
envVars: providerEnvNames("cloudflare")
|
|
36775
37174
|
},
|
|
37175
|
+
createInventory: () => createCloudflareProvider(),
|
|
36776
37176
|
createDns: createCloudflareProvider
|
|
36777
37177
|
}],
|
|
36778
37178
|
["brandsight", {
|
|
36779
37179
|
info: {
|
|
36780
37180
|
name: "brandsight",
|
|
36781
|
-
type: "
|
|
37181
|
+
type: "full",
|
|
36782
37182
|
configured: false,
|
|
36783
37183
|
envVars: providerEnvNames("brandsight")
|
|
36784
37184
|
},
|
|
36785
|
-
|
|
37185
|
+
createInventory: createBrandsightProvider,
|
|
37186
|
+
createRegistrar: createBrandsightProvider,
|
|
37187
|
+
createDns: createBrandsightProvider
|
|
36786
37188
|
}],
|
|
36787
37189
|
["sedo", {
|
|
36788
37190
|
info: {
|
|
@@ -36799,14 +37201,15 @@ function isConfigured(providerName) {
|
|
|
36799
37201
|
function getAvailableProviders() {
|
|
36800
37202
|
return Array.from(providerRegistry.values()).map((e3) => ({
|
|
36801
37203
|
...e3.info,
|
|
36802
|
-
configured: isConfigured(e3.info.name)
|
|
37204
|
+
configured: isConfigured(e3.info.name),
|
|
37205
|
+
inventory: !!e3.createInventory
|
|
36803
37206
|
}));
|
|
36804
37207
|
}
|
|
36805
37208
|
function getProviderInfo(name) {
|
|
36806
37209
|
const entry = providerRegistry.get(name.toLowerCase());
|
|
36807
37210
|
if (!entry)
|
|
36808
37211
|
return null;
|
|
36809
|
-
return { ...entry.info, configured: isConfigured(entry.info.name) };
|
|
37212
|
+
return { ...entry.info, configured: isConfigured(entry.info.name), inventory: !!entry.createInventory };
|
|
36810
37213
|
}
|
|
36811
37214
|
function providerHasRegistrar(name) {
|
|
36812
37215
|
return !!providerRegistry.get(name.toLowerCase())?.createRegistrar;
|
|
@@ -36814,6 +37217,15 @@ function providerHasRegistrar(name) {
|
|
|
36814
37217
|
function providerHasDns(name) {
|
|
36815
37218
|
return !!providerRegistry.get(name.toLowerCase())?.createDns;
|
|
36816
37219
|
}
|
|
37220
|
+
function providerHasInventory(name) {
|
|
37221
|
+
return !!providerRegistry.get(name.toLowerCase())?.createInventory;
|
|
37222
|
+
}
|
|
37223
|
+
function getDomainInventoryProvider(name) {
|
|
37224
|
+
const entry = providerRegistry.get(name.toLowerCase());
|
|
37225
|
+
if (!entry?.createInventory)
|
|
37226
|
+
throw new Error(`No domain inventory provider: ${name}`);
|
|
37227
|
+
return entry.createInventory();
|
|
37228
|
+
}
|
|
36817
37229
|
function getRegistrarProvider(name) {
|
|
36818
37230
|
const entry = providerRegistry.get(name.toLowerCase());
|
|
36819
37231
|
if (!entry?.createRegistrar)
|
|
@@ -36824,11 +37236,11 @@ function getProvider(name) {
|
|
|
36824
37236
|
return getRegistrarProvider(name);
|
|
36825
37237
|
}
|
|
36826
37238
|
async function syncAll(dbFns) {
|
|
36827
|
-
const available = getAvailableProviders().filter((p3) => p3.configured &&
|
|
37239
|
+
const available = getAvailableProviders().filter((p3) => p3.configured && providerHasInventory(p3.name));
|
|
36828
37240
|
const result = { providers: [], totalSynced: 0, totalErrors: [] };
|
|
36829
37241
|
for (const info of available) {
|
|
36830
37242
|
try {
|
|
36831
|
-
const provider =
|
|
37243
|
+
const provider = getDomainInventoryProvider(info.name);
|
|
36832
37244
|
const syncResult = await provider.syncToLocalDb(dbFns);
|
|
36833
37245
|
result.providers.push({ name: info.name, result: syncResult });
|
|
36834
37246
|
result.totalSynced += syncResult.synced;
|
|
@@ -36846,14 +37258,16 @@ function autoDetectRegistrar(domain, getDomainByName2) {
|
|
|
36846
37258
|
if (!dbDomain?.registrar)
|
|
36847
37259
|
return null;
|
|
36848
37260
|
const r3 = dbDomain.registrar.toLowerCase();
|
|
37261
|
+
if (r3.includes("cloudflare dns") || r3.includes("route 53 dns") || r3.includes("route53 dns"))
|
|
37262
|
+
return null;
|
|
36849
37263
|
if (r3.includes("namecheap"))
|
|
36850
37264
|
return "namecheap";
|
|
36851
37265
|
if (r3.includes("godaddy"))
|
|
36852
37266
|
return "godaddy";
|
|
36853
|
-
if (r3.includes("route 53") || r3.includes("route53")
|
|
37267
|
+
if (r3.includes("route 53") || r3.includes("route53"))
|
|
36854
37268
|
return "route53";
|
|
36855
37269
|
if (r3.includes("cloudflare"))
|
|
36856
|
-
return
|
|
37270
|
+
return null;
|
|
36857
37271
|
if (r3.includes("brandsight"))
|
|
36858
37272
|
return "brandsight";
|
|
36859
37273
|
return null;
|
|
@@ -36872,8 +37286,8 @@ var PROVIDER_CAPABILITIES = {
|
|
|
36872
37286
|
route53: { canBuy: true, canDns: true, gated: false, notes: "Full self-serve buy + hosted zones via AWS API; primary buy path." },
|
|
36873
37287
|
cloudflare: { canBuy: false, canDns: true, gated: false, notes: "DNS/zone management only; not a registrar. Always our DNS." },
|
|
36874
37288
|
namecheap: { canBuy: true, canDns: true, gated: false, notes: "Buy + DNS via API; requires API access + whitelisted IP." },
|
|
36875
|
-
godaddy: { canBuy: false, canDns: true, gated: true, notes: "
|
|
36876
|
-
brandsight: { canBuy:
|
|
37289
|
+
godaddy: { canBuy: false, canDns: true, gated: true, notes: "Availability remains threshold-gated; this CLI supports sync/renew/DNS records where account access qualifies, but not direct automated purchase." },
|
|
37290
|
+
brandsight: { canBuy: true, canDns: true, gated: true, notes: "GoDaddy Corporate Domains (enterprise/contract-only); this CLI supports portfolio, registration, renewal, nameserver, and DNS operations through the official v2 API when the account contract permits it." },
|
|
36877
37291
|
sedo: { canBuy: false, canDns: false, gated: true, notes: "Marketplace API only: search/portfolio/listings and recorded purchases; no registrar DNS or direct registration API in this CLI." }
|
|
36878
37292
|
};
|
|
36879
37293
|
var UNKNOWN = { canBuy: false, canDns: false, gated: true, notes: "Unknown provider." };
|
|
@@ -36958,6 +37372,7 @@ export {
|
|
|
36958
37372
|
createHostedZone as r53CreateHostedZone,
|
|
36959
37373
|
checkAvailability3 as r53CheckAvailability,
|
|
36960
37374
|
providerHasRegistrar,
|
|
37375
|
+
providerHasInventory,
|
|
36961
37376
|
providerHasDns,
|
|
36962
37377
|
pollRegistrationUntilDone,
|
|
36963
37378
|
markDomainPremium,
|
|
@@ -36981,6 +37396,7 @@ export {
|
|
|
36981
37396
|
getProvider,
|
|
36982
37397
|
getDomainStats,
|
|
36983
37398
|
getDomainOffer,
|
|
37399
|
+
getDomainInventoryProvider,
|
|
36984
37400
|
getDomainEmailLink,
|
|
36985
37401
|
getDomainDetails,
|
|
36986
37402
|
getDomainByName,
|