@hasna/domains 0.0.25 → 0.0.26

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.
@@ -54,14 +54,45 @@ export interface SedoCapability {
54
54
  }
55
55
  export declare function sedoCapability(env?: Record<string, string | undefined>): SedoCapability;
56
56
  /**
57
- * Search for domains for sale on Sedo.
57
+ * Sedo encodes currency as an integer code in API responses
58
+ * (see DomainInsert / DomainSearch docs): 0 = EUR, 1 = USD, 2 = GBP.
59
+ */
60
+ export declare const SEDO_CURRENCY_CODES: Record<string, string>;
61
+ export interface SedoFault {
62
+ code: string;
63
+ message: string;
64
+ }
65
+ /**
66
+ * Detect and parse a Sedo <SEDOFAULT> error envelope.
67
+ * Returns null when the response is not a fault.
58
68
  */
59
- export declare function searchSedoDomains(query: string, options?: {
69
+ export declare function parseSedoFault(xml: string): SedoFault | null;
70
+ export interface SedoSearchOptions {
60
71
  tld?: string;
61
72
  limit?: number;
62
73
  minPrice?: number;
63
74
  maxPrice?: number;
64
- }): Promise<SedoSearchResult>;
75
+ /** Keyword match mode: B=begins with, C=contains, E=ends with. Default C. */
76
+ kwtype?: "B" | "C" | "E";
77
+ /** ISO 639-1 result language. Default "en". */
78
+ language?: string;
79
+ }
80
+ /**
81
+ * Build the Sedo DomainSearch request params using the documented
82
+ * parameter names. The marketplace search action is `keyword` based —
83
+ * `searchword`/`limit` are NOT recognized and yield an E1201 fault.
84
+ * See https://api.sedo.com/apidocs/v1/Basic/functions/sedoapi_DomainSearch.html
85
+ */
86
+ export declare function buildSedoSearchParams(query: string, options?: SedoSearchOptions): Record<string, unknown>;
87
+ /**
88
+ * Parse a Sedo <SEDOSEARCH> XML response into domain listings.
89
+ * Throws if the response is a <SEDOFAULT> error envelope.
90
+ */
91
+ export declare function parseSedoSearchResponse(xml: string): SedoSearchResult;
92
+ /**
93
+ * Search for domains for sale on Sedo.
94
+ */
95
+ export declare function searchSedoDomains(query: string, options?: SedoSearchOptions): Promise<SedoSearchResult>;
65
96
  /**
66
97
  * Search health/tech domains on Sedo — convenience method.
67
98
  */
@@ -1 +1 @@
1
- {"version":3,"file":"sedo.d.ts","sourceRoot":"","sources":["../../src/lib/sedo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sedo.d.ts","sourceRoot":"","sources":["../../src/lib/sedo.ts"],"names":[],"mappings":"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"}
package/dist/mcp/index.js CHANGED
@@ -11786,7 +11786,7 @@ var init_bowser = __esm(() => {
11786
11786
 
11787
11787
  // node_modules/@aws-sdk/core/dist-cjs/submodules/client/index.js
11788
11788
  var require_client2 = __commonJS((exports) => {
11789
- var __dirname = "/home/hasna/Workspace/hasna/opensource/open-domains/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
11789
+ var __dirname = "/home/hasna/workspace/hasna/opensource/open-domains/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
11790
11790
  var retry = require_retry();
11791
11791
  var protocols = require_protocols();
11792
11792
  var lambdaInvokeStore = require_invoke_store();
@@ -41227,28 +41227,20 @@ class UpdateDomainNameserversCommand extends import_client46.Command.classBuilde
41227
41227
  }
41228
41228
 
41229
41229
  // src/lib/route53.ts
41230
+ init_dist_es9();
41230
41231
  function getConfig2() {
41231
41232
  return {
41232
- region: process.env["AWS_REGION"] || "us-east-1",
41233
- accessKeyId: process.env["AWS_ACCESS_KEY_ID"],
41234
- secretAccessKey: process.env["AWS_SECRET_ACCESS_KEY"],
41235
- sessionToken: process.env["AWS_SESSION_TOKEN"]
41233
+ region: process.env["ROUTE53_REGION"] || process.env["ROUTE53_AWS_REGION"] || process.env["AWS_REGION"] || "us-east-1",
41234
+ accessKeyId: process.env["ROUTE53_ACCESS_KEY_ID"] || process.env["AWS_ACCESS_KEY_ID"],
41235
+ secretAccessKey: process.env["ROUTE53_SECRET_ACCESS_KEY"] || process.env["AWS_SECRET_ACCESS_KEY"],
41236
+ sessionToken: process.env["ROUTE53_SESSION_TOKEN"] || process.env["AWS_SESSION_TOKEN"],
41237
+ profile: process.env["ROUTE53_AWS_PROFILE"] || process.env["AWS_PROFILE"]
41236
41238
  };
41237
41239
  }
41238
- function checkCredentials(cfg) {
41239
- if (cfg.accessKeyId && cfg.secretAccessKey)
41240
- return;
41241
- const hasEnv = !!(process.env["AWS_ACCESS_KEY_ID"] && process.env["AWS_SECRET_ACCESS_KEY"]);
41242
- const hasProfile = !!process.env["AWS_PROFILE"];
41243
- if (!hasEnv && !hasProfile) {
41244
- throw new Error("AWS credentials not configured. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (or AWS_PROFILE) environment variables.");
41245
- }
41246
- }
41247
41240
  function makeClients(config2) {
41248
41241
  const cfg = config2 ?? getConfig2();
41249
- checkCredentials(cfg);
41250
41242
  const region = cfg.region || "us-east-1";
41251
- const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey, sessionToken: cfg.sessionToken } : undefined;
41243
+ const credentials = cfg.accessKeyId && cfg.secretAccessKey ? { accessKeyId: cfg.accessKeyId, secretAccessKey: cfg.secretAccessKey, sessionToken: cfg.sessionToken } : cfg.profile ? fromIni({ profile: cfg.profile }) : undefined;
41252
41244
  return {
41253
41245
  route53: new Route53Client({ region, credentials }),
41254
41246
  domains: new Route53DomainsClient({ region: "us-east-1", credentials })
@@ -41259,51 +41251,77 @@ async function checkAvailability3(domain, config2) {
41259
41251
  const result = await domains.send(new CheckDomainAvailabilityCommand({ DomainName: domain }));
41260
41252
  const availability = {
41261
41253
  domain,
41262
- available: result.Availability === "AVAILABLE"
41254
+ available: result.Availability === "AVAILABLE",
41255
+ availability: result.Availability ?? "UNKNOWN"
41263
41256
  };
41264
- try {
41265
- const tld = domain.split(".").slice(1).join(".");
41266
- const prices = await domains.send(new ListPricesCommand({ Tld: tld, MaxItems: 1 }));
41267
- const price = prices.Prices?.[0];
41268
- if (price) {
41269
- availability.currency = price.RegistrationPrice?.Currency ?? price.RenewalPrice?.Currency ?? price.TransferPrice?.Currency;
41270
- if (price.RegistrationPrice?.Price != null)
41271
- availability.price = price.RegistrationPrice.Price.toString();
41272
- if (price.RenewalPrice?.Price != null)
41273
- availability.renewal_price = price.RenewalPrice.Price.toString();
41274
- if (price.TransferPrice?.Price != null)
41275
- availability.transfer_price = price.TransferPrice.Price.toString();
41276
- }
41277
- } catch {}
41257
+ if (availability.available) {
41258
+ try {
41259
+ const tld = domain.split(".").slice(1).join(".");
41260
+ const price = await getTldPrice(tld, config2);
41261
+ if (price) {
41262
+ availability.currency = price.currency;
41263
+ availability.price = price.registration_price;
41264
+ availability.renewal_price = price.renewal_price;
41265
+ availability.transfer_price = price.transfer_price;
41266
+ }
41267
+ } catch {}
41268
+ }
41278
41269
  return availability;
41279
41270
  }
41280
- async function registerDomain2(domain, contact, durationYears = 1, autoRenew = true, config2) {
41271
+ function normalizeTld(tld) {
41272
+ return tld.trim().replace(/^\./, "");
41273
+ }
41274
+ function priceString(value) {
41275
+ return value == null ? undefined : value.toString();
41276
+ }
41277
+ function tldPriceFromRoute53Price(tld, price) {
41278
+ return {
41279
+ tld: price.Name || tld,
41280
+ registration_price: priceString(price.RegistrationPrice?.Price),
41281
+ renewal_price: priceString(price.RenewalPrice?.Price),
41282
+ transfer_price: priceString(price.TransferPrice?.Price),
41283
+ currency: price.RegistrationPrice?.Currency ?? price.RenewalPrice?.Currency ?? price.TransferPrice?.Currency
41284
+ };
41285
+ }
41286
+ async function getTldPrice(tld, config2) {
41281
41287
  const { domains } = makeClients(config2);
41282
- const contactDetail = {
41288
+ const normalized = normalizeTld(tld);
41289
+ const prices = await domains.send(new ListPricesCommand({ Tld: normalized, MaxItems: 1 }));
41290
+ const price = prices.Prices?.[0];
41291
+ return price ? tldPriceFromRoute53Price(normalized, price) : null;
41292
+ }
41293
+ async function registerDomain2(domain, contact, durationYears = 1, autoRenew = true, config2, options = {}) {
41294
+ const { domains } = makeClients(config2);
41295
+ const contactDetail = contactToRoute53Contact(contact);
41296
+ const result = await domains.send(new RegisterDomainCommand({
41297
+ DomainName: domain,
41298
+ DurationInYears: durationYears,
41299
+ AutoRenew: autoRenew,
41300
+ AdminContact: contactDetail,
41301
+ RegistrantContact: contactDetail,
41302
+ TechContact: contactDetail,
41303
+ PrivacyProtectAdminContact: options.privacy_protected ?? true,
41304
+ PrivacyProtectRegistrantContact: options.privacy_protected ?? true,
41305
+ PrivacyProtectTechContact: options.privacy_protected ?? true,
41306
+ ...options.nameservers?.length ? { Nameservers: options.nameservers.map((Name) => ({ Name })) } : {}
41307
+ }));
41308
+ return { operationId: result.OperationId ?? "" };
41309
+ }
41310
+ function contactToRoute53Contact(contact) {
41311
+ return {
41283
41312
  FirstName: contact.first_name,
41284
41313
  LastName: contact.last_name,
41285
41314
  Email: contact.email,
41286
41315
  PhoneNumber: contact.phone,
41287
41316
  AddressLine1: contact.address_line_1,
41317
+ ...contact.address_line_2 ? { AddressLine2: contact.address_line_2 } : {},
41288
41318
  City: contact.city,
41289
- State: contact.state,
41290
- CountryCode: contact.country_code,
41319
+ ...contact.state ? { State: contact.state } : {},
41320
+ CountryCode: contact.country_code.toUpperCase(),
41291
41321
  ZipCode: contact.zip_code,
41292
41322
  ContactType: contact.organization_name ? "COMPANY" : "PERSON",
41293
41323
  ...contact.organization_name ? { OrganizationName: contact.organization_name } : {}
41294
41324
  };
41295
- const result = await domains.send(new RegisterDomainCommand({
41296
- DomainName: domain,
41297
- DurationInYears: durationYears,
41298
- AutoRenew: autoRenew,
41299
- AdminContact: contactDetail,
41300
- RegistrantContact: contactDetail,
41301
- TechContact: contactDetail,
41302
- PrivacyProtectAdminContact: true,
41303
- PrivacyProtectRegistrantContact: true,
41304
- PrivacyProtectTechContact: true
41305
- }));
41306
- return { operationId: result.OperationId ?? "" };
41307
41325
  }
41308
41326
  async function getRegistrationStatus(operationId, config2) {
41309
41327
  const { domains } = makeClients(config2);
@@ -41316,16 +41334,42 @@ async function getRegistrationStatus(operationId, config2) {
41316
41334
  }
41317
41335
  async function getDomainDetail(domain, config2) {
41318
41336
  const { domains } = makeClients(config2);
41319
- const result = await domains.send(new GetDomainDetailCommand({ DomainName: domain }));
41337
+ const [result, summary] = await Promise.all([
41338
+ domains.send(new GetDomainDetailCommand({ DomainName: domain })),
41339
+ getDomainSummary(domain, config2)
41340
+ ]);
41341
+ const privacy = result;
41320
41342
  return {
41321
41343
  domain: result.DomainName ?? domain,
41322
- expiry: result.ExpirationDate?.toISOString() ?? "",
41323
- auto_renew: result.AutoRenew ?? false,
41324
- transfer_lock: result.StatusList?.includes("TRANSFER_LOCK") ?? false,
41344
+ expiry: result.ExpirationDate?.toISOString() ?? summary?.expiry ?? "",
41345
+ auto_renew: result.AutoRenew ?? summary?.auto_renew ?? null,
41346
+ transfer_lock: summary?.transfer_lock ?? (result.StatusList?.includes("TRANSFER_LOCK") ? true : null),
41325
41347
  created: result.CreationDate?.toISOString() ?? "",
41326
- nameservers: (result.Nameservers ?? []).map((ns) => ns.Name ?? "").filter(Boolean)
41348
+ updated: result.UpdatedDate?.toISOString() ?? "",
41349
+ nameservers: (result.Nameservers ?? []).map((ns) => ns.Name ?? "").filter(Boolean),
41350
+ status_list: result.StatusList ?? [],
41351
+ registrar_name: result.RegistrarName,
41352
+ privacy_protected: privacy.RegistrantPrivacy ?? privacy.AdminPrivacy ?? privacy.TechPrivacy ?? null
41327
41353
  };
41328
41354
  }
41355
+ async function getDomainSummary(domain, config2) {
41356
+ let marker;
41357
+ do {
41358
+ const { domains } = makeClients(config2);
41359
+ const result = await domains.send(new ListDomainsCommand({ Marker: marker, MaxItems: 100 }));
41360
+ const summary = (result.Domains ?? []).find((item) => item.DomainName === domain);
41361
+ if (summary) {
41362
+ return {
41363
+ domain: summary.DomainName ?? domain,
41364
+ expiry: summary.Expiry?.toISOString() ?? "",
41365
+ auto_renew: summary.AutoRenew ?? false,
41366
+ transfer_lock: summary.TransferLock ?? false
41367
+ };
41368
+ }
41369
+ marker = result.NextPageMarker;
41370
+ } while (marker);
41371
+ return null;
41372
+ }
41329
41373
  async function updateNameservers2(domain, nameservers, config2, client2) {
41330
41374
  if (!nameservers.length) {
41331
41375
  throw new Error("updateNameservers requires at least one nameserver");
@@ -41361,9 +41405,12 @@ function cleanZoneId(id) {
41361
41405
  function normalizeZoneId(id) {
41362
41406
  return cleanZoneId(id.trim());
41363
41407
  }
41364
- async function createHostedZone(domain, comment, config2) {
41408
+ function cleanChangeId(id) {
41409
+ return id?.replace("/change/", "") || null;
41410
+ }
41411
+ async function createHostedZone(domain, comment, config2, options) {
41365
41412
  const { route53 } = makeClients(config2);
41366
- const callerRef = `domains-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
41413
+ const callerRef = options?.callerReference ?? `domains-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
41367
41414
  const result = await route53.send(new CreateHostedZoneCommand({
41368
41415
  Name: domain,
41369
41416
  CallerReference: callerRef,
@@ -41410,7 +41457,38 @@ async function getHostedZone(hostedZoneId, config2) {
41410
41457
  }
41411
41458
  async function deleteHostedZone(hostedZoneId, config2) {
41412
41459
  const { route53 } = makeClients(config2);
41413
- await route53.send(new DeleteHostedZoneCommand({ Id: normalizeZoneId(hostedZoneId) }));
41460
+ const zoneId = normalizeZoneId(hostedZoneId);
41461
+ const managedRecords = [];
41462
+ let nextName;
41463
+ let nextType;
41464
+ let nextIdentifier;
41465
+ do {
41466
+ const result = await route53.send(new ListResourceRecordSetsCommand({
41467
+ HostedZoneId: zoneId,
41468
+ StartRecordName: nextName,
41469
+ StartRecordType: nextType,
41470
+ StartRecordIdentifier: nextIdentifier
41471
+ }));
41472
+ managedRecords.push(...result.ResourceRecordSets?.filter((record) => record.Type !== "NS" && record.Type !== "SOA") ?? []);
41473
+ nextName = result.IsTruncated ? result.NextRecordName : undefined;
41474
+ nextType = result.IsTruncated ? result.NextRecordType : undefined;
41475
+ nextIdentifier = result.IsTruncated ? result.NextRecordIdentifier : undefined;
41476
+ } while (nextName && nextType);
41477
+ for (let index = 0;index < managedRecords.length; index += 100) {
41478
+ const batch = managedRecords.slice(index, index + 100);
41479
+ if (batch.length === 0)
41480
+ continue;
41481
+ await route53.send(new ChangeResourceRecordSetsCommand({
41482
+ HostedZoneId: zoneId,
41483
+ ChangeBatch: {
41484
+ Changes: batch.map((record) => ({
41485
+ Action: "DELETE",
41486
+ ResourceRecordSet: record
41487
+ }))
41488
+ }
41489
+ }));
41490
+ }
41491
+ await route53.send(new DeleteHostedZoneCommand({ Id: zoneId }));
41414
41492
  }
41415
41493
  async function findHostedZoneByDomain(domain, config2) {
41416
41494
  const zones = await listHostedZones(config2);
@@ -41488,36 +41566,44 @@ async function listRecords(hostedZoneId, config2) {
41488
41566
  } while (nextName);
41489
41567
  return records;
41490
41568
  }
41491
- async function upsertRecord(hostedZoneId, record, config2) {
41569
+ async function upsertRecord(hostedZoneId, record, config2, options) {
41492
41570
  const { route53 } = makeClients(config2);
41493
- await route53.send(new ChangeResourceRecordSetsCommand({
41571
+ const result = await route53.send(new ChangeResourceRecordSetsCommand({
41494
41572
  HostedZoneId: normalizeZoneId(hostedZoneId),
41495
41573
  ChangeBatch: {
41574
+ ...options?.comment ? { Comment: options.comment } : {},
41496
41575
  Changes: [{ Action: "UPSERT", ResourceRecordSet: recordToRrs(record) }]
41497
41576
  }
41498
41577
  }));
41578
+ return { changeId: cleanChangeId(result.ChangeInfo?.Id) };
41499
41579
  }
41500
- async function deleteRecord(hostedZoneId, record, config2) {
41580
+ async function deleteRecord(hostedZoneId, record, config2, options) {
41501
41581
  const { route53 } = makeClients(config2);
41502
- await route53.send(new ChangeResourceRecordSetsCommand({
41582
+ const result = await route53.send(new ChangeResourceRecordSetsCommand({
41503
41583
  HostedZoneId: normalizeZoneId(hostedZoneId),
41504
41584
  ChangeBatch: {
41585
+ ...options?.comment ? { Comment: options.comment } : {},
41505
41586
  Changes: [{ Action: "DELETE", ResourceRecordSet: recordToRrs(record) }]
41506
41587
  }
41507
41588
  }));
41589
+ return { changeId: cleanChangeId(result.ChangeInfo?.Id) };
41508
41590
  }
41509
- async function upsertRecords(hostedZoneId, records, config2) {
41591
+ async function upsertRecords(hostedZoneId, records, config2, options) {
41510
41592
  if (records.length === 0)
41511
- return;
41593
+ return { changeId: null };
41512
41594
  const { route53 } = makeClients(config2);
41513
41595
  const changes = records.map((r4) => ({
41514
41596
  Action: "UPSERT",
41515
41597
  ResourceRecordSet: recordToRrs(r4)
41516
41598
  }));
41517
- await route53.send(new ChangeResourceRecordSetsCommand({
41599
+ const result = await route53.send(new ChangeResourceRecordSetsCommand({
41518
41600
  HostedZoneId: normalizeZoneId(hostedZoneId),
41519
- ChangeBatch: { Changes: changes }
41601
+ ChangeBatch: {
41602
+ ...options?.comment ? { Comment: options.comment } : {},
41603
+ Changes: changes
41604
+ }
41520
41605
  }));
41606
+ return { changeId: cleanChangeId(result.ChangeInfo?.Id) };
41521
41607
  }
41522
41608
  function createRoute53Provider(config2) {
41523
41609
  const cfg = config2 ?? getConfig2();
@@ -41580,7 +41666,7 @@ function createRoute53Provider(config2) {
41580
41666
  expires: detail.expiry,
41581
41667
  nameservers: detail.nameservers,
41582
41668
  status: "active",
41583
- auto_renew: detail.auto_renew
41669
+ auto_renew: detail.auto_renew ?? false
41584
41670
  };
41585
41671
  },
41586
41672
  async registerDomain(domain, contact, options = {}) {
@@ -41736,6 +41822,19 @@ var CLOUDFLARE_ENV = {
41736
41822
  email: ["CLOUDFLARE_EMAIL"],
41737
41823
  accountId: ["CLOUDFLARE_ACCOUNT_ID"]
41738
41824
  };
41825
+ var ROUTE53_ENV = {
41826
+ accessKeyId: ["ROUTE53_ACCESS_KEY_ID", "AWS_ACCESS_KEY_ID"],
41827
+ secretAccessKey: ["ROUTE53_SECRET_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY"],
41828
+ sessionToken: ["ROUTE53_SESSION_TOKEN", "AWS_SESSION_TOKEN"],
41829
+ profile: ["ROUTE53_AWS_PROFILE", "AWS_PROFILE"],
41830
+ region: ["ROUTE53_REGION", "ROUTE53_AWS_REGION", "AWS_REGION"],
41831
+ webIdentityTokenFile: ["AWS_WEB_IDENTITY_TOKEN_FILE"],
41832
+ roleArn: ["AWS_ROLE_ARN"],
41833
+ containerCredentials: [
41834
+ "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
41835
+ "AWS_CONTAINER_CREDENTIALS_FULL_URI"
41836
+ ]
41837
+ };
41739
41838
  function providerEnvNames(provider) {
41740
41839
  switch (provider.toLowerCase()) {
41741
41840
  case "namecheap":
@@ -41755,7 +41854,16 @@ function providerEnvNames(provider) {
41755
41854
  case "cloudflare":
41756
41855
  return flattenEnvNames([CLOUDFLARE_ENV.apiToken, CLOUDFLARE_ENV.apiKey, CLOUDFLARE_ENV.email, CLOUDFLARE_ENV.accountId]);
41757
41856
  case "route53":
41758
- return ["AWS_PROFILE", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"];
41857
+ return flattenEnvNames([
41858
+ ROUTE53_ENV.profile,
41859
+ ROUTE53_ENV.accessKeyId,
41860
+ ROUTE53_ENV.secretAccessKey,
41861
+ ROUTE53_ENV.sessionToken,
41862
+ ROUTE53_ENV.region,
41863
+ ROUTE53_ENV.webIdentityTokenFile,
41864
+ ROUTE53_ENV.roleArn,
41865
+ ROUTE53_ENV.containerCredentials
41866
+ ]);
41759
41867
  default:
41760
41868
  return [];
41761
41869
  }
@@ -41775,8 +41883,13 @@ function hasProviderCredentials(provider, env = process.env) {
41775
41883
  const keyMode = hasEveryEnv(env, [CLOUDFLARE_ENV.apiKey, CLOUDFLARE_ENV.email]);
41776
41884
  return tokenMode || keyMode;
41777
41885
  }
41778
- case "route53":
41779
- return !!env["AWS_PROFILE"] || hasEveryEnv(env, [["AWS_ACCESS_KEY_ID"], ["AWS_SECRET_ACCESS_KEY"]]);
41886
+ case "route53": {
41887
+ const profileMode = !!firstEnv(env, ROUTE53_ENV.profile);
41888
+ const keyMode = hasEveryEnv(env, [ROUTE53_ENV.accessKeyId, ROUTE53_ENV.secretAccessKey]);
41889
+ const webIdentityMode = hasEveryEnv(env, [ROUTE53_ENV.webIdentityTokenFile, ROUTE53_ENV.roleArn]);
41890
+ const containerMode = !!firstEnv(env, ROUTE53_ENV.containerCredentials);
41891
+ return profileMode || keyMode || webIdentityMode || containerMode;
41892
+ }
41780
41893
  default:
41781
41894
  return false;
41782
41895
  }
@@ -41806,13 +41919,13 @@ function cloudflareAuthHeaders(cfg) {
41806
41919
  function getConfig3() {
41807
41920
  return resolveCloudflareConfig();
41808
41921
  }
41809
- function checkCredentials2(cfg) {
41922
+ function checkCredentials(cfg) {
41810
41923
  cloudflareAuthHeaders(cfg);
41811
41924
  }
41812
41925
  var CF_BASE = "https://api.cloudflare.com/client/v4";
41813
41926
  async function cfFetch(path, opts = {}) {
41814
41927
  const cfg = opts.config ?? getConfig3();
41815
- checkCredentials2(cfg);
41928
+ checkCredentials(cfg);
41816
41929
  const res = await fetch(`${CF_BASE}${path}`, {
41817
41930
  method: opts.method ?? "GET",
41818
41931
  headers: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/domains",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "description": "Domain portfolio, registrar, marketplace, and DNS management for AI agents — CLI + MCP server with SQLite",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,30 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "import": "./dist/index.js"
16
16
  },
17
+ "./capability": {
18
+ "types": "./dist/lib/capability.d.ts",
19
+ "import": "./dist/lib/capability.js"
20
+ },
21
+ "./cloudflare": {
22
+ "types": "./dist/lib/cloudflare.d.ts",
23
+ "import": "./dist/lib/cloudflare.js"
24
+ },
25
+ "./cloudflare-auth": {
26
+ "types": "./dist/lib/cloudflare-auth.d.ts",
27
+ "import": "./dist/lib/cloudflare-auth.js"
28
+ },
29
+ "./delegate": {
30
+ "types": "./dist/lib/delegate.d.ts",
31
+ "import": "./dist/lib/delegate.js"
32
+ },
33
+ "./registrar": {
34
+ "types": "./dist/lib/registrar.d.ts",
35
+ "import": "./dist/lib/registrar.js"
36
+ },
37
+ "./route53": {
38
+ "types": "./dist/lib/route53.d.ts",
39
+ "import": "./dist/lib/route53.js"
40
+ },
17
41
  "./storage": {
18
42
  "types": "./dist/storage.d.ts",
19
43
  "import": "./dist/storage.js"
@@ -26,7 +50,7 @@
26
50
  ],
27
51
  "scripts": {
28
52
  "clean": "rm -rf dist",
29
- "build": "bun run clean && bun build src/cli/index.ts --outdir dist/cli --target bun --external ink --external react --external chalk --external ink-text-input --external @modelcontextprotocol/sdk && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk && bun build src/index.ts src/storage.ts --outdir dist --target bun && tsc --emitDeclarationOnly --outDir dist",
53
+ "build": "bun run clean && bun build src/cli/index.ts --outdir dist/cli --target bun --external ink --external react --external chalk --external ink-text-input --external @modelcontextprotocol/sdk && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk && bun build src/index.ts src/storage.ts --outdir dist --target bun && bun build src/lib/capability.ts src/lib/cloudflare.ts src/lib/cloudflare-auth.ts src/lib/delegate.ts src/lib/registrar.ts src/lib/route53.ts --outdir dist/lib --target node --packages external && tsc --emitDeclarationOnly --outDir dist",
30
54
  "typecheck": "tsc --noEmit",
31
55
  "test": "bun test",
32
56
  "dev:cli": "bun run src/cli/index.ts",
@@ -66,6 +90,7 @@
66
90
  "dependencies": {
67
91
  "@aws-sdk/client-route-53": "^3.1067.0",
68
92
  "@aws-sdk/client-route-53-domains": "^3.1067.0",
93
+ "@aws-sdk/credential-provider-ini": "3.972.53",
69
94
  "@modelcontextprotocol/sdk": "^1.29.0",
70
95
  "chalk": "^5.4.1",
71
96
  "commander": "^13.1.0",