@hasna/domains 0.0.25 → 0.0.27
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/dist/cli/commands/sedo.d.ts.map +1 -1
- package/dist/cli/index.js +336 -96
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +445 -126
- package/dist/lib/capability.js +46 -0
- package/dist/lib/cloudflare-auth.js +139 -0
- package/dist/lib/cloudflare.js +394 -0
- package/dist/lib/creds-check.d.ts.map +1 -1
- package/dist/lib/delegate.js +12 -0
- package/dist/lib/env-aliases.d.ts +10 -0
- package/dist/lib/env-aliases.d.ts.map +1 -1
- package/dist/lib/registrar.js +2216 -0
- package/dist/lib/route53.d.ts +54 -11
- package/dist/lib/route53.d.ts.map +1 -1
- package/dist/lib/route53.js +678 -0
- package/dist/lib/sedo.d.ts +34 -3
- package/dist/lib/sedo.d.ts.map +1 -1
- package/dist/mcp/index.js +181 -68
- package/package.json +28 -3
package/dist/cli/index.js
CHANGED
|
@@ -36170,14 +36170,19 @@ __export(exports_route53, {
|
|
|
36170
36170
|
upsertRecords: () => upsertRecords,
|
|
36171
36171
|
upsertRecord: () => upsertRecord,
|
|
36172
36172
|
updateNameservers: () => updateNameservers2,
|
|
36173
|
+
transferDomain: () => transferDomain,
|
|
36174
|
+
requestTransferOutAuthCode: () => requestTransferOutAuthCode,
|
|
36173
36175
|
registerDomain: () => registerDomain2,
|
|
36176
|
+
listTldPrices: () => listTldPrices,
|
|
36174
36177
|
listRegisteredDomains: () => listRegisteredDomains,
|
|
36175
36178
|
listRecords: () => listRecords,
|
|
36176
36179
|
listHostedZones: () => listHostedZones,
|
|
36180
|
+
getTldPrice: () => getTldPrice,
|
|
36177
36181
|
getRegistrationStatus: () => getRegistrationStatus,
|
|
36178
36182
|
getHostedZone: () => getHostedZone,
|
|
36179
36183
|
getDomainDetail: () => getDomainDetail,
|
|
36180
36184
|
getConfig: () => getConfig2,
|
|
36185
|
+
findHostedZoneByNameservers: () => findHostedZoneByNameservers,
|
|
36181
36186
|
findHostedZoneByDomain: () => findHostedZoneByDomain,
|
|
36182
36187
|
deleteRecord: () => deleteRecord,
|
|
36183
36188
|
deleteHostedZone: () => deleteHostedZone,
|
|
@@ -36187,26 +36192,17 @@ __export(exports_route53, {
|
|
|
36187
36192
|
});
|
|
36188
36193
|
function getConfig2() {
|
|
36189
36194
|
return {
|
|
36190
|
-
region: process.env["AWS_REGION"] || "us-east-1",
|
|
36191
|
-
accessKeyId: process.env["AWS_ACCESS_KEY_ID"],
|
|
36192
|
-
secretAccessKey: process.env["AWS_SECRET_ACCESS_KEY"],
|
|
36193
|
-
sessionToken: process.env["AWS_SESSION_TOKEN"]
|
|
36195
|
+
region: process.env["ROUTE53_REGION"] || process.env["ROUTE53_AWS_REGION"] || process.env["AWS_REGION"] || "us-east-1",
|
|
36196
|
+
accessKeyId: process.env["ROUTE53_ACCESS_KEY_ID"] || process.env["AWS_ACCESS_KEY_ID"],
|
|
36197
|
+
secretAccessKey: process.env["ROUTE53_SECRET_ACCESS_KEY"] || process.env["AWS_SECRET_ACCESS_KEY"],
|
|
36198
|
+
sessionToken: process.env["ROUTE53_SESSION_TOKEN"] || process.env["AWS_SESSION_TOKEN"],
|
|
36199
|
+
profile: process.env["ROUTE53_AWS_PROFILE"] || process.env["AWS_PROFILE"]
|
|
36194
36200
|
};
|
|
36195
36201
|
}
|
|
36196
|
-
function checkCredentials(cfg) {
|
|
36197
|
-
if (cfg.accessKeyId && cfg.secretAccessKey)
|
|
36198
|
-
return;
|
|
36199
|
-
const hasEnv = !!(process.env["AWS_ACCESS_KEY_ID"] && process.env["AWS_SECRET_ACCESS_KEY"]);
|
|
36200
|
-
const hasProfile = !!process.env["AWS_PROFILE"];
|
|
36201
|
-
if (!hasEnv && !hasProfile) {
|
|
36202
|
-
throw new Error("AWS credentials not configured. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (or AWS_PROFILE) environment variables.");
|
|
36203
|
-
}
|
|
36204
|
-
}
|
|
36205
36202
|
function makeClients(config2) {
|
|
36206
36203
|
const cfg = config2 ?? getConfig2();
|
|
36207
|
-
checkCredentials(cfg);
|
|
36208
36204
|
const region = cfg.region || "us-east-1";
|
|
36209
|
-
const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey, sessionToken: cfg.sessionToken } : undefined;
|
|
36205
|
+
const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey, sessionToken: cfg.sessionToken } : cfg.profile ? fromIni({ profile: cfg.profile }) : undefined;
|
|
36210
36206
|
return {
|
|
36211
36207
|
route53: new Route53Client({ region, credentials }),
|
|
36212
36208
|
domains: new Route53DomainsClient({ region: "us-east-1", credentials })
|
|
@@ -36217,49 +36213,106 @@ async function checkAvailability3(domain, config2) {
|
|
|
36217
36213
|
const result = await domains.send(new CheckDomainAvailabilityCommand({ DomainName: domain }));
|
|
36218
36214
|
const availability = {
|
|
36219
36215
|
domain,
|
|
36220
|
-
available: result.Availability === "AVAILABLE"
|
|
36216
|
+
available: result.Availability === "AVAILABLE",
|
|
36217
|
+
availability: result.Availability ?? "UNKNOWN"
|
|
36221
36218
|
};
|
|
36222
|
-
|
|
36223
|
-
|
|
36224
|
-
|
|
36225
|
-
|
|
36226
|
-
|
|
36227
|
-
|
|
36228
|
-
|
|
36229
|
-
availability.
|
|
36230
|
-
|
|
36231
|
-
|
|
36232
|
-
|
|
36233
|
-
|
|
36234
|
-
}
|
|
36235
|
-
} catch {}
|
|
36219
|
+
if (availability.available) {
|
|
36220
|
+
try {
|
|
36221
|
+
const tld = domain.split(".").slice(1).join(".");
|
|
36222
|
+
const price = await getTldPrice(tld, config2);
|
|
36223
|
+
if (price) {
|
|
36224
|
+
availability.currency = price.currency;
|
|
36225
|
+
availability.price = price.registration_price;
|
|
36226
|
+
availability.renewal_price = price.renewal_price;
|
|
36227
|
+
availability.transfer_price = price.transfer_price;
|
|
36228
|
+
}
|
|
36229
|
+
} catch {}
|
|
36230
|
+
}
|
|
36236
36231
|
return availability;
|
|
36237
36232
|
}
|
|
36238
|
-
|
|
36233
|
+
function normalizeTld(tld) {
|
|
36234
|
+
return tld.trim().replace(/^\./, "");
|
|
36235
|
+
}
|
|
36236
|
+
function priceString(value) {
|
|
36237
|
+
return value == null ? undefined : value.toString();
|
|
36238
|
+
}
|
|
36239
|
+
function tldPriceFromRoute53Price(tld, price) {
|
|
36240
|
+
return {
|
|
36241
|
+
tld: price.Name || tld,
|
|
36242
|
+
registration_price: priceString(price.RegistrationPrice?.Price),
|
|
36243
|
+
renewal_price: priceString(price.RenewalPrice?.Price),
|
|
36244
|
+
transfer_price: priceString(price.TransferPrice?.Price),
|
|
36245
|
+
currency: price.RegistrationPrice?.Currency ?? price.RenewalPrice?.Currency ?? price.TransferPrice?.Currency
|
|
36246
|
+
};
|
|
36247
|
+
}
|
|
36248
|
+
async function getTldPrice(tld, config2) {
|
|
36249
|
+
const { domains } = makeClients(config2);
|
|
36250
|
+
const normalized = normalizeTld(tld);
|
|
36251
|
+
const prices = await domains.send(new ListPricesCommand({ Tld: normalized, MaxItems: 1 }));
|
|
36252
|
+
const price = prices.Prices?.[0];
|
|
36253
|
+
return price ? tldPriceFromRoute53Price(normalized, price) : null;
|
|
36254
|
+
}
|
|
36255
|
+
async function listTldPrices(config2) {
|
|
36256
|
+
const { domains } = makeClients(config2);
|
|
36257
|
+
const prices = [];
|
|
36258
|
+
let marker;
|
|
36259
|
+
do {
|
|
36260
|
+
const result = await domains.send(new ListPricesCommand({ Marker: marker, MaxItems: 100 }));
|
|
36261
|
+
for (const price of result.Prices ?? []) {
|
|
36262
|
+
prices.push(tldPriceFromRoute53Price(price.Name || "", price));
|
|
36263
|
+
}
|
|
36264
|
+
marker = result.NextPageMarker;
|
|
36265
|
+
} while (marker);
|
|
36266
|
+
return prices;
|
|
36267
|
+
}
|
|
36268
|
+
async function registerDomain2(domain, contact, durationYears = 1, autoRenew = true, config2, options = {}) {
|
|
36239
36269
|
const { domains } = makeClients(config2);
|
|
36240
|
-
const contactDetail =
|
|
36270
|
+
const contactDetail = contactToRoute53Contact(contact);
|
|
36271
|
+
const result = await domains.send(new RegisterDomainCommand({
|
|
36272
|
+
DomainName: domain,
|
|
36273
|
+
DurationInYears: durationYears,
|
|
36274
|
+
AutoRenew: autoRenew,
|
|
36275
|
+
AdminContact: contactDetail,
|
|
36276
|
+
RegistrantContact: contactDetail,
|
|
36277
|
+
TechContact: contactDetail,
|
|
36278
|
+
PrivacyProtectAdminContact: options.privacy_protected ?? true,
|
|
36279
|
+
PrivacyProtectRegistrantContact: options.privacy_protected ?? true,
|
|
36280
|
+
PrivacyProtectTechContact: options.privacy_protected ?? true,
|
|
36281
|
+
...options.nameservers?.length ? { Nameservers: options.nameservers.map((Name) => ({ Name })) } : {}
|
|
36282
|
+
}));
|
|
36283
|
+
return { operationId: result.OperationId ?? "" };
|
|
36284
|
+
}
|
|
36285
|
+
function contactToRoute53Contact(contact) {
|
|
36286
|
+
return {
|
|
36241
36287
|
FirstName: contact.first_name,
|
|
36242
36288
|
LastName: contact.last_name,
|
|
36243
36289
|
Email: contact.email,
|
|
36244
36290
|
PhoneNumber: contact.phone,
|
|
36245
36291
|
AddressLine1: contact.address_line_1,
|
|
36292
|
+
...contact.address_line_2 ? { AddressLine2: contact.address_line_2 } : {},
|
|
36246
36293
|
City: contact.city,
|
|
36247
|
-
State: contact.state,
|
|
36248
|
-
CountryCode: contact.country_code,
|
|
36294
|
+
...contact.state ? { State: contact.state } : {},
|
|
36295
|
+
CountryCode: contact.country_code.toUpperCase(),
|
|
36249
36296
|
ZipCode: contact.zip_code,
|
|
36250
36297
|
ContactType: contact.organization_name ? "COMPANY" : "PERSON",
|
|
36251
36298
|
...contact.organization_name ? { OrganizationName: contact.organization_name } : {}
|
|
36252
36299
|
};
|
|
36253
|
-
|
|
36300
|
+
}
|
|
36301
|
+
async function transferDomain(domain, authCode, contact, durationYears = 1, autoRenew = true, config2, options = {}) {
|
|
36302
|
+
const { domains } = makeClients(config2);
|
|
36303
|
+
const contactDetail = contactToRoute53Contact(contact);
|
|
36304
|
+
const result = await domains.send(new TransferDomainCommand({
|
|
36254
36305
|
DomainName: domain,
|
|
36306
|
+
AuthCode: authCode,
|
|
36255
36307
|
DurationInYears: durationYears,
|
|
36256
36308
|
AutoRenew: autoRenew,
|
|
36257
36309
|
AdminContact: contactDetail,
|
|
36258
36310
|
RegistrantContact: contactDetail,
|
|
36259
36311
|
TechContact: contactDetail,
|
|
36260
|
-
PrivacyProtectAdminContact: true,
|
|
36261
|
-
PrivacyProtectRegistrantContact: true,
|
|
36262
|
-
PrivacyProtectTechContact: true
|
|
36312
|
+
PrivacyProtectAdminContact: options.privacy_protected ?? true,
|
|
36313
|
+
PrivacyProtectRegistrantContact: options.privacy_protected ?? true,
|
|
36314
|
+
PrivacyProtectTechContact: options.privacy_protected ?? true,
|
|
36315
|
+
...options.nameservers?.length ? { Nameservers: options.nameservers.map((Name) => ({ Name })) } : {}
|
|
36263
36316
|
}));
|
|
36264
36317
|
return { operationId: result.OperationId ?? "" };
|
|
36265
36318
|
}
|
|
@@ -36274,14 +36327,60 @@ async function getRegistrationStatus(operationId, config2) {
|
|
|
36274
36327
|
}
|
|
36275
36328
|
async function getDomainDetail(domain, config2) {
|
|
36276
36329
|
const { domains } = makeClients(config2);
|
|
36277
|
-
const result = await
|
|
36330
|
+
const [result, summary] = await Promise.all([
|
|
36331
|
+
domains.send(new GetDomainDetailCommand({ DomainName: domain })),
|
|
36332
|
+
getDomainSummary(domain, config2)
|
|
36333
|
+
]);
|
|
36334
|
+
const privacy = result;
|
|
36278
36335
|
return {
|
|
36279
36336
|
domain: result.DomainName ?? domain,
|
|
36280
|
-
expiry: result.ExpirationDate?.toISOString() ?? "",
|
|
36281
|
-
auto_renew: result.AutoRenew ??
|
|
36282
|
-
transfer_lock: result.StatusList?.includes("TRANSFER_LOCK")
|
|
36337
|
+
expiry: result.ExpirationDate?.toISOString() ?? summary?.expiry ?? "",
|
|
36338
|
+
auto_renew: result.AutoRenew ?? summary?.auto_renew ?? null,
|
|
36339
|
+
transfer_lock: summary?.transfer_lock ?? (result.StatusList?.includes("TRANSFER_LOCK") ? true : null),
|
|
36283
36340
|
created: result.CreationDate?.toISOString() ?? "",
|
|
36284
|
-
|
|
36341
|
+
updated: result.UpdatedDate?.toISOString() ?? "",
|
|
36342
|
+
nameservers: (result.Nameservers ?? []).map((ns) => ns.Name ?? "").filter(Boolean),
|
|
36343
|
+
status_list: result.StatusList ?? [],
|
|
36344
|
+
registrar_name: result.RegistrarName,
|
|
36345
|
+
privacy_protected: privacy.RegistrantPrivacy ?? privacy.AdminPrivacy ?? privacy.TechPrivacy ?? null
|
|
36346
|
+
};
|
|
36347
|
+
}
|
|
36348
|
+
async function getDomainSummary(domain, config2) {
|
|
36349
|
+
let marker;
|
|
36350
|
+
do {
|
|
36351
|
+
const { domains } = makeClients(config2);
|
|
36352
|
+
const result = await domains.send(new ListDomainsCommand({ Marker: marker, MaxItems: 100 }));
|
|
36353
|
+
const summary = (result.Domains ?? []).find((item) => item.DomainName === domain);
|
|
36354
|
+
if (summary) {
|
|
36355
|
+
return {
|
|
36356
|
+
domain: summary.DomainName ?? domain,
|
|
36357
|
+
expiry: summary.Expiry?.toISOString() ?? "",
|
|
36358
|
+
auto_renew: summary.AutoRenew ?? false,
|
|
36359
|
+
transfer_lock: summary.TransferLock ?? false
|
|
36360
|
+
};
|
|
36361
|
+
}
|
|
36362
|
+
marker = result.NextPageMarker;
|
|
36363
|
+
} while (marker);
|
|
36364
|
+
return null;
|
|
36365
|
+
}
|
|
36366
|
+
async function requestTransferOutAuthCode(domain, config2) {
|
|
36367
|
+
const { domains } = makeClients(config2);
|
|
36368
|
+
const detail = await getDomainDetail(domain, config2);
|
|
36369
|
+
let transferLockDisabled = false;
|
|
36370
|
+
let transferLockOperationId = null;
|
|
36371
|
+
if (detail.transfer_lock) {
|
|
36372
|
+
const result = await domains.send(new DisableDomainTransferLockCommand({ DomainName: domain }));
|
|
36373
|
+
transferLockDisabled = true;
|
|
36374
|
+
transferLockOperationId = result.OperationId ?? null;
|
|
36375
|
+
}
|
|
36376
|
+
const authCodeResult = await domains.send(new RetrieveDomainAuthCodeCommand({ DomainName: domain }));
|
|
36377
|
+
if (!authCodeResult.AuthCode) {
|
|
36378
|
+
throw new Error("Route53 did not return a domain transfer authorization code");
|
|
36379
|
+
}
|
|
36380
|
+
return {
|
|
36381
|
+
auth_code: authCodeResult.AuthCode,
|
|
36382
|
+
transfer_lock_disabled: transferLockDisabled,
|
|
36383
|
+
transfer_lock_operation_id: transferLockOperationId
|
|
36285
36384
|
};
|
|
36286
36385
|
}
|
|
36287
36386
|
async function updateNameservers2(domain, nameservers, config2, client2) {
|
|
@@ -36319,9 +36418,22 @@ function cleanZoneId(id) {
|
|
|
36319
36418
|
function normalizeZoneId(id) {
|
|
36320
36419
|
return cleanZoneId(id.trim());
|
|
36321
36420
|
}
|
|
36322
|
-
|
|
36421
|
+
function normalizeNameserver(value) {
|
|
36422
|
+
return value.trim().toLowerCase().replace(/\.$/, "");
|
|
36423
|
+
}
|
|
36424
|
+
function nameserversMatch(a4, b4) {
|
|
36425
|
+
if (a4.length !== b4.length)
|
|
36426
|
+
return false;
|
|
36427
|
+
const left = [...new Set(a4.map(normalizeNameserver))].sort();
|
|
36428
|
+
const right = [...new Set(b4.map(normalizeNameserver))].sort();
|
|
36429
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
36430
|
+
}
|
|
36431
|
+
function cleanChangeId(id) {
|
|
36432
|
+
return id?.replace("/change/", "") || null;
|
|
36433
|
+
}
|
|
36434
|
+
async function createHostedZone(domain, comment, config2, options) {
|
|
36323
36435
|
const { route53 } = makeClients(config2);
|
|
36324
|
-
const callerRef = `domains-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
36436
|
+
const callerRef = options?.callerReference ?? `domains-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
36325
36437
|
const result = await route53.send(new CreateHostedZoneCommand({
|
|
36326
36438
|
Name: domain,
|
|
36327
36439
|
CallerReference: callerRef,
|
|
@@ -36368,7 +36480,38 @@ async function getHostedZone(hostedZoneId, config2) {
|
|
|
36368
36480
|
}
|
|
36369
36481
|
async function deleteHostedZone(hostedZoneId, config2) {
|
|
36370
36482
|
const { route53 } = makeClients(config2);
|
|
36371
|
-
|
|
36483
|
+
const zoneId = normalizeZoneId(hostedZoneId);
|
|
36484
|
+
const managedRecords = [];
|
|
36485
|
+
let nextName;
|
|
36486
|
+
let nextType;
|
|
36487
|
+
let nextIdentifier;
|
|
36488
|
+
do {
|
|
36489
|
+
const result = await route53.send(new ListResourceRecordSetsCommand({
|
|
36490
|
+
HostedZoneId: zoneId,
|
|
36491
|
+
StartRecordName: nextName,
|
|
36492
|
+
StartRecordType: nextType,
|
|
36493
|
+
StartRecordIdentifier: nextIdentifier
|
|
36494
|
+
}));
|
|
36495
|
+
managedRecords.push(...result.ResourceRecordSets?.filter((record) => record.Type !== "NS" && record.Type !== "SOA") ?? []);
|
|
36496
|
+
nextName = result.IsTruncated ? result.NextRecordName : undefined;
|
|
36497
|
+
nextType = result.IsTruncated ? result.NextRecordType : undefined;
|
|
36498
|
+
nextIdentifier = result.IsTruncated ? result.NextRecordIdentifier : undefined;
|
|
36499
|
+
} while (nextName && nextType);
|
|
36500
|
+
for (let index = 0;index < managedRecords.length; index += 100) {
|
|
36501
|
+
const batch = managedRecords.slice(index, index + 100);
|
|
36502
|
+
if (batch.length === 0)
|
|
36503
|
+
continue;
|
|
36504
|
+
await route53.send(new ChangeResourceRecordSetsCommand({
|
|
36505
|
+
HostedZoneId: zoneId,
|
|
36506
|
+
ChangeBatch: {
|
|
36507
|
+
Changes: batch.map((record) => ({
|
|
36508
|
+
Action: "DELETE",
|
|
36509
|
+
ResourceRecordSet: record
|
|
36510
|
+
}))
|
|
36511
|
+
}
|
|
36512
|
+
}));
|
|
36513
|
+
}
|
|
36514
|
+
await route53.send(new DeleteHostedZoneCommand({ Id: zoneId }));
|
|
36372
36515
|
}
|
|
36373
36516
|
async function findHostedZoneByDomain(domain, config2) {
|
|
36374
36517
|
const zones = await listHostedZones(config2);
|
|
@@ -36383,6 +36526,24 @@ async function findHostedZoneByDomain(domain, config2) {
|
|
|
36383
36526
|
}
|
|
36384
36527
|
return candidates[0] ?? null;
|
|
36385
36528
|
}
|
|
36529
|
+
async function findHostedZoneByNameservers(domain, nameservers, config2) {
|
|
36530
|
+
if (!nameservers.length)
|
|
36531
|
+
return null;
|
|
36532
|
+
const { route53 } = makeClients(config2);
|
|
36533
|
+
const result = await route53.send(new ListHostedZonesByNameCommand({ DNSName: domain }));
|
|
36534
|
+
const zones = (result.HostedZones ?? []).filter((zone) => zone.Name?.replace(/\.$/, "") === domain && !zone.Config?.PrivateZone);
|
|
36535
|
+
for (const zone of zones) {
|
|
36536
|
+
const id = cleanZoneId(zone.Id ?? "");
|
|
36537
|
+
if (!id)
|
|
36538
|
+
continue;
|
|
36539
|
+
const detail = await getHostedZone(id, config2);
|
|
36540
|
+
const delegatedNameservers = detail.name_servers ?? [];
|
|
36541
|
+
if (nameserversMatch(delegatedNameservers, nameservers)) {
|
|
36542
|
+
return { ...detail, id, name_servers: delegatedNameservers };
|
|
36543
|
+
}
|
|
36544
|
+
}
|
|
36545
|
+
return null;
|
|
36546
|
+
}
|
|
36386
36547
|
function rrsToRecord(rrs) {
|
|
36387
36548
|
if (rrs.AliasTarget) {
|
|
36388
36549
|
return {
|
|
@@ -36446,36 +36607,44 @@ async function listRecords(hostedZoneId, config2) {
|
|
|
36446
36607
|
} while (nextName);
|
|
36447
36608
|
return records;
|
|
36448
36609
|
}
|
|
36449
|
-
async function upsertRecord(hostedZoneId, record, config2) {
|
|
36610
|
+
async function upsertRecord(hostedZoneId, record, config2, options) {
|
|
36450
36611
|
const { route53 } = makeClients(config2);
|
|
36451
|
-
await route53.send(new ChangeResourceRecordSetsCommand({
|
|
36612
|
+
const result = await route53.send(new ChangeResourceRecordSetsCommand({
|
|
36452
36613
|
HostedZoneId: normalizeZoneId(hostedZoneId),
|
|
36453
36614
|
ChangeBatch: {
|
|
36615
|
+
...options?.comment ? { Comment: options.comment } : {},
|
|
36454
36616
|
Changes: [{ Action: "UPSERT", ResourceRecordSet: recordToRrs(record) }]
|
|
36455
36617
|
}
|
|
36456
36618
|
}));
|
|
36619
|
+
return { changeId: cleanChangeId(result.ChangeInfo?.Id) };
|
|
36457
36620
|
}
|
|
36458
|
-
async function deleteRecord(hostedZoneId, record, config2) {
|
|
36621
|
+
async function deleteRecord(hostedZoneId, record, config2, options) {
|
|
36459
36622
|
const { route53 } = makeClients(config2);
|
|
36460
|
-
await route53.send(new ChangeResourceRecordSetsCommand({
|
|
36623
|
+
const result = await route53.send(new ChangeResourceRecordSetsCommand({
|
|
36461
36624
|
HostedZoneId: normalizeZoneId(hostedZoneId),
|
|
36462
36625
|
ChangeBatch: {
|
|
36626
|
+
...options?.comment ? { Comment: options.comment } : {},
|
|
36463
36627
|
Changes: [{ Action: "DELETE", ResourceRecordSet: recordToRrs(record) }]
|
|
36464
36628
|
}
|
|
36465
36629
|
}));
|
|
36630
|
+
return { changeId: cleanChangeId(result.ChangeInfo?.Id) };
|
|
36466
36631
|
}
|
|
36467
|
-
async function upsertRecords(hostedZoneId, records, config2) {
|
|
36632
|
+
async function upsertRecords(hostedZoneId, records, config2, options) {
|
|
36468
36633
|
if (records.length === 0)
|
|
36469
|
-
return;
|
|
36634
|
+
return { changeId: null };
|
|
36470
36635
|
const { route53 } = makeClients(config2);
|
|
36471
36636
|
const changes = records.map((r4) => ({
|
|
36472
36637
|
Action: "UPSERT",
|
|
36473
36638
|
ResourceRecordSet: recordToRrs(r4)
|
|
36474
36639
|
}));
|
|
36475
|
-
await route53.send(new ChangeResourceRecordSetsCommand({
|
|
36640
|
+
const result = await route53.send(new ChangeResourceRecordSetsCommand({
|
|
36476
36641
|
HostedZoneId: normalizeZoneId(hostedZoneId),
|
|
36477
|
-
ChangeBatch: {
|
|
36642
|
+
ChangeBatch: {
|
|
36643
|
+
...options?.comment ? { Comment: options.comment } : {},
|
|
36644
|
+
Changes: changes
|
|
36645
|
+
}
|
|
36478
36646
|
}));
|
|
36647
|
+
return { changeId: cleanChangeId(result.ChangeInfo?.Id) };
|
|
36479
36648
|
}
|
|
36480
36649
|
function createRoute53Provider(config2) {
|
|
36481
36650
|
const cfg = config2 ?? getConfig2();
|
|
@@ -36538,7 +36707,7 @@ function createRoute53Provider(config2) {
|
|
|
36538
36707
|
expires: detail.expiry,
|
|
36539
36708
|
nameservers: detail.nameservers,
|
|
36540
36709
|
status: "active",
|
|
36541
|
-
auto_renew: detail.auto_renew
|
|
36710
|
+
auto_renew: detail.auto_renew ?? false
|
|
36542
36711
|
};
|
|
36543
36712
|
},
|
|
36544
36713
|
async registerDomain(domain, contact, options = {}) {
|
|
@@ -36653,6 +36822,7 @@ function createRoute53Provider(config2) {
|
|
|
36653
36822
|
var init_route53 = __esm(() => {
|
|
36654
36823
|
init_dist_es12();
|
|
36655
36824
|
init_dist_es13();
|
|
36825
|
+
init_dist_es9();
|
|
36656
36826
|
});
|
|
36657
36827
|
|
|
36658
36828
|
// src/lib/env-aliases.ts
|
|
@@ -36689,7 +36859,16 @@ function providerEnvNames(provider) {
|
|
|
36689
36859
|
case "cloudflare":
|
|
36690
36860
|
return flattenEnvNames([CLOUDFLARE_ENV.apiToken, CLOUDFLARE_ENV.apiKey, CLOUDFLARE_ENV.email, CLOUDFLARE_ENV.accountId]);
|
|
36691
36861
|
case "route53":
|
|
36692
|
-
return [
|
|
36862
|
+
return flattenEnvNames([
|
|
36863
|
+
ROUTE53_ENV.profile,
|
|
36864
|
+
ROUTE53_ENV.accessKeyId,
|
|
36865
|
+
ROUTE53_ENV.secretAccessKey,
|
|
36866
|
+
ROUTE53_ENV.sessionToken,
|
|
36867
|
+
ROUTE53_ENV.region,
|
|
36868
|
+
ROUTE53_ENV.webIdentityTokenFile,
|
|
36869
|
+
ROUTE53_ENV.roleArn,
|
|
36870
|
+
ROUTE53_ENV.containerCredentials
|
|
36871
|
+
]);
|
|
36693
36872
|
default:
|
|
36694
36873
|
return [];
|
|
36695
36874
|
}
|
|
@@ -36709,13 +36888,18 @@ function hasProviderCredentials(provider, env = process.env) {
|
|
|
36709
36888
|
const keyMode = hasEveryEnv(env, [CLOUDFLARE_ENV.apiKey, CLOUDFLARE_ENV.email]);
|
|
36710
36889
|
return tokenMode || keyMode;
|
|
36711
36890
|
}
|
|
36712
|
-
case "route53":
|
|
36713
|
-
|
|
36891
|
+
case "route53": {
|
|
36892
|
+
const profileMode = !!firstEnv(env, ROUTE53_ENV.profile);
|
|
36893
|
+
const keyMode = hasEveryEnv(env, [ROUTE53_ENV.accessKeyId, ROUTE53_ENV.secretAccessKey]);
|
|
36894
|
+
const webIdentityMode = hasEveryEnv(env, [ROUTE53_ENV.webIdentityTokenFile, ROUTE53_ENV.roleArn]);
|
|
36895
|
+
const containerMode = !!firstEnv(env, ROUTE53_ENV.containerCredentials);
|
|
36896
|
+
return profileMode || keyMode || webIdentityMode || containerMode;
|
|
36897
|
+
}
|
|
36714
36898
|
default:
|
|
36715
36899
|
return false;
|
|
36716
36900
|
}
|
|
36717
36901
|
}
|
|
36718
|
-
var NAMECHEAP_ENV, GODADDY_ENV, BRANDSIGHT_ENV, SEDO_ENV, CLOUDFLARE_ENV;
|
|
36902
|
+
var NAMECHEAP_ENV, GODADDY_ENV, BRANDSIGHT_ENV, SEDO_ENV, CLOUDFLARE_ENV, ROUTE53_ENV;
|
|
36719
36903
|
var init_env_aliases = __esm(() => {
|
|
36720
36904
|
NAMECHEAP_ENV = {
|
|
36721
36905
|
apiKey: ["NAMECHEAP_API_KEY"],
|
|
@@ -36745,6 +36929,19 @@ var init_env_aliases = __esm(() => {
|
|
|
36745
36929
|
email: ["CLOUDFLARE_EMAIL"],
|
|
36746
36930
|
accountId: ["CLOUDFLARE_ACCOUNT_ID"]
|
|
36747
36931
|
};
|
|
36932
|
+
ROUTE53_ENV = {
|
|
36933
|
+
accessKeyId: ["ROUTE53_ACCESS_KEY_ID", "AWS_ACCESS_KEY_ID"],
|
|
36934
|
+
secretAccessKey: ["ROUTE53_SECRET_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY"],
|
|
36935
|
+
sessionToken: ["ROUTE53_SESSION_TOKEN", "AWS_SESSION_TOKEN"],
|
|
36936
|
+
profile: ["ROUTE53_AWS_PROFILE", "AWS_PROFILE"],
|
|
36937
|
+
region: ["ROUTE53_REGION", "ROUTE53_AWS_REGION", "AWS_REGION"],
|
|
36938
|
+
webIdentityTokenFile: ["AWS_WEB_IDENTITY_TOKEN_FILE"],
|
|
36939
|
+
roleArn: ["AWS_ROLE_ARN"],
|
|
36940
|
+
containerCredentials: [
|
|
36941
|
+
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
|
|
36942
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI"
|
|
36943
|
+
]
|
|
36944
|
+
};
|
|
36748
36945
|
});
|
|
36749
36946
|
|
|
36750
36947
|
// src/lib/cloudflare-auth.ts
|
|
@@ -36774,12 +36971,12 @@ var init_cloudflare_auth = __esm(() => {
|
|
|
36774
36971
|
function getConfig3() {
|
|
36775
36972
|
return resolveCloudflareConfig();
|
|
36776
36973
|
}
|
|
36777
|
-
function
|
|
36974
|
+
function checkCredentials(cfg) {
|
|
36778
36975
|
cloudflareAuthHeaders(cfg);
|
|
36779
36976
|
}
|
|
36780
36977
|
async function cfFetch(path, opts = {}) {
|
|
36781
36978
|
const cfg = opts.config ?? getConfig3();
|
|
36782
|
-
|
|
36979
|
+
checkCredentials(cfg);
|
|
36783
36980
|
const res = await fetch(`${CF_BASE}${path}`, {
|
|
36784
36981
|
method: opts.method ?? "GET",
|
|
36785
36982
|
headers: {
|
|
@@ -37689,12 +37886,16 @@ __export(exports_sedo, {
|
|
|
37689
37886
|
resolveSedoConfig: () => resolveSedoConfig,
|
|
37690
37887
|
removeDomainFromSedo: () => removeDomainFromSedo,
|
|
37691
37888
|
recordSedoPurchase: () => recordSedoPurchase,
|
|
37889
|
+
parseSedoSearchResponse: () => parseSedoSearchResponse,
|
|
37890
|
+
parseSedoFault: () => parseSedoFault,
|
|
37692
37891
|
listSedoPortfolio: () => listSedoPortfolio,
|
|
37693
37892
|
getSedoConfig: () => getSedoConfig,
|
|
37694
37893
|
editDomainOnSedo: () => editDomainOnSedo,
|
|
37695
37894
|
checkSedoStatus: () => checkSedoStatus,
|
|
37696
37895
|
checkSedoBlacklist: () => checkSedoBlacklist,
|
|
37697
|
-
|
|
37896
|
+
buildSedoSearchParams: () => buildSedoSearchParams,
|
|
37897
|
+
addDomainToSedo: () => addDomainToSedo,
|
|
37898
|
+
SEDO_CURRENCY_CODES: () => SEDO_CURRENCY_CODES
|
|
37698
37899
|
});
|
|
37699
37900
|
function resolveSedoConfig(env = process.env) {
|
|
37700
37901
|
return {
|
|
@@ -37721,17 +37922,17 @@ function sedoCapability(env = process.env) {
|
|
|
37721
37922
|
notes: configured ? "Credentials present; Sedo supports marketplace search, portfolio listing, listing edits, and recorded purchases, but not registrar DNS or direct self-serve registration through this CLI." : "Not configured; Sedo is marketplace-only here, not registrar DNS."
|
|
37722
37923
|
};
|
|
37723
37924
|
}
|
|
37724
|
-
function
|
|
37925
|
+
function buildAuthParams(config2) {
|
|
37725
37926
|
return {
|
|
37726
|
-
partnerid:
|
|
37727
|
-
signkey:
|
|
37728
|
-
username:
|
|
37729
|
-
password:
|
|
37927
|
+
partnerid: config2.partnerId,
|
|
37928
|
+
signkey: config2.signKey,
|
|
37929
|
+
username: config2.username,
|
|
37930
|
+
password: config2.password
|
|
37730
37931
|
};
|
|
37731
37932
|
}
|
|
37732
|
-
async function
|
|
37933
|
+
async function sedoRequestRaw(action, config2, extraParams = {}) {
|
|
37733
37934
|
const params = new URLSearchParams({
|
|
37734
|
-
...
|
|
37935
|
+
...buildAuthParams(config2),
|
|
37735
37936
|
output_method: "xml",
|
|
37736
37937
|
...Object.fromEntries(Object.entries(extraParams).map(([k4, v2]) => [k4, String(v2)]))
|
|
37737
37938
|
});
|
|
@@ -37740,9 +37941,23 @@ async function sedoRequest(action, config2, extraParams = {}) {
|
|
|
37740
37941
|
if (!resp.ok) {
|
|
37741
37942
|
throw new Error(`Sedo API ${action} failed: ${resp.status} ${resp.statusText}`);
|
|
37742
37943
|
}
|
|
37743
|
-
|
|
37944
|
+
return resp.text();
|
|
37945
|
+
}
|
|
37946
|
+
async function sedoRequest(action, config2, extraParams = {}) {
|
|
37947
|
+
const text = await sedoRequestRaw(action, config2, extraParams);
|
|
37948
|
+
const fault = parseSedoFault(text);
|
|
37949
|
+
if (fault) {
|
|
37950
|
+
throw new Error(`Sedo API ${action} fault ${fault.code}: ${fault.message}`);
|
|
37951
|
+
}
|
|
37744
37952
|
return parseSedoXml(text);
|
|
37745
37953
|
}
|
|
37954
|
+
function parseSedoFault(xml) {
|
|
37955
|
+
if (!/<SEDOFAULT\b/i.test(xml))
|
|
37956
|
+
return null;
|
|
37957
|
+
const code = xml.match(/<faultcode[^>]*>([^<]*)<\/faultcode>/i)?.[1]?.trim() || "UNKNOWN";
|
|
37958
|
+
const message = xml.match(/<faultstring[^>]*>([^<]*)<\/faultstring>/i)?.[1]?.trim() || code;
|
|
37959
|
+
return { code, message };
|
|
37960
|
+
}
|
|
37746
37961
|
function parseSedoXml(xml) {
|
|
37747
37962
|
const result = {};
|
|
37748
37963
|
const itemMatches = xml.match(/<item[^>]*>([\s\S]*?)<\/item>/g);
|
|
@@ -37768,11 +37983,12 @@ function parseSedoItemXml(itemXml) {
|
|
|
37768
37983
|
}
|
|
37769
37984
|
return obj;
|
|
37770
37985
|
}
|
|
37771
|
-
|
|
37772
|
-
const config2 = getSedoConfig();
|
|
37986
|
+
function buildSedoSearchParams(query, options = {}) {
|
|
37773
37987
|
const params = {
|
|
37774
|
-
|
|
37775
|
-
|
|
37988
|
+
keyword: query,
|
|
37989
|
+
kwtype: options.kwtype || "C",
|
|
37990
|
+
resultsize: options.limit || 100,
|
|
37991
|
+
language: options.language || "en"
|
|
37776
37992
|
};
|
|
37777
37993
|
if (options.tld)
|
|
37778
37994
|
params.tld = options.tld;
|
|
@@ -37780,20 +37996,35 @@ async function searchSedoDomains(query, options = {}) {
|
|
|
37780
37996
|
params.price_min = options.minPrice;
|
|
37781
37997
|
if (options.maxPrice)
|
|
37782
37998
|
params.price_max = options.maxPrice;
|
|
37783
|
-
|
|
37999
|
+
return params;
|
|
38000
|
+
}
|
|
38001
|
+
function parseSedoSearchResponse(xml) {
|
|
38002
|
+
const fault = parseSedoFault(xml);
|
|
38003
|
+
if (fault) {
|
|
38004
|
+
throw new Error(`Sedo DomainSearch fault ${fault.code}: ${fault.message}`);
|
|
38005
|
+
}
|
|
38006
|
+
const response = parseSedoXml(xml);
|
|
37784
38007
|
const items = response.items || [];
|
|
37785
|
-
const domains = items.map((item) =>
|
|
37786
|
-
|
|
37787
|
-
|
|
37788
|
-
|
|
37789
|
-
|
|
37790
|
-
|
|
37791
|
-
|
|
37792
|
-
|
|
37793
|
-
|
|
37794
|
-
|
|
37795
|
-
|
|
37796
|
-
|
|
38008
|
+
const domains = items.map((item) => {
|
|
38009
|
+
const rawPrice = item.price;
|
|
38010
|
+
const price = rawPrice !== undefined ? parseFloat(rawPrice) : undefined;
|
|
38011
|
+
const currencyCode = item.currency;
|
|
38012
|
+
const currency = currencyCode !== undefined ? SEDO_CURRENCY_CODES[currencyCode] || currencyCode : undefined;
|
|
38013
|
+
return {
|
|
38014
|
+
domain: item.domain || "",
|
|
38015
|
+
forSale: true,
|
|
38016
|
+
price: price && price > 0 ? price : undefined,
|
|
38017
|
+
currency: price && price > 0 ? currency : undefined,
|
|
38018
|
+
status: item.type || undefined
|
|
38019
|
+
};
|
|
38020
|
+
});
|
|
38021
|
+
return { domains, total: domains.length };
|
|
38022
|
+
}
|
|
38023
|
+
async function searchSedoDomains(query, options = {}) {
|
|
38024
|
+
const config2 = getSedoConfig();
|
|
38025
|
+
const params = buildSedoSearchParams(query, options);
|
|
38026
|
+
const xml = await sedoRequestRaw("DomainSearch", config2, params);
|
|
38027
|
+
return parseSedoSearchResponse(xml);
|
|
37797
38028
|
}
|
|
37798
38029
|
async function searchHealthDomains(options = {}) {
|
|
37799
38030
|
return searchSedoDomains("health", { ...options, limit: options.limit || 100 });
|
|
@@ -37917,11 +38148,16 @@ function recordSedoPurchase(domain, price, orderId) {
|
|
|
37917
38148
|
});
|
|
37918
38149
|
return created;
|
|
37919
38150
|
}
|
|
37920
|
-
var BASE_URL = "https://api.sedo.com/api/v1/";
|
|
38151
|
+
var BASE_URL = "https://api.sedo.com/api/v1/", SEDO_CURRENCY_CODES;
|
|
37921
38152
|
var init_sedo = __esm(() => {
|
|
37922
38153
|
init_env_aliases();
|
|
37923
38154
|
init_domains();
|
|
37924
38155
|
init_domain_history();
|
|
38156
|
+
SEDO_CURRENCY_CODES = {
|
|
38157
|
+
"0": "EUR",
|
|
38158
|
+
"1": "USD",
|
|
38159
|
+
"2": "GBP"
|
|
38160
|
+
};
|
|
37925
38161
|
});
|
|
37926
38162
|
|
|
37927
38163
|
// src/lib/creds-check.ts
|
|
@@ -37937,12 +38173,16 @@ function missingStatus(provider, detail) {
|
|
|
37937
38173
|
}
|
|
37938
38174
|
function checkProvisioningCredentials(env = process.env) {
|
|
37939
38175
|
const out = [];
|
|
37940
|
-
const
|
|
37941
|
-
const
|
|
37942
|
-
|
|
37943
|
-
|
|
38176
|
+
const awsProfile = firstEnv(env, ROUTE53_ENV.profile);
|
|
38177
|
+
const awsAccessKey = firstEnv(env, ROUTE53_ENV.accessKeyId);
|
|
38178
|
+
const awsSecretKey = firstEnv(env, ROUTE53_ENV.secretAccessKey);
|
|
38179
|
+
const hasAwsKeys = !!(awsAccessKey && awsSecretKey);
|
|
38180
|
+
const hasWebIdentity = !!(firstEnv(env, ROUTE53_ENV.webIdentityTokenFile) && firstEnv(env, ROUTE53_ENV.roleArn));
|
|
38181
|
+
const hasContainerCredentials = !!firstEnv(env, ROUTE53_ENV.containerCredentials);
|
|
38182
|
+
if (awsProfile || hasAwsKeys || hasWebIdentity || hasContainerCredentials) {
|
|
38183
|
+
out.push(configuredStatus("route53", awsProfile ? `profile:${awsProfile.value}` : hasAwsKeys ? "access-keys" : hasWebIdentity ? "web-identity" : "container-credentials", "AWS credentials present (Route 53 Domains API uses us-east-1)"));
|
|
37944
38184
|
} else {
|
|
37945
|
-
out.push(missingStatus("route53", "Set AWS_PROFILE or
|
|
38185
|
+
out.push(missingStatus("route53", "Set ROUTE53_AWS_PROFILE/AWS_PROFILE, ROUTE53_ACCESS_KEY_ID+ROUTE53_SECRET_ACCESS_KEY, or AWS provider-chain credentials"));
|
|
37946
38186
|
}
|
|
37947
38187
|
const cf = resolveCloudflareConfig(env);
|
|
37948
38188
|
const cfMode = cf.apiToken ? "token" : cf.apiKey && cf.email ? "global-key" : "none";
|
|
@@ -38066,7 +38306,7 @@ function registerSedoCommand(program2) {
|
|
|
38066
38306
|
}
|
|
38067
38307
|
console.log(`Sedo marketplace \u2014 "${keyword}" (${result.total} total):`);
|
|
38068
38308
|
for (const d4 of result.domains) {
|
|
38069
|
-
const price = d4.price ? ` \u2014
|
|
38309
|
+
const price = d4.price ? ` \u2014 ${d4.price.toLocaleString()} ${d4.currency || ""}`.trimEnd() : " \u2014 make offer";
|
|
38070
38310
|
const premium = d4.isPremium ? " [PREMIUM]" : "";
|
|
38071
38311
|
console.log(` ${d4.domain}${price}${premium}`);
|
|
38072
38312
|
}
|
|
@@ -49184,7 +49424,7 @@ init_route53();
|
|
|
49184
49424
|
import { readFileSync as readFileSync6 } from "fs";
|
|
49185
49425
|
|
|
49186
49426
|
// src/lib/zone-setup.ts
|
|
49187
|
-
function
|
|
49427
|
+
function nameserversMatch2(a4, b4) {
|
|
49188
49428
|
const norm = (ns) => new Set(ns.map((n2) => n2.trim().toLowerCase().replace(/\.$/, "")));
|
|
49189
49429
|
const sa = norm(a4);
|
|
49190
49430
|
const sb = norm(b4);
|
|
@@ -49211,7 +49451,7 @@ async function setupDomainZone(domain, deps) {
|
|
|
49211
49451
|
}
|
|
49212
49452
|
let nsUpdated = false;
|
|
49213
49453
|
const registrarNs = await deps.getRegistrarNs(domain);
|
|
49214
|
-
if (!
|
|
49454
|
+
if (!nameserversMatch2(registrarNs, zone.name_servers)) {
|
|
49215
49455
|
await deps.setRegistrarNs(domain, zone.name_servers);
|
|
49216
49456
|
nsUpdated = true;
|
|
49217
49457
|
log("ns_aligned", { domain, zoneId: zone.id, nameservers: zone.name_servers });
|