@hasna/domains 0.0.37 → 0.0.38

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.
@@ -1,4 +1,5 @@
1
1
  import type { Command } from "commander";
2
+ import { type DnsProvider } from "../../lib/registrar.js";
2
3
  /** Record types the store (local sqlite CHECK + cloud API) accepts on write. */
3
4
  export declare const SUPPORTED_DNS_TYPES: Set<string>;
4
5
  /**
@@ -13,5 +14,7 @@ export declare function partitionPullableRecords<T extends {
13
14
  keep: T[];
14
15
  skipped: Map<string, number>;
15
16
  };
16
- export declare function registerDnsCommands(program: Command): void;
17
+ export declare function registerDnsCommands(program: Command, deps?: {
18
+ getDnsProvider?: (name: string) => DnsProvider;
19
+ }): void;
17
20
  //# sourceMappingURL=dns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dns.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBzC,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,aAA4D,CAAC;AAE7F;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACjE,OAAO,EAAE,CAAC,EAAE,GACX;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAW7C;AAoBD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkY1D"}
1
+ {"version":3,"file":"dns.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAa1E,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,aAA4D,CAAC;AAE7F;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACjE,OAAO,EAAE,CAAC,EAAE,GACX;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAW7C;AAyBD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,IAAI,GAAE;IAAE,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,CAAA;CAAO,GAC5D,IAAI,CAsYN"}
package/dist/cli/index.js CHANGED
@@ -28946,7 +28946,7 @@ var init_bowser = __esm(() => {
28946
28946
 
28947
28947
  // node_modules/@aws-sdk/core/dist-cjs/submodules/client/index.js
28948
28948
  var require_client2 = __commonJS((exports) => {
28949
- var __dirname = "/home/hasna/.hasna/repos/worktrees/open-domains/2a0dcf21-d730-4a74-bfc3-12e59e51ecd5/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
28949
+ var __dirname = "/home/hasna/.hasna/repos/worktrees/domains/0a933b3e-a459-4bcb-b94d-6ab12a2ec235/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
28950
28950
  var retry = require_retry();
28951
28951
  var protocols = require_protocols();
28952
28952
  var lambdaInvokeStore = require_invoke_store();
@@ -50215,6 +50215,7 @@ function createRoute53Provider(config2) {
50215
50215
  }
50216
50216
  return {
50217
50217
  name: "route53",
50218
+ dnsWriteScope: "changed-groups",
50218
50219
  async listDomains() {
50219
50220
  return listDomainInventory();
50220
50221
  },
@@ -50584,16 +50585,51 @@ async function listRecordsByNameType(zoneId, type, name, config2) {
50584
50585
  proxied: r4.proxied
50585
50586
  }));
50586
50587
  }
50587
- async function replaceRecordsByNameType(zoneId, records, config2) {
50588
+ function sameRecordIdentity(a4, b4) {
50589
+ return a4.type === b4.type && a4.name === b4.name && a4.content === b4.content && (a4.priority ?? undefined) === (b4.priority ?? undefined);
50590
+ }
50591
+ function resolveDesiredProxied(records, existing) {
50592
+ const omitted = records.filter((record) => record.proxied === undefined);
50593
+ if (omitted.length === 0)
50594
+ return records;
50595
+ const { type, name } = records[0];
50596
+ if (omitted.length === records.length) {
50597
+ const proxyStates = new Set(existing.map((record) => record.proxied));
50598
+ if (proxyStates.size > 1) {
50599
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name}: ` + "existing records have mixed proxied values while desired records omit proxied; " + "set proxied explicitly on every desired record");
50600
+ }
50601
+ const inherited = existing[0]?.proxied;
50602
+ return inherited === undefined ? records : records.map((record) => ({ ...record, proxied: inherited }));
50603
+ }
50604
+ const existingHasProxyState = existing.some((record) => record.proxied !== undefined);
50605
+ return records.map((record) => {
50606
+ if (record.proxied !== undefined)
50607
+ return record;
50608
+ const matches = existing.filter((candidate) => sameRecordIdentity(candidate, record));
50609
+ if (matches.length === 1 && matches[0].proxied !== undefined) {
50610
+ return { ...record, proxied: matches[0].proxied };
50611
+ }
50612
+ if (!existingHasProxyState)
50613
+ return record;
50614
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name} record ${record.content}: ` + "omitted proxied does not resolve to exactly one existing value; " + "set proxied explicitly on this desired record");
50615
+ });
50616
+ }
50617
+ async function prepareRecordsByNameType(zoneId, records, config2) {
50588
50618
  if (records.length === 0)
50589
50619
  return;
50590
50620
  const { type, name } = records[0];
50591
50621
  const existing = await listRecordsByNameType(zoneId, type, name, config2);
50592
- for (const record of existing) {
50622
+ if (existing.length === records.length && records.every((record) => existing.some((candidate) => sameRecordIdentity(candidate, record) && candidate.ttl === record.ttl && (record.proxied === undefined || candidate.proxied === record.proxied)))) {
50623
+ return;
50624
+ }
50625
+ return { existing, desired: resolveDesiredProxied(records, existing) };
50626
+ }
50627
+ async function replaceRecordsByNameType(zoneId, replacement, config2) {
50628
+ for (const record of replacement.existing) {
50593
50629
  if (record.id)
50594
50630
  await deleteRecord2(zoneId, record.id, config2);
50595
50631
  }
50596
- for (const record of records) {
50632
+ for (const record of replacement.desired) {
50597
50633
  await cfFetch(`/zones/${zoneId}/dns_records`, {
50598
50634
  method: "POST",
50599
50635
  body: {
@@ -50602,7 +50638,7 @@ async function replaceRecordsByNameType(zoneId, records, config2) {
50602
50638
  content: record.content,
50603
50639
  ttl: record.ttl ?? 1,
50604
50640
  priority: record.priority,
50605
- proxied: record.proxied ?? false
50641
+ ...record.proxied === undefined ? {} : { proxied: record.proxied }
50606
50642
  },
50607
50643
  config: config2
50608
50644
  });
@@ -50637,6 +50673,7 @@ function createCloudflareProvider(config2) {
50637
50673
  const cfg = config2 ?? getConfig3();
50638
50674
  return {
50639
50675
  name: "cloudflare",
50676
+ dnsWriteScope: "changed-groups",
50640
50677
  async listDomains() {
50641
50678
  const zones = await listZones(cfg);
50642
50679
  return zones.map(zoneToDomainInfo);
@@ -50687,7 +50724,8 @@ function createCloudflareProvider(config2) {
50687
50724
  name: r4.name,
50688
50725
  value: r4.content,
50689
50726
  ttl: r4.ttl === 1 ? 0 : r4.ttl,
50690
- priority: r4.priority
50727
+ priority: r4.priority,
50728
+ ...r4.proxied === undefined ? {} : { proxied: r4.proxied }
50691
50729
  }));
50692
50730
  },
50693
50731
  async setDnsRecords(domain, records) {
@@ -50698,11 +50736,24 @@ function createCloudflareProvider(config2) {
50698
50736
  for (const r4 of records) {
50699
50737
  const key = `${r4.type}|${r4.name}`;
50700
50738
  const existing = grouped.get(key) ?? [];
50701
- existing.push({ type: r4.type, name: r4.name, content: r4.value, ttl: r4.ttl || 1, priority: r4.priority });
50739
+ existing.push({
50740
+ type: r4.type,
50741
+ name: r4.name,
50742
+ content: r4.value,
50743
+ ttl: r4.ttl || 1,
50744
+ priority: r4.priority,
50745
+ ...r4.proxied === undefined ? {} : { proxied: r4.proxied }
50746
+ });
50702
50747
  grouped.set(key, existing);
50703
50748
  }
50749
+ const replacements = [];
50704
50750
  for (const group of grouped.values()) {
50705
- await replaceRecordsByNameType(zone.id, group, cfg);
50751
+ const replacement = await prepareRecordsByNameType(zone.id, group, cfg);
50752
+ if (replacement)
50753
+ replacements.push(replacement);
50754
+ }
50755
+ for (const replacement of replacements) {
50756
+ await replaceRecordsByNameType(zone.id, replacement, cfg);
50706
50757
  }
50707
50758
  return true;
50708
50759
  }
@@ -56457,13 +56508,16 @@ function normalizeDnsRecord(record, domain) {
56457
56508
  } else if (lowerName.endsWith(`.${normalizedDomain}`)) {
56458
56509
  name = name.replace(/\.$/, "").slice(0, -(normalizedDomain.length + 1));
56459
56510
  }
56460
- return {
56511
+ const normalized = {
56461
56512
  type,
56462
56513
  name,
56463
56514
  value: String(record.value).trim(),
56464
56515
  ttl: Number.isFinite(record.ttl) && record.ttl > 0 ? Math.trunc(record.ttl) : 300,
56465
56516
  priority: record.priority
56466
56517
  };
56518
+ if (record.proxied !== undefined)
56519
+ normalized.proxied = record.proxied;
56520
+ return normalized;
56467
56521
  }
56468
56522
  function parseDesiredDnsState(input, domainHint) {
56469
56523
  let parsed;
@@ -56494,7 +56548,8 @@ function parseDesiredDnsState(input, domainHint) {
56494
56548
  name: r4["name"],
56495
56549
  value: r4["value"],
56496
56550
  ttl: typeof r4["ttl"] === "number" ? r4["ttl"] : Number(r4["ttl"] ?? 300),
56497
- priority: r4["priority"] == null ? undefined : Number(r4["priority"])
56551
+ priority: r4["priority"] == null ? undefined : Number(r4["priority"]),
56552
+ proxied: typeof r4["proxied"] === "boolean" ? r4["proxied"] : undefined
56498
56553
  }, domain);
56499
56554
  })
56500
56555
  };
@@ -56503,7 +56558,7 @@ function identity(record) {
56503
56558
  return [record.type, record.name, record.value, record.priority ?? ""].join("\x00");
56504
56559
  }
56505
56560
  function sameMutableFields(a4, b4) {
56506
- return a4.ttl === b4.ttl;
56561
+ return a4.ttl === b4.ttl && (b4.proxied === undefined || a4.proxied === b4.proxied);
56507
56562
  }
56508
56563
  function createDnsPlan(domain, current, desired) {
56509
56564
  const normalizedCurrent = current.map((record) => normalizeDnsRecord(record, domain));
@@ -56538,6 +56593,13 @@ function createDnsPlan(domain, current, desired) {
56538
56593
  function planHasChanges(plan) {
56539
56594
  return plan.creates + plan.updates + plan.deletes > 0;
56540
56595
  }
56596
+ function dnsRecordGroupKey(record) {
56597
+ return `${record.type}\x00${record.name}`;
56598
+ }
56599
+ function selectChangedDnsRecords(plan, desired) {
56600
+ const changedGroups = new Set(plan.operations.filter((operation) => operation.op !== "unchanged").map((operation) => dnsRecordGroupKey(operation.record)));
56601
+ return desired.filter((record) => changedGroups.has(dnsRecordGroupKey(normalizeDnsRecord(record, plan.domain))));
56602
+ }
56541
56603
  function getDnsApplyBlockReason(plan, opts) {
56542
56604
  if (!planHasChanges(plan))
56543
56605
  return;
@@ -56575,19 +56637,20 @@ function printDnsPlan(plan) {
56575
56637
  printLine(` ${op.op.toUpperCase()} ${op.record.type} ${op.record.name} ${op.record.value} ttl=${op.record.ttl}${priority}${currentTtl}`);
56576
56638
  }
56577
56639
  }
56578
- async function loadDnsPlan(domain, providerName, file) {
56640
+ async function loadDnsPlan(domain, providerName, file, resolveDnsProvider = getDnsProvider) {
56579
56641
  const desired = parseDesiredDnsState(readFileSync4(file, "utf-8"), domain);
56580
56642
  const planDomain = desired.domain ?? domain;
56581
- const provider = getDnsProvider(providerName);
56643
+ const provider = resolveDnsProvider(providerName);
56582
56644
  const current = await provider.getDnsRecords(planDomain);
56583
56645
  return createDnsPlan(planDomain, current, desired.records);
56584
56646
  }
56585
- function registerDnsCommands(program2) {
56647
+ function registerDnsCommands(program2, deps = {}) {
56648
+ const resolveDnsProvider = deps.getDnsProvider ?? getDnsProvider;
56586
56649
  const dnsCmd = program2.command("dns").description("DNS record management");
56587
56650
  dnsCmd.command("plan <domain>").description("Preview desired DNS state changes from a JSON file without mutating provider records").requiredOption("--file <path>", "Desired DNS state JSON file").option("--provider <name>", "DNS provider \u2014 defaults to config default-dns").option("--json", "Output as JSON", false).action(async (domain, opts) => {
56588
56651
  const providerName = opts.provider ?? loadConfig3().default_dns ?? "route53";
56589
56652
  try {
56590
- const plan = await loadDnsPlan(domain, providerName, opts.file);
56653
+ const plan = await loadDnsPlan(domain, providerName, opts.file, resolveDnsProvider);
56591
56654
  if (opts.json)
56592
56655
  printLine(JSON.stringify(plan, null, 2));
56593
56656
  else
@@ -56600,7 +56663,7 @@ function registerDnsCommands(program2) {
56600
56663
  dnsCmd.command("diff <domain>").description("Alias of dns plan: show live provider DNS drift against desired JSON state").requiredOption("--file <path>", "Desired DNS state JSON file").option("--provider <name>", "DNS provider \u2014 defaults to config default-dns").option("--json", "Output as JSON", false).action(async (domain, opts) => {
56601
56664
  const providerName = opts.provider ?? loadConfig3().default_dns ?? "route53";
56602
56665
  try {
56603
- const plan = await loadDnsPlan(domain, providerName, opts.file);
56666
+ const plan = await loadDnsPlan(domain, providerName, opts.file, resolveDnsProvider);
56604
56667
  if (opts.json)
56605
56668
  printLine(JSON.stringify(plan, null, 2));
56606
56669
  else
@@ -56617,7 +56680,7 @@ function registerDnsCommands(program2) {
56617
56680
  try {
56618
56681
  const desired = parseDesiredDnsState(readFileSync4(opts.file, "utf-8"), domain);
56619
56682
  const planDomain = desired.domain ?? domain;
56620
- const provider = getDnsProvider(providerName);
56683
+ const provider = resolveDnsProvider(providerName);
56621
56684
  const current = await provider.getDnsRecords(planDomain);
56622
56685
  const plan = createDnsPlan(planDomain, current, desired.records);
56623
56686
  if (!planHasChanges(plan)) {
@@ -56642,7 +56705,8 @@ function registerDnsCommands(program2) {
56642
56705
  }
56643
56706
  process.exit(1);
56644
56707
  }
56645
- await provider.setDnsRecords(planDomain, desired.records);
56708
+ const recordsToApply = provider.dnsWriteScope === "changed-groups" ? selectChangedDnsRecords(plan, desired.records) : desired.records;
56709
+ await provider.setDnsRecords(planDomain, recordsToApply);
56646
56710
  const verified = createDnsPlan(planDomain, await provider.getDnsRecords(planDomain), desired.records);
56647
56711
  if (planHasChanges(verified)) {
56648
56712
  if (opts.json)
@@ -56832,7 +56896,7 @@ ${compactHint(page, "subdomain(s)", "Use --all for every discovered name or --js
56832
56896
  dnsCmd.command("pull <domain>").description("Pull live DNS records from provider into local DB").option("--provider <name>", "DNS provider (route53, cloudflare) \u2014 defaults to config default-dns").action(async (domain, opts) => {
56833
56897
  const providerName = opts.provider ?? loadConfig3().default_dns ?? "route53";
56834
56898
  try {
56835
- const provider = getDnsProvider(providerName);
56899
+ const provider = resolveDnsProvider(providerName);
56836
56900
  const records = await provider.getDnsRecords(domain);
56837
56901
  const dbDomain = await getDomainByName2(domain);
56838
56902
  if (!dbDomain) {
@@ -56866,7 +56930,7 @@ ${compactHint(page, "subdomain(s)", "Use --all for every discovered name or --js
56866
56930
  const dbDomain = await getDomain2(domainId) ?? (() => {
56867
56931
  throw new Error(`Domain '${domainId}' not found`);
56868
56932
  })();
56869
- const provider = getDnsProvider(providerName);
56933
+ const provider = resolveDnsProvider(providerName);
56870
56934
  await provider.setDnsRecords(dbDomain.name, records.map((r4) => ({
56871
56935
  type: r4.type,
56872
56936
  name: r4.name,
package/dist/index.js CHANGED
@@ -12578,7 +12578,7 @@ var init_bowser = __esm(() => {
12578
12578
 
12579
12579
  // node_modules/@aws-sdk/core/dist-cjs/submodules/client/index.js
12580
12580
  var require_client2 = __commonJS((exports) => {
12581
- var __dirname = "/home/hasna/.hasna/repos/worktrees/open-domains/2a0dcf21-d730-4a74-bfc3-12e59e51ecd5/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
12581
+ var __dirname = "/home/hasna/.hasna/repos/worktrees/domains/0a933b3e-a459-4bcb-b94d-6ab12a2ec235/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
12582
12582
  var retry = require_retry();
12583
12583
  var protocols = require_protocols();
12584
12584
  var lambdaInvokeStore = require_invoke_store();
@@ -46786,6 +46786,7 @@ function createRoute53Provider(config2) {
46786
46786
  }
46787
46787
  return {
46788
46788
  name: "route53",
46789
+ dnsWriteScope: "changed-groups",
46789
46790
  async listDomains() {
46790
46791
  return listDomainInventory();
46791
46792
  },
@@ -47159,16 +47160,51 @@ async function upsertRecord2(zoneId, record, config2) {
47159
47160
  await cfFetch(`/zones/${zoneId}/dns_records`, { method: "POST", body, config: config2 });
47160
47161
  }
47161
47162
  }
47162
- async function replaceRecordsByNameType(zoneId, records, config2) {
47163
+ function sameRecordIdentity(a4, b4) {
47164
+ return a4.type === b4.type && a4.name === b4.name && a4.content === b4.content && (a4.priority ?? undefined) === (b4.priority ?? undefined);
47165
+ }
47166
+ function resolveDesiredProxied(records, existing) {
47167
+ const omitted = records.filter((record) => record.proxied === undefined);
47168
+ if (omitted.length === 0)
47169
+ return records;
47170
+ const { type, name } = records[0];
47171
+ if (omitted.length === records.length) {
47172
+ const proxyStates = new Set(existing.map((record) => record.proxied));
47173
+ if (proxyStates.size > 1) {
47174
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name}: ` + "existing records have mixed proxied values while desired records omit proxied; " + "set proxied explicitly on every desired record");
47175
+ }
47176
+ const inherited = existing[0]?.proxied;
47177
+ return inherited === undefined ? records : records.map((record) => ({ ...record, proxied: inherited }));
47178
+ }
47179
+ const existingHasProxyState = existing.some((record) => record.proxied !== undefined);
47180
+ return records.map((record) => {
47181
+ if (record.proxied !== undefined)
47182
+ return record;
47183
+ const matches = existing.filter((candidate) => sameRecordIdentity(candidate, record));
47184
+ if (matches.length === 1 && matches[0].proxied !== undefined) {
47185
+ return { ...record, proxied: matches[0].proxied };
47186
+ }
47187
+ if (!existingHasProxyState)
47188
+ return record;
47189
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name} record ${record.content}: ` + "omitted proxied does not resolve to exactly one existing value; " + "set proxied explicitly on this desired record");
47190
+ });
47191
+ }
47192
+ async function prepareRecordsByNameType(zoneId, records, config2) {
47163
47193
  if (records.length === 0)
47164
47194
  return;
47165
47195
  const { type, name } = records[0];
47166
47196
  const existing = await listRecordsByNameType(zoneId, type, name, config2);
47167
- for (const record of existing) {
47197
+ if (existing.length === records.length && records.every((record) => existing.some((candidate) => sameRecordIdentity(candidate, record) && candidate.ttl === record.ttl && (record.proxied === undefined || candidate.proxied === record.proxied)))) {
47198
+ return;
47199
+ }
47200
+ return { existing, desired: resolveDesiredProxied(records, existing) };
47201
+ }
47202
+ async function replaceRecordsByNameType(zoneId, replacement, config2) {
47203
+ for (const record of replacement.existing) {
47168
47204
  if (record.id)
47169
47205
  await deleteRecord2(zoneId, record.id, config2);
47170
47206
  }
47171
- for (const record of records) {
47207
+ for (const record of replacement.desired) {
47172
47208
  await cfFetch(`/zones/${zoneId}/dns_records`, {
47173
47209
  method: "POST",
47174
47210
  body: {
@@ -47177,7 +47213,7 @@ async function replaceRecordsByNameType(zoneId, records, config2) {
47177
47213
  content: record.content,
47178
47214
  ttl: record.ttl ?? 1,
47179
47215
  priority: record.priority,
47180
- proxied: record.proxied ?? false
47216
+ ...record.proxied === undefined ? {} : { proxied: record.proxied }
47181
47217
  },
47182
47218
  config: config2
47183
47219
  });
@@ -47212,6 +47248,7 @@ function createCloudflareProvider(config2) {
47212
47248
  const cfg = config2 ?? getConfig3();
47213
47249
  return {
47214
47250
  name: "cloudflare",
47251
+ dnsWriteScope: "changed-groups",
47215
47252
  async listDomains() {
47216
47253
  const zones = await listZones(cfg);
47217
47254
  return zones.map(zoneToDomainInfo);
@@ -47262,7 +47299,8 @@ function createCloudflareProvider(config2) {
47262
47299
  name: r4.name,
47263
47300
  value: r4.content,
47264
47301
  ttl: r4.ttl === 1 ? 0 : r4.ttl,
47265
- priority: r4.priority
47302
+ priority: r4.priority,
47303
+ ...r4.proxied === undefined ? {} : { proxied: r4.proxied }
47266
47304
  }));
47267
47305
  },
47268
47306
  async setDnsRecords(domain, records) {
@@ -47273,11 +47311,24 @@ function createCloudflareProvider(config2) {
47273
47311
  for (const r4 of records) {
47274
47312
  const key = `${r4.type}|${r4.name}`;
47275
47313
  const existing = grouped.get(key) ?? [];
47276
- existing.push({ type: r4.type, name: r4.name, content: r4.value, ttl: r4.ttl || 1, priority: r4.priority });
47314
+ existing.push({
47315
+ type: r4.type,
47316
+ name: r4.name,
47317
+ content: r4.value,
47318
+ ttl: r4.ttl || 1,
47319
+ priority: r4.priority,
47320
+ ...r4.proxied === undefined ? {} : { proxied: r4.proxied }
47321
+ });
47277
47322
  grouped.set(key, existing);
47278
47323
  }
47324
+ const replacements = [];
47279
47325
  for (const group of grouped.values()) {
47280
- await replaceRecordsByNameType(zone.id, group, cfg);
47326
+ const replacement = await prepareRecordsByNameType(zone.id, group, cfg);
47327
+ if (replacement)
47328
+ replacements.push(replacement);
47329
+ }
47330
+ for (const replacement of replacements) {
47331
+ await replaceRecordsByNameType(zone.id, replacement, cfg);
47281
47332
  }
47282
47333
  return true;
47283
47334
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/lib/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,WAAW,EACX,uBAAuB,EAIxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAIjC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,wBAAgB,SAAS,IAAI,gBAAgB,CAE5C;AAqCD,wBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAkBpF;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQvG;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAUnG;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,CAAC,EAAE;IACL,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7E,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CAC1E,GACA,OAAO,CAAC,cAAc,CAAC,CASzB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF;AAID,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkBxG;AAkBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrH;AAyBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7G;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjI;AA4BD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,uBAAuB,CA+EzG"}
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/lib/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,WAAW,EACX,uBAAuB,EAIxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAIjC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,wBAAgB,SAAS,IAAI,gBAAgB,CAE5C;AAqCD,wBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAkBpF;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQvG;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAUnG;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,CAAC,EAAE;IACL,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7E,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CAC1E,GACA,OAAO,CAAC,cAAc,CAAC,CASzB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF;AAID,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkBxG;AAkBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrH;AA+FD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7G;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjI;AA4BD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,uBAAuB,CA6FzG"}
@@ -249,16 +249,51 @@ async function upsertRecord(zoneId, record, config) {
249
249
  await cfFetch(`/zones/${zoneId}/dns_records`, { method: "POST", body, config });
250
250
  }
251
251
  }
252
- async function replaceRecordsByNameType(zoneId, records, config) {
252
+ function sameRecordIdentity(a, b) {
253
+ return a.type === b.type && a.name === b.name && a.content === b.content && (a.priority ?? undefined) === (b.priority ?? undefined);
254
+ }
255
+ function resolveDesiredProxied(records, existing) {
256
+ const omitted = records.filter((record) => record.proxied === undefined);
257
+ if (omitted.length === 0)
258
+ return records;
259
+ const { type, name } = records[0];
260
+ if (omitted.length === records.length) {
261
+ const proxyStates = new Set(existing.map((record) => record.proxied));
262
+ if (proxyStates.size > 1) {
263
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name}: ` + "existing records have mixed proxied values while desired records omit proxied; " + "set proxied explicitly on every desired record");
264
+ }
265
+ const inherited = existing[0]?.proxied;
266
+ return inherited === undefined ? records : records.map((record) => ({ ...record, proxied: inherited }));
267
+ }
268
+ const existingHasProxyState = existing.some((record) => record.proxied !== undefined);
269
+ return records.map((record) => {
270
+ if (record.proxied !== undefined)
271
+ return record;
272
+ const matches = existing.filter((candidate) => sameRecordIdentity(candidate, record));
273
+ if (matches.length === 1 && matches[0].proxied !== undefined) {
274
+ return { ...record, proxied: matches[0].proxied };
275
+ }
276
+ if (!existingHasProxyState)
277
+ return record;
278
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name} record ${record.content}: ` + "omitted proxied does not resolve to exactly one existing value; " + "set proxied explicitly on this desired record");
279
+ });
280
+ }
281
+ async function prepareRecordsByNameType(zoneId, records, config) {
253
282
  if (records.length === 0)
254
283
  return;
255
284
  const { type, name } = records[0];
256
285
  const existing = await listRecordsByNameType(zoneId, type, name, config);
257
- for (const record of existing) {
286
+ if (existing.length === records.length && records.every((record) => existing.some((candidate) => sameRecordIdentity(candidate, record) && candidate.ttl === record.ttl && (record.proxied === undefined || candidate.proxied === record.proxied)))) {
287
+ return;
288
+ }
289
+ return { existing, desired: resolveDesiredProxied(records, existing) };
290
+ }
291
+ async function replaceRecordsByNameType(zoneId, replacement, config) {
292
+ for (const record of replacement.existing) {
258
293
  if (record.id)
259
294
  await deleteRecord(zoneId, record.id, config);
260
295
  }
261
- for (const record of records) {
296
+ for (const record of replacement.desired) {
262
297
  await cfFetch(`/zones/${zoneId}/dns_records`, {
263
298
  method: "POST",
264
299
  body: {
@@ -267,7 +302,7 @@ async function replaceRecordsByNameType(zoneId, records, config) {
267
302
  content: record.content,
268
303
  ttl: record.ttl ?? 1,
269
304
  priority: record.priority,
270
- proxied: record.proxied ?? false
305
+ ...record.proxied === undefined ? {} : { proxied: record.proxied }
271
306
  },
272
307
  config
273
308
  });
@@ -308,6 +343,7 @@ function createCloudflareProvider(config) {
308
343
  const cfg = config ?? getConfig();
309
344
  return {
310
345
  name: "cloudflare",
346
+ dnsWriteScope: "changed-groups",
311
347
  async listDomains() {
312
348
  const zones = await listZones(cfg);
313
349
  return zones.map(zoneToDomainInfo);
@@ -358,7 +394,8 @@ function createCloudflareProvider(config) {
358
394
  name: r.name,
359
395
  value: r.content,
360
396
  ttl: r.ttl === 1 ? 0 : r.ttl,
361
- priority: r.priority
397
+ priority: r.priority,
398
+ ...r.proxied === undefined ? {} : { proxied: r.proxied }
362
399
  }));
363
400
  },
364
401
  async setDnsRecords(domain, records) {
@@ -369,11 +406,24 @@ function createCloudflareProvider(config) {
369
406
  for (const r of records) {
370
407
  const key = `${r.type}|${r.name}`;
371
408
  const existing = grouped.get(key) ?? [];
372
- existing.push({ type: r.type, name: r.name, content: r.value, ttl: r.ttl || 1, priority: r.priority });
409
+ existing.push({
410
+ type: r.type,
411
+ name: r.name,
412
+ content: r.value,
413
+ ttl: r.ttl || 1,
414
+ priority: r.priority,
415
+ ...r.proxied === undefined ? {} : { proxied: r.proxied }
416
+ });
373
417
  grouped.set(key, existing);
374
418
  }
419
+ const replacements = [];
375
420
  for (const group of grouped.values()) {
376
- await replaceRecordsByNameType(zone.id, group, cfg);
421
+ const replacement = await prepareRecordsByNameType(zone.id, group, cfg);
422
+ if (replacement)
423
+ replacements.push(replacement);
424
+ }
425
+ for (const replacement of replacements) {
426
+ await replaceRecordsByNameType(zone.id, replacement, cfg);
377
427
  }
378
428
  return true;
379
429
  }
@@ -22,6 +22,7 @@ export declare function normalizeDnsRecord(record: ProviderDnsRecord, domain: st
22
22
  export declare function parseDesiredDnsState(input: string, domainHint?: string): DesiredDnsState;
23
23
  export declare function createDnsPlan(domain: string, current: ProviderDnsRecord[], desired: ProviderDnsRecord[]): DnsPlan;
24
24
  export declare function planHasChanges(plan: DnsPlan): boolean;
25
+ export declare function selectChangedDnsRecords(plan: DnsPlan, desired: ProviderDnsRecord[]): ProviderDnsRecord[];
25
26
  export declare function getDnsApplyBlockReason(plan: DnsPlan, opts: {
26
27
  yes?: boolean;
27
28
  allowDelete?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"dns-plan.d.ts","sourceRoot":"","sources":["../../src/lib/dns-plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEhF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,oBAAoB,CAAC;IACzB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,GAAG,8BAA8B,GAAG,0BAA0B,CAAC;AAMxH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAiB/F;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,CA6BxF;AAUD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAgCjH;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,mBAAmB,GAAG,SAAS,CAMrI"}
1
+ {"version":3,"file":"dns-plan.d.ts","sourceRoot":"","sources":["../../src/lib/dns-plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEhF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,oBAAoB,CAAC;IACzB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,GAAG,8BAA8B,GAAG,0BAA0B,CAAC;AAMxH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAmB/F;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,CA8BxF;AAUD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAgCjH;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAErD;AAMD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,CASxG;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,mBAAmB,GAAG,SAAS,CAMrI"}
@@ -10,6 +10,7 @@ export interface ProviderDnsRecord {
10
10
  value: string;
11
11
  ttl: number;
12
12
  priority?: number;
13
+ proxied?: boolean;
13
14
  }
14
15
  export interface ProviderDomainInfo {
15
16
  domain: string;
@@ -92,8 +93,11 @@ export interface RegistrarProvider extends DomainInventoryProvider {
92
93
  updateNameservers?(domain: string, nameservers: string[]): Promise<ProviderNameserverUpdateResult>;
93
94
  }
94
95
  /** Handles DNS zone and record management */
96
+ export type DnsWriteScope = "full-zone" | "changed-groups";
95
97
  export interface DnsProvider {
96
98
  name: string;
99
+ /** Omission is conservative: setDnsRecords receives the complete desired zone. */
100
+ dnsWriteScope?: DnsWriteScope;
97
101
  getDnsRecords(domain: string): Promise<ProviderDnsRecord[]>;
98
102
  setDnsRecords(domain: string, records: ProviderDnsRecord[]): Promise<boolean>;
99
103
  }
@@ -1 +1 @@
1
- {"version":3,"file":"registrar.d.ts","sourceRoot":"","sources":["../../src/lib/registrar.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registrar.d.ts","sourceRoot":"","sources":["../../src/lib/registrar.ts"],"names":[],"mappings":"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"}
@@ -249,16 +249,51 @@ async function upsertRecord(zoneId, record, config) {
249
249
  await cfFetch(`/zones/${zoneId}/dns_records`, { method: "POST", body, config });
250
250
  }
251
251
  }
252
- async function replaceRecordsByNameType(zoneId, records, config) {
252
+ function sameRecordIdentity(a, b) {
253
+ return a.type === b.type && a.name === b.name && a.content === b.content && (a.priority ?? undefined) === (b.priority ?? undefined);
254
+ }
255
+ function resolveDesiredProxied(records, existing) {
256
+ const omitted = records.filter((record) => record.proxied === undefined);
257
+ if (omitted.length === 0)
258
+ return records;
259
+ const { type, name } = records[0];
260
+ if (omitted.length === records.length) {
261
+ const proxyStates = new Set(existing.map((record) => record.proxied));
262
+ if (proxyStates.size > 1) {
263
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name}: ` + "existing records have mixed proxied values while desired records omit proxied; " + "set proxied explicitly on every desired record");
264
+ }
265
+ const inherited = existing[0]?.proxied;
266
+ return inherited === undefined ? records : records.map((record) => ({ ...record, proxied: inherited }));
267
+ }
268
+ const existingHasProxyState = existing.some((record) => record.proxied !== undefined);
269
+ return records.map((record) => {
270
+ if (record.proxied !== undefined)
271
+ return record;
272
+ const matches = existing.filter((candidate) => sameRecordIdentity(candidate, record));
273
+ if (matches.length === 1 && matches[0].proxied !== undefined) {
274
+ return { ...record, proxied: matches[0].proxied };
275
+ }
276
+ if (!existingHasProxyState)
277
+ return record;
278
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name} record ${record.content}: ` + "omitted proxied does not resolve to exactly one existing value; " + "set proxied explicitly on this desired record");
279
+ });
280
+ }
281
+ async function prepareRecordsByNameType(zoneId, records, config) {
253
282
  if (records.length === 0)
254
283
  return;
255
284
  const { type, name } = records[0];
256
285
  const existing = await listRecordsByNameType(zoneId, type, name, config);
257
- for (const record of existing) {
286
+ if (existing.length === records.length && records.every((record) => existing.some((candidate) => sameRecordIdentity(candidate, record) && candidate.ttl === record.ttl && (record.proxied === undefined || candidate.proxied === record.proxied)))) {
287
+ return;
288
+ }
289
+ return { existing, desired: resolveDesiredProxied(records, existing) };
290
+ }
291
+ async function replaceRecordsByNameType(zoneId, replacement, config) {
292
+ for (const record of replacement.existing) {
258
293
  if (record.id)
259
294
  await deleteRecord(zoneId, record.id, config);
260
295
  }
261
- for (const record of records) {
296
+ for (const record of replacement.desired) {
262
297
  await cfFetch(`/zones/${zoneId}/dns_records`, {
263
298
  method: "POST",
264
299
  body: {
@@ -267,7 +302,7 @@ async function replaceRecordsByNameType(zoneId, records, config) {
267
302
  content: record.content,
268
303
  ttl: record.ttl ?? 1,
269
304
  priority: record.priority,
270
- proxied: record.proxied ?? false
305
+ ...record.proxied === undefined ? {} : { proxied: record.proxied }
271
306
  },
272
307
  config
273
308
  });
@@ -308,6 +343,7 @@ function createCloudflareProvider(config) {
308
343
  const cfg = config ?? getConfig();
309
344
  return {
310
345
  name: "cloudflare",
346
+ dnsWriteScope: "changed-groups",
311
347
  async listDomains() {
312
348
  const zones = await listZones(cfg);
313
349
  return zones.map(zoneToDomainInfo);
@@ -358,7 +394,8 @@ function createCloudflareProvider(config) {
358
394
  name: r.name,
359
395
  value: r.content,
360
396
  ttl: r.ttl === 1 ? 0 : r.ttl,
361
- priority: r.priority
397
+ priority: r.priority,
398
+ ...r.proxied === undefined ? {} : { proxied: r.proxied }
362
399
  }));
363
400
  },
364
401
  async setDnsRecords(domain, records) {
@@ -369,11 +406,24 @@ function createCloudflareProvider(config) {
369
406
  for (const r of records) {
370
407
  const key = `${r.type}|${r.name}`;
371
408
  const existing = grouped.get(key) ?? [];
372
- existing.push({ type: r.type, name: r.name, content: r.value, ttl: r.ttl || 1, priority: r.priority });
409
+ existing.push({
410
+ type: r.type,
411
+ name: r.name,
412
+ content: r.value,
413
+ ttl: r.ttl || 1,
414
+ priority: r.priority,
415
+ ...r.proxied === undefined ? {} : { proxied: r.proxied }
416
+ });
373
417
  grouped.set(key, existing);
374
418
  }
419
+ const replacements = [];
375
420
  for (const group of grouped.values()) {
376
- await replaceRecordsByNameType(zone.id, group, cfg);
421
+ const replacement = await prepareRecordsByNameType(zone.id, group, cfg);
422
+ if (replacement)
423
+ replacements.push(replacement);
424
+ }
425
+ for (const replacement of replacements) {
426
+ await replaceRecordsByNameType(zone.id, replacement, cfg);
377
427
  }
378
428
  return true;
379
429
  }
@@ -910,6 +960,7 @@ function createRoute53Provider(config) {
910
960
  }
911
961
  return {
912
962
  name: "route53",
963
+ dnsWriteScope: "changed-groups",
913
964
  async listDomains() {
914
965
  return listDomainInventory();
915
966
  },
@@ -1 +1 @@
1
- {"version":3,"file":"route53.d.ts","sourceRoot":"","sources":["../../src/lib/route53.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route53.d.ts","sourceRoot":"","sources":["../../src/lib/route53.ts"],"names":[],"mappings":"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"}
@@ -528,6 +528,7 @@ function createRoute53Provider(config) {
528
528
  }
529
529
  return {
530
530
  name: "route53",
531
+ dnsWriteScope: "changed-groups",
531
532
  async listDomains() {
532
533
  return listDomainInventory();
533
534
  },
package/dist/mcp/index.js CHANGED
@@ -15752,7 +15752,7 @@ var init_bowser = __esm(() => {
15752
15752
 
15753
15753
  // node_modules/@aws-sdk/core/dist-cjs/submodules/client/index.js
15754
15754
  var require_client2 = __commonJS((exports) => {
15755
- var __dirname = "/home/hasna/.hasna/repos/worktrees/open-domains/2a0dcf21-d730-4a74-bfc3-12e59e51ecd5/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
15755
+ var __dirname = "/home/hasna/.hasna/repos/worktrees/domains/0a933b3e-a459-4bcb-b94d-6ab12a2ec235/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
15756
15756
  var retry = require_retry();
15757
15757
  var protocols = require_protocols();
15758
15758
  var lambdaInvokeStore = require_invoke_store();
@@ -50615,6 +50615,7 @@ function createRoute53Provider(config2) {
50615
50615
  }
50616
50616
  return {
50617
50617
  name: "route53",
50618
+ dnsWriteScope: "changed-groups",
50618
50619
  async listDomains() {
50619
50620
  return listDomainInventory();
50620
50621
  },
@@ -50971,16 +50972,51 @@ async function listRecordsByNameType(zoneId, type, name, config2) {
50971
50972
  proxied: r4.proxied
50972
50973
  }));
50973
50974
  }
50974
- async function replaceRecordsByNameType(zoneId, records, config2) {
50975
+ function sameRecordIdentity(a4, b4) {
50976
+ return a4.type === b4.type && a4.name === b4.name && a4.content === b4.content && (a4.priority ?? undefined) === (b4.priority ?? undefined);
50977
+ }
50978
+ function resolveDesiredProxied(records, existing) {
50979
+ const omitted = records.filter((record) => record.proxied === undefined);
50980
+ if (omitted.length === 0)
50981
+ return records;
50982
+ const { type, name } = records[0];
50983
+ if (omitted.length === records.length) {
50984
+ const proxyStates = new Set(existing.map((record) => record.proxied));
50985
+ if (proxyStates.size > 1) {
50986
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name}: ` + "existing records have mixed proxied values while desired records omit proxied; " + "set proxied explicitly on every desired record");
50987
+ }
50988
+ const inherited = existing[0]?.proxied;
50989
+ return inherited === undefined ? records : records.map((record) => ({ ...record, proxied: inherited }));
50990
+ }
50991
+ const existingHasProxyState = existing.some((record) => record.proxied !== undefined);
50992
+ return records.map((record) => {
50993
+ if (record.proxied !== undefined)
50994
+ return record;
50995
+ const matches = existing.filter((candidate) => sameRecordIdentity(candidate, record));
50996
+ if (matches.length === 1 && matches[0].proxied !== undefined) {
50997
+ return { ...record, proxied: matches[0].proxied };
50998
+ }
50999
+ if (!existingHasProxyState)
51000
+ return record;
51001
+ throw new Error(`Cannot safely preserve Cloudflare proxied state for ${type} ${name} record ${record.content}: ` + "omitted proxied does not resolve to exactly one existing value; " + "set proxied explicitly on this desired record");
51002
+ });
51003
+ }
51004
+ async function prepareRecordsByNameType(zoneId, records, config2) {
50975
51005
  if (records.length === 0)
50976
51006
  return;
50977
51007
  const { type, name } = records[0];
50978
51008
  const existing = await listRecordsByNameType(zoneId, type, name, config2);
50979
- for (const record of existing) {
51009
+ if (existing.length === records.length && records.every((record) => existing.some((candidate) => sameRecordIdentity(candidate, record) && candidate.ttl === record.ttl && (record.proxied === undefined || candidate.proxied === record.proxied)))) {
51010
+ return;
51011
+ }
51012
+ return { existing, desired: resolveDesiredProxied(records, existing) };
51013
+ }
51014
+ async function replaceRecordsByNameType(zoneId, replacement, config2) {
51015
+ for (const record of replacement.existing) {
50980
51016
  if (record.id)
50981
51017
  await deleteRecord2(zoneId, record.id, config2);
50982
51018
  }
50983
- for (const record of records) {
51019
+ for (const record of replacement.desired) {
50984
51020
  await cfFetch(`/zones/${zoneId}/dns_records`, {
50985
51021
  method: "POST",
50986
51022
  body: {
@@ -50989,7 +51025,7 @@ async function replaceRecordsByNameType(zoneId, records, config2) {
50989
51025
  content: record.content,
50990
51026
  ttl: record.ttl ?? 1,
50991
51027
  priority: record.priority,
50992
- proxied: record.proxied ?? false
51028
+ ...record.proxied === undefined ? {} : { proxied: record.proxied }
50993
51029
  },
50994
51030
  config: config2
50995
51031
  });
@@ -51024,6 +51060,7 @@ function createCloudflareProvider(config2) {
51024
51060
  const cfg = config2 ?? getConfig3();
51025
51061
  return {
51026
51062
  name: "cloudflare",
51063
+ dnsWriteScope: "changed-groups",
51027
51064
  async listDomains() {
51028
51065
  const zones = await listZones(cfg);
51029
51066
  return zones.map(zoneToDomainInfo);
@@ -51074,7 +51111,8 @@ function createCloudflareProvider(config2) {
51074
51111
  name: r4.name,
51075
51112
  value: r4.content,
51076
51113
  ttl: r4.ttl === 1 ? 0 : r4.ttl,
51077
- priority: r4.priority
51114
+ priority: r4.priority,
51115
+ ...r4.proxied === undefined ? {} : { proxied: r4.proxied }
51078
51116
  }));
51079
51117
  },
51080
51118
  async setDnsRecords(domain, records) {
@@ -51085,11 +51123,24 @@ function createCloudflareProvider(config2) {
51085
51123
  for (const r4 of records) {
51086
51124
  const key = `${r4.type}|${r4.name}`;
51087
51125
  const existing = grouped.get(key) ?? [];
51088
- existing.push({ type: r4.type, name: r4.name, content: r4.value, ttl: r4.ttl || 1, priority: r4.priority });
51126
+ existing.push({
51127
+ type: r4.type,
51128
+ name: r4.name,
51129
+ content: r4.value,
51130
+ ttl: r4.ttl || 1,
51131
+ priority: r4.priority,
51132
+ ...r4.proxied === undefined ? {} : { proxied: r4.proxied }
51133
+ });
51089
51134
  grouped.set(key, existing);
51090
51135
  }
51136
+ const replacements = [];
51091
51137
  for (const group of grouped.values()) {
51092
- await replaceRecordsByNameType(zone.id, group, cfg);
51138
+ const replacement = await prepareRecordsByNameType(zone.id, group, cfg);
51139
+ if (replacement)
51140
+ replacements.push(replacement);
51141
+ }
51142
+ for (const replacement of replacements) {
51143
+ await replaceRecordsByNameType(zone.id, replacement, cfg);
51093
51144
  }
51094
51145
  return true;
51095
51146
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/domains",
3
- "version": "0.0.37",
3
+ "version": "0.0.38",
4
4
  "description": "Domain portfolio, registrar, marketplace, and DNS management for AI agents — CLI + MCP + HTTP API + SDK, local SQLite or cloud Postgres",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",