groundmail 0.26.1 → 0.28.0
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/authjs.d.ts +1 -1
- package/dist/authjs.js +1 -1
- package/dist/better-auth.d.ts +1 -1
- package/dist/better-auth.js +1 -1
- package/dist/{chunk-E6G7G2PM.js → chunk-POS35D4J.js} +401 -17
- package/dist/clerk.d.ts +1 -1
- package/dist/clerk.js +1 -1
- package/dist/{client-DZNmwhee.d.ts → client-DdtHUMEu.d.ts} +23 -8
- package/dist/index.d.ts +9 -3
- package/dist/index.js +1 -1
- package/dist/payload.d.ts +1 -1
- package/dist/payload.js +1 -1
- package/package.json +2 -2
package/dist/authjs.d.ts
CHANGED
package/dist/authjs.js
CHANGED
package/dist/better-auth.d.ts
CHANGED
package/dist/better-auth.js
CHANGED
|
@@ -71,9 +71,9 @@ function isSpfRecord(value) {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// src/dns/cloudflare.ts
|
|
74
|
-
function relativeName(
|
|
74
|
+
function relativeName(fqdn2, zone) {
|
|
75
75
|
const domain = zone.replace(/\.$/, "").toLowerCase();
|
|
76
|
-
const host =
|
|
76
|
+
const host = fqdn2.replace(/\.$/, "").toLowerCase();
|
|
77
77
|
if (host === domain) return "@";
|
|
78
78
|
if (host.endsWith(`.${domain}`)) return host.slice(0, -(domain.length + 1));
|
|
79
79
|
return host;
|
|
@@ -301,10 +301,185 @@ function createCloudflareProvider(options) {
|
|
|
301
301
|
};
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
// src/dns/record-store.ts
|
|
305
|
+
function zoneNameCandidates2(domain) {
|
|
306
|
+
const labels = domain.replace(/\.$/, "").toLowerCase().split(".").filter(Boolean);
|
|
307
|
+
const candidates = [];
|
|
308
|
+
for (let i = 0; i <= labels.length - 2; i++) {
|
|
309
|
+
candidates.push(labels.slice(i).join("."));
|
|
310
|
+
}
|
|
311
|
+
return candidates;
|
|
312
|
+
}
|
|
313
|
+
function relativeName2(fqdn2, zone) {
|
|
314
|
+
const domain = zone.replace(/\.$/, "").toLowerCase();
|
|
315
|
+
const host = fqdn2.replace(/\.$/, "").toLowerCase();
|
|
316
|
+
if (host === domain) return "";
|
|
317
|
+
if (host.endsWith(`.${domain}`)) return host.slice(0, -(domain.length + 1));
|
|
318
|
+
return host;
|
|
319
|
+
}
|
|
320
|
+
function fqdn(name, zone) {
|
|
321
|
+
return name ? `${name}.${zone}` : zone;
|
|
322
|
+
}
|
|
323
|
+
function normalizeValue(type, value) {
|
|
324
|
+
const trimmed = value.trim();
|
|
325
|
+
if (type === "TXT") return trimmed.replace(/^"([\s\S]*)"$/, "$1").replace(/"\s+"/g, "");
|
|
326
|
+
return trimmed.replace(/\.$/, "").toLowerCase();
|
|
327
|
+
}
|
|
328
|
+
function ownedTxt(purpose, value) {
|
|
329
|
+
const lower = value.toLowerCase();
|
|
330
|
+
if (purpose === "Domain ownership") return lower.includes("groundmail-verify=");
|
|
331
|
+
if (purpose === "DKIM") return lower.includes("v=dkim1");
|
|
332
|
+
if (purpose === "DMARC") return lower.includes("v=dmarc1");
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
async function applyToRecordStore(zone, records, store) {
|
|
336
|
+
const results = [];
|
|
337
|
+
let cached = await store.list();
|
|
338
|
+
const at = (type, name) => cached.filter((row) => row.type.toUpperCase() === type && row.name === name);
|
|
339
|
+
for (const record of records) {
|
|
340
|
+
const type = record.type.toUpperCase();
|
|
341
|
+
const name = relativeName2(record.host, zone);
|
|
342
|
+
const value = normalizeValue(type, record.value);
|
|
343
|
+
const done = (action, detail) => results.push({ purpose: record.purpose, host: record.host, action, ...detail ? { detail } : {} });
|
|
344
|
+
if (type === "CNAME") {
|
|
345
|
+
const existing = at("CNAME", name)[0];
|
|
346
|
+
if (existing && normalizeValue(type, existing.value) === value) {
|
|
347
|
+
done("unchanged");
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
if (existing) {
|
|
351
|
+
await store.update(existing, { name, type, value });
|
|
352
|
+
done("updated");
|
|
353
|
+
} else {
|
|
354
|
+
await store.create({ name, type, value });
|
|
355
|
+
done("created");
|
|
356
|
+
}
|
|
357
|
+
} else if (type === "MX") {
|
|
358
|
+
const priority = record.priority ?? 10;
|
|
359
|
+
const sameName = at("MX", name);
|
|
360
|
+
if (sameName.some((row) => normalizeValue(type, row.value) === value && (row.priority ?? 10) === priority)) {
|
|
361
|
+
done("unchanged");
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
await store.create({ name, type, value, priority });
|
|
365
|
+
done(sameName.length > 0 ? "merged" : "created");
|
|
366
|
+
} else if (type !== "TXT") {
|
|
367
|
+
done("unchanged", `Skipped unsupported type ${record.type}`);
|
|
368
|
+
continue;
|
|
369
|
+
} else if (record.purpose === "SPF") {
|
|
370
|
+
const existing = at("TXT", name).find((row) => isSpfRecord(normalizeValue(type, row.value)));
|
|
371
|
+
const includeHost = record.value.match(/include:([^\s"]+)/i)?.[1] || "spf.groundmail.dev";
|
|
372
|
+
const current = existing ? normalizeValue(type, existing.value) : void 0;
|
|
373
|
+
const merged = mergeSpfInclude(current, includeHost);
|
|
374
|
+
if (existing && current?.trim() === merged.trim()) {
|
|
375
|
+
done("unchanged", "SPF already includes Groundmail");
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (existing) {
|
|
379
|
+
await store.update(existing, { name, type, value: merged });
|
|
380
|
+
done("merged", merged);
|
|
381
|
+
} else {
|
|
382
|
+
await store.create({ name, type, value: merged });
|
|
383
|
+
done("created", merged);
|
|
384
|
+
}
|
|
385
|
+
} else {
|
|
386
|
+
const sameName = at("TXT", name);
|
|
387
|
+
if (sameName.some((row) => normalizeValue(type, row.value) === value)) {
|
|
388
|
+
done("unchanged");
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
const replaceable = sameName.find((row) => ownedTxt(record.purpose, normalizeValue(type, row.value)));
|
|
392
|
+
if (replaceable) {
|
|
393
|
+
await store.update(replaceable, { name, type, value });
|
|
394
|
+
done("updated");
|
|
395
|
+
} else {
|
|
396
|
+
await store.create({ name, type, value });
|
|
397
|
+
done("created");
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
cached = await store.list();
|
|
401
|
+
}
|
|
402
|
+
return results;
|
|
403
|
+
}
|
|
404
|
+
async function resolveZone(domain, hostLabel, lookup) {
|
|
405
|
+
for (const candidate of zoneNameCandidates2(domain)) {
|
|
406
|
+
const info = await lookup(candidate);
|
|
407
|
+
if (info !== null) return { zone: candidate, info };
|
|
408
|
+
}
|
|
409
|
+
throw new Error(`No ${hostLabel} DNS zone found for ${domain}. The domain must use ${hostLabel} nameservers.`);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// src/dns/godaddy-token.ts
|
|
413
|
+
function createGoDaddyTokenProvider(options) {
|
|
414
|
+
const fetchImpl = options.fetchImpl || fetch;
|
|
415
|
+
async function godaddy(path, init) {
|
|
416
|
+
const response = await fetchImpl(`https://api.godaddy.com/v3/domains${path}`, {
|
|
417
|
+
...init,
|
|
418
|
+
headers: {
|
|
419
|
+
Authorization: `Bearer ${options.apiToken}`,
|
|
420
|
+
"Content-Type": "application/json",
|
|
421
|
+
Accept: "application/json",
|
|
422
|
+
...init?.headers || {}
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
const body = response.status === 204 ? {} : await response.json().catch(() => ({}));
|
|
426
|
+
if (!response.ok && response.status !== 404) {
|
|
427
|
+
if (response.status === 401 || response.status === 403) {
|
|
428
|
+
throw new Error(
|
|
429
|
+
"GoDaddy refused the token. Create a Personal Access Token with the domains.domain:read and domains.dns:update scopes."
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
throw new Error(body.message || body.code || `GoDaddy HTTP ${response.status}`);
|
|
433
|
+
}
|
|
434
|
+
return { status: response.status, body };
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
name: "godaddy",
|
|
438
|
+
async apply(domain, records) {
|
|
439
|
+
const { zone } = await resolveZone(domain, "GoDaddy", async (candidate) => {
|
|
440
|
+
const { status } = await godaddy(`/zones/${encodeURIComponent(candidate)}/dns-records?pageSize=1`);
|
|
441
|
+
return status === 404 ? null : true;
|
|
442
|
+
});
|
|
443
|
+
const path = `/zones/${encodeURIComponent(zone)}/dns-records`;
|
|
444
|
+
const body = (record) => ({
|
|
445
|
+
name: record.name || "@",
|
|
446
|
+
type: record.type,
|
|
447
|
+
data: record.value,
|
|
448
|
+
ttl: 600,
|
|
449
|
+
...record.priority != null ? { priority: record.priority } : {}
|
|
450
|
+
});
|
|
451
|
+
const write = async (method, suffix, record) => {
|
|
452
|
+
const { status } = await godaddy(`${path}${suffix}`, { method, body: JSON.stringify(body(record)) });
|
|
453
|
+
if (status === 404) throw new Error(`GoDaddy lost the ${zone} zone mid-update`);
|
|
454
|
+
};
|
|
455
|
+
return applyToRecordStore(zone, records, {
|
|
456
|
+
async list() {
|
|
457
|
+
const rows = [];
|
|
458
|
+
for (let page = 1; page <= 20; page++) {
|
|
459
|
+
const { body: list } = await godaddy(`${path}?page=${page}&pageSize=100`);
|
|
460
|
+
const items = list.items || [];
|
|
461
|
+
rows.push(...items);
|
|
462
|
+
if (items.length < 100 || !list.links?.some((link) => link.rel === "next")) break;
|
|
463
|
+
}
|
|
464
|
+
return rows.map((row) => ({
|
|
465
|
+
id: row.recordId,
|
|
466
|
+
name: row.name === "@" ? "" : row.name.toLowerCase(),
|
|
467
|
+
type: row.type,
|
|
468
|
+
value: row.data,
|
|
469
|
+
priority: row.priority ?? void 0
|
|
470
|
+
}));
|
|
471
|
+
},
|
|
472
|
+
create: (record) => write("POST", "", record),
|
|
473
|
+
update: (existing, record) => write("PUT", `/${encodeURIComponent(existing.id)}`, record)
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
304
479
|
// src/dns/godaddy.ts
|
|
305
|
-
function
|
|
480
|
+
function relativeName3(fqdn2, zone) {
|
|
306
481
|
const domain = zone.replace(/\.$/, "").toLowerCase();
|
|
307
|
-
const host =
|
|
482
|
+
const host = fqdn2.replace(/\.$/, "").toLowerCase();
|
|
308
483
|
if (host === domain) return "@";
|
|
309
484
|
if (host.endsWith(`.${domain}`)) return host.slice(0, -(domain.length + 1));
|
|
310
485
|
return host;
|
|
@@ -318,7 +493,7 @@ function serializeGoDaddyMxRecords(name, rows) {
|
|
|
318
493
|
ttl: Math.max(row.ttl || 600, 600)
|
|
319
494
|
}));
|
|
320
495
|
}
|
|
321
|
-
function
|
|
496
|
+
function createGoDaddyKeyProvider(options) {
|
|
322
497
|
const fetchImpl = options.fetchImpl || fetch;
|
|
323
498
|
const headers = {
|
|
324
499
|
Authorization: `sso-key ${options.apiKey}:${options.apiSecret}`,
|
|
@@ -345,7 +520,7 @@ function createGoDaddyProvider(options) {
|
|
|
345
520
|
const results = [];
|
|
346
521
|
for (const record of records) {
|
|
347
522
|
const recordType = record.type.toUpperCase();
|
|
348
|
-
const name =
|
|
523
|
+
const name = relativeName3(record.host, zone);
|
|
349
524
|
if (recordType === "CNAME") {
|
|
350
525
|
const target = record.value.replace(/\.$/, "");
|
|
351
526
|
const existing2 = await gd(
|
|
@@ -470,9 +645,192 @@ function createGoDaddyProvider(options) {
|
|
|
470
645
|
}
|
|
471
646
|
};
|
|
472
647
|
}
|
|
648
|
+
function createGoDaddyProvider(options) {
|
|
649
|
+
if ("apiToken" in options) return createGoDaddyTokenProvider({ apiToken: options.apiToken, fetchImpl: options.fetchImpl });
|
|
650
|
+
return createGoDaddyKeyProvider(options);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// src/dns/digitalocean.ts
|
|
654
|
+
function createDigitalOceanProvider(options) {
|
|
655
|
+
const fetchImpl = options.fetchImpl || fetch;
|
|
656
|
+
async function digitalocean(path, init) {
|
|
657
|
+
const response = await fetchImpl(`https://api.digitalocean.com/v2${path}`, {
|
|
658
|
+
...init,
|
|
659
|
+
headers: { Authorization: `Bearer ${options.apiToken}`, "Content-Type": "application/json", ...init?.headers || {} }
|
|
660
|
+
});
|
|
661
|
+
const body = await response.json().catch(() => ({}));
|
|
662
|
+
if (!response.ok && response.status !== 404) {
|
|
663
|
+
if (response.status === 403) {
|
|
664
|
+
throw new Error("DigitalOcean refused the DNS change. Reconnect DigitalOcean under Integrations to allow DNS.");
|
|
665
|
+
}
|
|
666
|
+
throw new Error(body.message || `DigitalOcean HTTP ${response.status}`);
|
|
667
|
+
}
|
|
668
|
+
return { status: response.status, body };
|
|
669
|
+
}
|
|
670
|
+
return {
|
|
671
|
+
name: "digitalocean",
|
|
672
|
+
async apply(domain, records) {
|
|
673
|
+
const { zone } = await resolveZone(domain, "DigitalOcean", async (candidate) => {
|
|
674
|
+
const { status } = await digitalocean(`/domains/${encodeURIComponent(candidate)}`);
|
|
675
|
+
return status === 404 ? null : true;
|
|
676
|
+
});
|
|
677
|
+
const path = `/domains/${encodeURIComponent(zone)}/records`;
|
|
678
|
+
const body = (record) => ({
|
|
679
|
+
type: record.type,
|
|
680
|
+
name: record.name || "@",
|
|
681
|
+
data: record.type === "TXT" ? record.value : `${record.value}.`,
|
|
682
|
+
ttl: 1800,
|
|
683
|
+
...record.priority != null ? { priority: record.priority } : {}
|
|
684
|
+
});
|
|
685
|
+
const write = async (method, suffix, record) => {
|
|
686
|
+
const { status } = await digitalocean(`${path}${suffix}`, { method, body: JSON.stringify(body(record)) });
|
|
687
|
+
if (status === 404) throw new Error(`DigitalOcean lost the ${zone} zone mid-update`);
|
|
688
|
+
};
|
|
689
|
+
return applyToRecordStore(zone, records, {
|
|
690
|
+
async list() {
|
|
691
|
+
const rows = [];
|
|
692
|
+
for (let page = 1; page <= 20; page++) {
|
|
693
|
+
const { body: list } = await digitalocean(`${path}?per_page=200&page=${page}`);
|
|
694
|
+
rows.push(...list.domain_records || []);
|
|
695
|
+
if (!list.links?.pages?.next) break;
|
|
696
|
+
}
|
|
697
|
+
return rows.map((row) => ({
|
|
698
|
+
id: String(row.id),
|
|
699
|
+
name: row.name === "@" ? "" : row.name.toLowerCase(),
|
|
700
|
+
type: row.type,
|
|
701
|
+
value: row.data,
|
|
702
|
+
priority: row.priority ?? void 0
|
|
703
|
+
}));
|
|
704
|
+
},
|
|
705
|
+
create: (record) => write("POST", "", record),
|
|
706
|
+
update: (existing, record) => write("PUT", `/${existing.id}`, record)
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// src/dns/dnsimple.ts
|
|
713
|
+
function createDnsimpleProvider(options) {
|
|
714
|
+
const fetchImpl = options.fetchImpl || fetch;
|
|
715
|
+
const base = `https://api.dnsimple.com/v2/${encodeURIComponent(options.accountId)}`;
|
|
716
|
+
async function dnsimple(path, init) {
|
|
717
|
+
const response = await fetchImpl(`${base}${path}`, {
|
|
718
|
+
...init,
|
|
719
|
+
headers: {
|
|
720
|
+
Authorization: `Bearer ${options.apiToken}`,
|
|
721
|
+
"Content-Type": "application/json",
|
|
722
|
+
Accept: "application/json",
|
|
723
|
+
...init?.headers || {}
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
const body = await response.json().catch(() => ({}));
|
|
727
|
+
if (!response.ok && response.status !== 404) throw new Error(body.message || `DNSimple HTTP ${response.status}`);
|
|
728
|
+
return { status: response.status, body };
|
|
729
|
+
}
|
|
730
|
+
return {
|
|
731
|
+
name: "dnsimple",
|
|
732
|
+
async apply(domain, records) {
|
|
733
|
+
const { zone } = await resolveZone(domain, "DNSimple", async (candidate) => {
|
|
734
|
+
const { status } = await dnsimple(`/zones/${encodeURIComponent(candidate)}`);
|
|
735
|
+
return status === 404 ? null : true;
|
|
736
|
+
});
|
|
737
|
+
const path = `/zones/${encodeURIComponent(zone)}/records`;
|
|
738
|
+
const body = (record) => ({
|
|
739
|
+
name: record.name,
|
|
740
|
+
type: record.type,
|
|
741
|
+
content: record.value,
|
|
742
|
+
ttl: 3600,
|
|
743
|
+
...record.priority != null ? { priority: record.priority } : {}
|
|
744
|
+
});
|
|
745
|
+
const write = async (method, suffix, record) => {
|
|
746
|
+
const { status } = await dnsimple(`${path}${suffix}`, { method, body: JSON.stringify(body(record)) });
|
|
747
|
+
if (status === 404) throw new Error(`DNSimple lost the ${zone} zone mid-update`);
|
|
748
|
+
};
|
|
749
|
+
return applyToRecordStore(zone, records, {
|
|
750
|
+
async list() {
|
|
751
|
+
const rows = [];
|
|
752
|
+
for (let page = 1; page <= 20; page++) {
|
|
753
|
+
const { body: list } = await dnsimple(`${path}?per_page=100&page=${page}`);
|
|
754
|
+
rows.push(...list.data || []);
|
|
755
|
+
if ((list.pagination?.total_pages ?? 1) <= page) break;
|
|
756
|
+
}
|
|
757
|
+
return rows.filter((row) => !row.system_record).map((row) => ({
|
|
758
|
+
id: String(row.id),
|
|
759
|
+
name: row.name.toLowerCase(),
|
|
760
|
+
type: row.type,
|
|
761
|
+
value: row.content,
|
|
762
|
+
priority: row.priority ?? void 0
|
|
763
|
+
}));
|
|
764
|
+
},
|
|
765
|
+
create: (record) => write("POST", "", record),
|
|
766
|
+
update: (existing, record) => write("PATCH", `/${existing.id}`, record)
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// src/dns/netlify.ts
|
|
773
|
+
function createNetlifyProvider(options) {
|
|
774
|
+
const fetchImpl = options.fetchImpl || fetch;
|
|
775
|
+
async function netlify(path, init) {
|
|
776
|
+
const response = await fetchImpl(`https://api.netlify.com/api/v1${path}`, {
|
|
777
|
+
...init,
|
|
778
|
+
headers: { Authorization: `Bearer ${options.apiToken}`, "Content-Type": "application/json", ...init?.headers || {} }
|
|
779
|
+
});
|
|
780
|
+
const body = await response.json().catch(() => ({}));
|
|
781
|
+
if (!response.ok) throw new Error(body.message || `Netlify HTTP ${response.status}`);
|
|
782
|
+
return body;
|
|
783
|
+
}
|
|
784
|
+
return {
|
|
785
|
+
name: "netlify",
|
|
786
|
+
async apply(domain, records) {
|
|
787
|
+
const zones = await netlify("/dns_zones");
|
|
788
|
+
const { zone, info } = await resolveZone(
|
|
789
|
+
domain,
|
|
790
|
+
"Netlify",
|
|
791
|
+
async (candidate) => zones.find((z) => z.name.toLowerCase() === candidate) ?? null
|
|
792
|
+
);
|
|
793
|
+
const body = (record) => ({
|
|
794
|
+
type: record.type,
|
|
795
|
+
hostname: fqdn(record.name, zone),
|
|
796
|
+
value: record.value,
|
|
797
|
+
ttl: 3600,
|
|
798
|
+
...record.priority != null ? { priority: record.priority } : {}
|
|
799
|
+
});
|
|
800
|
+
const create = async (record) => {
|
|
801
|
+
await netlify(`/dns_zones/${info.id}/dns_records`, { method: "POST", body: JSON.stringify(body(record)) });
|
|
802
|
+
};
|
|
803
|
+
return applyToRecordStore(zone, records, {
|
|
804
|
+
async list() {
|
|
805
|
+
const rows = await netlify(`/dns_zones/${info.id}/dns_records`);
|
|
806
|
+
return rows.filter((row) => !row.managed).map((row) => ({
|
|
807
|
+
id: row.id,
|
|
808
|
+
name: relativeName2(row.hostname, zone),
|
|
809
|
+
type: row.type,
|
|
810
|
+
value: row.value,
|
|
811
|
+
priority: row.priority ?? void 0
|
|
812
|
+
}));
|
|
813
|
+
},
|
|
814
|
+
create,
|
|
815
|
+
// TXT: add the new value before removing the old, so SPF never disappears. A
|
|
816
|
+
// name can only hold one CNAME, so that one goes the other way round.
|
|
817
|
+
async update(existing, record) {
|
|
818
|
+
const remove = () => netlify(`/dns_zones/${info.id}/dns_records/${existing.id}`, { method: "DELETE" });
|
|
819
|
+
if (record.type === "CNAME") {
|
|
820
|
+
await remove();
|
|
821
|
+
await create(record);
|
|
822
|
+
} else {
|
|
823
|
+
await create(record);
|
|
824
|
+
await remove();
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
}
|
|
473
831
|
|
|
474
832
|
// src/dns/vercel.ts
|
|
475
|
-
function
|
|
833
|
+
function zoneNameCandidates3(domain) {
|
|
476
834
|
const labels = domain.replace(/\.$/, "").toLowerCase().split(".").filter(Boolean);
|
|
477
835
|
const candidates = [];
|
|
478
836
|
for (let i = 0; i <= labels.length - 2; i++) {
|
|
@@ -480,9 +838,9 @@ function zoneNameCandidates2(domain) {
|
|
|
480
838
|
}
|
|
481
839
|
return candidates;
|
|
482
840
|
}
|
|
483
|
-
function
|
|
841
|
+
function relativeName4(fqdn2, zone) {
|
|
484
842
|
const domain = zone.replace(/\.$/, "").toLowerCase();
|
|
485
|
-
const host =
|
|
843
|
+
const host = fqdn2.replace(/\.$/, "").toLowerCase();
|
|
486
844
|
if (host === domain) return "";
|
|
487
845
|
if (host.endsWith(`.${domain}`)) return host.slice(0, -(domain.length + 1));
|
|
488
846
|
return host;
|
|
@@ -530,7 +888,7 @@ function createVercelProvider(options) {
|
|
|
530
888
|
}
|
|
531
889
|
async function resolveDomain(domain) {
|
|
532
890
|
const errors = [];
|
|
533
|
-
for (const candidate of
|
|
891
|
+
for (const candidate of zoneNameCandidates3(domain)) {
|
|
534
892
|
try {
|
|
535
893
|
await listRecords(candidate);
|
|
536
894
|
return candidate;
|
|
@@ -554,7 +912,7 @@ function createVercelProvider(options) {
|
|
|
554
912
|
};
|
|
555
913
|
for (const record of records) {
|
|
556
914
|
const recordType = record.type.toUpperCase();
|
|
557
|
-
const name =
|
|
915
|
+
const name = relativeName4(record.host, zone);
|
|
558
916
|
if (recordType === "CNAME") {
|
|
559
917
|
const target = record.value.replace(/\.$/, "").toLowerCase();
|
|
560
918
|
const existing = cached.find(
|
|
@@ -706,11 +1064,13 @@ function createDnsProvider(provider, credentials, fetchImpl) {
|
|
|
706
1064
|
});
|
|
707
1065
|
}
|
|
708
1066
|
if (provider === "godaddy") {
|
|
1067
|
+
const apiToken = credentials.godaddyApiToken;
|
|
1068
|
+
if (apiToken) return createGoDaddyProvider({ apiToken, fetchImpl });
|
|
709
1069
|
const apiKey = credentials.godaddyApiKey;
|
|
710
1070
|
const apiSecret = credentials.godaddyApiSecret;
|
|
711
1071
|
if (!apiKey || !apiSecret) {
|
|
712
1072
|
throw new Error(
|
|
713
|
-
"Missing GoDaddy credentials. Set GODADDY_API_KEY and GODADDY_API_SECRET."
|
|
1073
|
+
"Missing GoDaddy credentials. Set GODADDY_PAT (a Personal Access Token), or GODADDY_API_KEY and GODADDY_API_SECRET."
|
|
714
1074
|
);
|
|
715
1075
|
}
|
|
716
1076
|
return createGoDaddyProvider({ apiKey, apiSecret, fetchImpl });
|
|
@@ -726,6 +1086,24 @@ function createDnsProvider(provider, credentials, fetchImpl) {
|
|
|
726
1086
|
fetchImpl
|
|
727
1087
|
});
|
|
728
1088
|
}
|
|
1089
|
+
if (provider === "netlify") {
|
|
1090
|
+
const apiToken = credentials.netlifyApiToken;
|
|
1091
|
+
if (!apiToken) throw new Error("Missing Netlify token. Set NETLIFY_AUTH_TOKEN or pass netlifyApiToken.");
|
|
1092
|
+
return createNetlifyProvider({ apiToken, fetchImpl });
|
|
1093
|
+
}
|
|
1094
|
+
if (provider === "digitalocean") {
|
|
1095
|
+
const apiToken = credentials.digitaloceanApiToken;
|
|
1096
|
+
if (!apiToken) throw new Error("Missing DigitalOcean token. Set DIGITALOCEAN_TOKEN or pass digitaloceanApiToken.");
|
|
1097
|
+
return createDigitalOceanProvider({ apiToken, fetchImpl });
|
|
1098
|
+
}
|
|
1099
|
+
if (provider === "dnsimple") {
|
|
1100
|
+
const apiToken = credentials.dnsimpleApiToken;
|
|
1101
|
+
const accountId = credentials.dnsimpleAccountId;
|
|
1102
|
+
if (!apiToken || !accountId) {
|
|
1103
|
+
throw new Error("Missing DNSimple credentials. Set DNSIMPLE_TOKEN and DNSIMPLE_ACCOUNT_ID.");
|
|
1104
|
+
}
|
|
1105
|
+
return createDnsimpleProvider({ apiToken, accountId, fetchImpl });
|
|
1106
|
+
}
|
|
729
1107
|
throw new Error(`Unsupported DNS provider: ${provider}`);
|
|
730
1108
|
}
|
|
731
1109
|
async function applyDnsRecords(input) {
|
|
@@ -1059,8 +1437,9 @@ var DomainsResource = class {
|
|
|
1059
1437
|
});
|
|
1060
1438
|
}
|
|
1061
1439
|
/**
|
|
1062
|
-
* Apply DNS using the public API
|
|
1063
|
-
*
|
|
1440
|
+
* Apply DNS using the public API with the DNS host connected in the dashboard (Cloudflare,
|
|
1441
|
+
* Vercel, GoDaddy, Netlify, DigitalOcean or DNSimple). GoDaddy also accepts one-time
|
|
1442
|
+
* credentials on the request.
|
|
1064
1443
|
*/
|
|
1065
1444
|
async apply(idOrName, options = {}) {
|
|
1066
1445
|
return this.client.request(`/domains/${encodeURIComponent(idOrName)}`, {
|
|
@@ -1073,8 +1452,8 @@ var DomainsResource = class {
|
|
|
1073
1452
|
});
|
|
1074
1453
|
}
|
|
1075
1454
|
/**
|
|
1076
|
-
* Fetch Groundmail DNS records, then write them at Cloudflare, Vercel,
|
|
1077
|
-
* using the caller's provider credentials (never sent to Groundmail).
|
|
1455
|
+
* Fetch Groundmail DNS records, then write them at Cloudflare, Vercel, GoDaddy, Netlify,
|
|
1456
|
+
* DigitalOcean or DNSimple using the caller's provider credentials (never sent to Groundmail).
|
|
1078
1457
|
*/
|
|
1079
1458
|
async applyDns(params) {
|
|
1080
1459
|
const detail = await this.get(params.idOrName);
|
|
@@ -1089,10 +1468,15 @@ var DomainsResource = class {
|
|
|
1089
1468
|
credentials: {
|
|
1090
1469
|
cloudflareApiToken: params.cloudflareApiToken,
|
|
1091
1470
|
cloudflareZoneId: params.cloudflareZoneId,
|
|
1471
|
+
godaddyApiToken: params.godaddyApiToken,
|
|
1092
1472
|
godaddyApiKey: params.godaddyApiKey,
|
|
1093
1473
|
godaddyApiSecret: params.godaddyApiSecret,
|
|
1094
1474
|
vercelApiToken: params.vercelApiToken,
|
|
1095
|
-
vercelTeamId: params.vercelTeamId
|
|
1475
|
+
vercelTeamId: params.vercelTeamId,
|
|
1476
|
+
netlifyApiToken: params.netlifyApiToken,
|
|
1477
|
+
digitaloceanApiToken: params.digitaloceanApiToken,
|
|
1478
|
+
dnsimpleApiToken: params.dnsimpleApiToken,
|
|
1479
|
+
dnsimpleAccountId: params.dnsimpleAccountId
|
|
1096
1480
|
},
|
|
1097
1481
|
fetchImpl: this.client.fetchImpl
|
|
1098
1482
|
});
|
package/dist/clerk.d.ts
CHANGED
package/dist/clerk.js
CHANGED
|
@@ -1013,20 +1013,28 @@ type UpdateDomainParams = {
|
|
|
1013
1013
|
/** What to do with received mail at or above the threshold. */
|
|
1014
1014
|
inbound_spam_action?: 'flag' | 'drop';
|
|
1015
1015
|
};
|
|
1016
|
-
type DnsProviderName = 'cloudflare' | 'godaddy' | 'vercel';
|
|
1016
|
+
type DnsProviderName = 'cloudflare' | 'godaddy' | 'vercel' | 'netlify' | 'digitalocean' | 'dnsimple';
|
|
1017
1017
|
type RemoteApplyDnsCredentials = {
|
|
1018
1018
|
/** Inline Cloudflare token instead of the stored dashboard integration. */
|
|
1019
1019
|
apiToken?: string;
|
|
1020
1020
|
zoneId?: string;
|
|
1021
1021
|
cloudflareApiToken?: string;
|
|
1022
1022
|
cloudflareZoneId?: string;
|
|
1023
|
-
/** GoDaddy one-time credentials. */
|
|
1023
|
+
/** GoDaddy one-time credentials: a Personal Access Token in apiToken, or the classic key and secret. */
|
|
1024
|
+
godaddyApiToken?: string;
|
|
1024
1025
|
apiKey?: string;
|
|
1025
1026
|
apiSecret?: string;
|
|
1026
1027
|
godaddyApiKey?: string;
|
|
1027
1028
|
godaddyApiSecret?: string;
|
|
1028
1029
|
vercelApiToken?: string;
|
|
1029
1030
|
vercelTeamId?: string;
|
|
1031
|
+
/** Inline token for netlify, digitalocean or dnsimple instead of the stored connection. */
|
|
1032
|
+
netlifyApiToken?: string;
|
|
1033
|
+
digitaloceanApiToken?: string;
|
|
1034
|
+
dnsimpleApiToken?: string;
|
|
1035
|
+
/** DNSimple account the inline token belongs to. */
|
|
1036
|
+
dnsimpleAccountId?: string;
|
|
1037
|
+
accountId?: string;
|
|
1030
1038
|
};
|
|
1031
1039
|
type ApplyDnsParams = {
|
|
1032
1040
|
provider: DnsProviderName;
|
|
@@ -1034,10 +1042,16 @@ type ApplyDnsParams = {
|
|
|
1034
1042
|
idOrName: string;
|
|
1035
1043
|
cloudflareApiToken?: string;
|
|
1036
1044
|
cloudflareZoneId?: string;
|
|
1045
|
+
/** GoDaddy Personal Access Token (preferred over the key and secret). */
|
|
1046
|
+
godaddyApiToken?: string;
|
|
1037
1047
|
godaddyApiKey?: string;
|
|
1038
1048
|
godaddyApiSecret?: string;
|
|
1039
1049
|
vercelApiToken?: string;
|
|
1040
1050
|
vercelTeamId?: string;
|
|
1051
|
+
netlifyApiToken?: string;
|
|
1052
|
+
digitaloceanApiToken?: string;
|
|
1053
|
+
dnsimpleApiToken?: string;
|
|
1054
|
+
dnsimpleAccountId?: string;
|
|
1041
1055
|
};
|
|
1042
1056
|
type ApplyDnsRecordResult = {
|
|
1043
1057
|
purpose: string;
|
|
@@ -1514,7 +1528,7 @@ type DmarcMonitoringDisabled = {
|
|
|
1514
1528
|
type DmarcStatus = DmarcMonitoring | DmarcMonitoringDisabled;
|
|
1515
1529
|
type EnableDmarcParams = {
|
|
1516
1530
|
/** Also write the record through a DNS provider connected under Settings → Integrations. */
|
|
1517
|
-
apply?:
|
|
1531
|
+
apply?: DnsProviderName;
|
|
1518
1532
|
digest_enabled?: boolean;
|
|
1519
1533
|
};
|
|
1520
1534
|
type EnableDmarcResult = {
|
|
@@ -1561,16 +1575,17 @@ declare class DomainsResource {
|
|
|
1561
1575
|
ok: boolean;
|
|
1562
1576
|
}>;
|
|
1563
1577
|
/**
|
|
1564
|
-
* Apply DNS using the public API
|
|
1565
|
-
*
|
|
1578
|
+
* Apply DNS using the public API with the DNS host connected in the dashboard (Cloudflare,
|
|
1579
|
+
* Vercel, GoDaddy, Netlify, DigitalOcean or DNSimple). GoDaddy also accepts one-time
|
|
1580
|
+
* credentials on the request.
|
|
1566
1581
|
*/
|
|
1567
1582
|
apply(idOrName: string, options?: {
|
|
1568
|
-
provider?:
|
|
1583
|
+
provider?: DnsProviderName;
|
|
1569
1584
|
credentials?: RemoteApplyDnsCredentials;
|
|
1570
1585
|
}): Promise<ApplyDnsResult>;
|
|
1571
1586
|
/**
|
|
1572
|
-
* Fetch Groundmail DNS records, then write them at Cloudflare, Vercel,
|
|
1573
|
-
* using the caller's provider credentials (never sent to Groundmail).
|
|
1587
|
+
* Fetch Groundmail DNS records, then write them at Cloudflare, Vercel, GoDaddy, Netlify,
|
|
1588
|
+
* DigitalOcean or DNSimple using the caller's provider credentials (never sent to Groundmail).
|
|
1574
1589
|
*/
|
|
1575
1590
|
applyDns(params: ApplyDnsParams): Promise<ApplyDnsResult>;
|
|
1576
1591
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as ApiErrorBody, D as DnsRecord } from './client-
|
|
2
|
-
export { a as ApiErrorCode, b as ApiKey, c as ApiKeyScope, d as ApplyDnsParams, e as ApplyDnsRecordResult, f as ApplyDnsResult, g as Asset, h as Automation, i as AutomationResult, j as AutomationRun, k as AutomationRunResponse, l as AutomationRunStatus, m as AutomationRunStep, n as AutomationRunStepStatus, o as AutomationStatus, p as AutomationStep, q as AutomationTrigger, B as BatchSendEmailResult, r as BounceType, C as CategoryOptOut, s as CategoryOptOutCategory, t as CategoryUnsubscribedErrorDetails, u as ConnectTwilioParams, v as ContactWebhookEventPayload, w as CreateApiKeyParams, x as CreateApiKeyResult, y as CreateAutomationParams, z as CreateDomainParams, E as CreateDomainResult, F as CreateMigrationParams, H as CreateSuppressionParams, I as CreateTemplateParams, J as CreateTenantParams, K as CreateWebhookParams, L as DEFAULT_API_BASE_URL, M as DailyRampLimitErrorDetails, N as DeleteTenantResult, O as DeliverabilityBucket, P as DeliverabilityDomainInsight, Q as DeliverabilityInsightsResult, R as DeliverabilityMailServerRelay, T as DeliverabilityWindow, U as DmarcDailyPoint, V as DmarcMonitoring, W as DmarcMonitoringDisabled, X as DmarcReadiness, Y as DmarcReadinessVerdict, Z as DmarcSource, _ as DmarcSourceStatus, $ as DmarcStatus, a0 as DnsProviderName, a1 as Domain, a2 as DomainBimiAnalysis, a3 as DomainDetailResult, a4 as DomainDmarcAnalysis, a5 as DomainDnsAnalysis, a6 as DomainStatus, a7 as DomainTlsMode, a8 as DomainTrackingDns, a9 as DomainTrackingStatus, aa as EmailListItem, ab as EmailWebhookEventPayload, ac as EmailWebhookEventType, ad as EnableDmarcParams, ae as EnableDmarcResult, af as EnrollmentSkip, ag as EventRecord, G as Groundmail, ah as GroundmailAccessToken, ai as GroundmailOptions, aj as GroundmailTokenOptions, ak as GroundmailTokenProvider, al as HeldBackErrorDetails, am as HeldBackReason, an as HeldBackRecipient, ao as ListApiKeysParams, ap as ListApiKeysResult, aq as ListAutomationRunsParams, ar as ListAutomationRunsResult, as as ListAutomationsResult, at as ListCategoryOptOutsParams, au as ListCategoryOptOutsResult, av as ListDomainsParams, aw as ListDomainsResult, ax as ListEmailsParams, ay as ListEmailsResult, az as ListReceivedEmailsParams, aA as ListReceivedEmailsResult, aB as ListSuppressionsParams, aC as ListSuppressionsResult, aD as ListTemplatesParams, aE as ListTemplatesResult, aF as ListTenantDomainsResult, aG as ListTenantsParams, aH as ListTenantsResult, aI as ListTestInboxEmailsParams, aJ as ListTestInboxEmailsResult, aK as MailServerSigningStatus, aL as MailStream, aM as Migration, aN as MigrationDnsChange, aO as MigrationDnsPlan, aP as MigrationDomainItem, aQ as MigrationItemStatus, aR as MigrationProvider, aS as MigrationResource, aT as MigrationSummary, aU as MigrationTemplateItem, aV as MigrationTotals, aW as MigrationWebhookItem, aX as ReceivedEmail, aY as ReceivedEmailAttachment, aZ as ReceivedEmailAttachmentMeta, a_ as RemoteApplyDnsCredentials, a$ as RemoveCategoryOptOutOptions, b0 as RunMigrationOptions, b1 as SendEmailParams, S as SendEmailResult, b2 as StreamDeliverability, b3 as SuppressedErrorDetails, b4 as Suppression, b5 as TEST_INBOX_WAIT_DEFAULT_MS, b6 as TEST_INBOX_WAIT_MAX_SECONDS, b7 as Template, b8 as TemplateFormat, b9 as TemplateLintWarning, ba as TemplateStarter, bb as TemplateStatus, bc as TemplateVersion, bd as Tenant, be as TenantPauseSource, bf as TenantRamp, bg as TenantStats, bh as TenantStatsResult, bi as TenantStatus, bj as TenantStreamPolicy, bk as TestEmailWebhookParams, bl as TestEmailWebhookResult, bm as TestInbox, bn as TestInboxAddressOptions, bo as TestInboxEmail, bp as TestInboxEmailDetail, bq as TestInboxHeader, br as TestInboxResource, bs as TestInboxUsage, bt as TriggerEventParams, bu as TriggerEventResult, bv as TwilioIntegrationResponse, bw as TwilioIntegrationStatus, bx as UpdateAutomationParams, by as UpdateDomainParams, bz as UpdateEmailParams, bA as UpdateTemplateParams, bB as UpdateTenantParams, bC as UpdateWebhookParams, bD as ValidateEmailResult, bE as ValidationReason, bF as ValidationVerdict, bG as VerifyDomainResult, bH as WaitForTestEmailParams, bI as WebhookEmailTag, bJ as WebhookEndpoint, bK as WebhookEndpointWithSecret, bL as WebhookEventType, bM as mergeMigrations, bN as normalizeAccessToken } from './client-
|
|
1
|
+
import { A as ApiErrorBody, D as DnsRecord } from './client-DdtHUMEu.js';
|
|
2
|
+
export { a as ApiErrorCode, b as ApiKey, c as ApiKeyScope, d as ApplyDnsParams, e as ApplyDnsRecordResult, f as ApplyDnsResult, g as Asset, h as Automation, i as AutomationResult, j as AutomationRun, k as AutomationRunResponse, l as AutomationRunStatus, m as AutomationRunStep, n as AutomationRunStepStatus, o as AutomationStatus, p as AutomationStep, q as AutomationTrigger, B as BatchSendEmailResult, r as BounceType, C as CategoryOptOut, s as CategoryOptOutCategory, t as CategoryUnsubscribedErrorDetails, u as ConnectTwilioParams, v as ContactWebhookEventPayload, w as CreateApiKeyParams, x as CreateApiKeyResult, y as CreateAutomationParams, z as CreateDomainParams, E as CreateDomainResult, F as CreateMigrationParams, H as CreateSuppressionParams, I as CreateTemplateParams, J as CreateTenantParams, K as CreateWebhookParams, L as DEFAULT_API_BASE_URL, M as DailyRampLimitErrorDetails, N as DeleteTenantResult, O as DeliverabilityBucket, P as DeliverabilityDomainInsight, Q as DeliverabilityInsightsResult, R as DeliverabilityMailServerRelay, T as DeliverabilityWindow, U as DmarcDailyPoint, V as DmarcMonitoring, W as DmarcMonitoringDisabled, X as DmarcReadiness, Y as DmarcReadinessVerdict, Z as DmarcSource, _ as DmarcSourceStatus, $ as DmarcStatus, a0 as DnsProviderName, a1 as Domain, a2 as DomainBimiAnalysis, a3 as DomainDetailResult, a4 as DomainDmarcAnalysis, a5 as DomainDnsAnalysis, a6 as DomainStatus, a7 as DomainTlsMode, a8 as DomainTrackingDns, a9 as DomainTrackingStatus, aa as EmailListItem, ab as EmailWebhookEventPayload, ac as EmailWebhookEventType, ad as EnableDmarcParams, ae as EnableDmarcResult, af as EnrollmentSkip, ag as EventRecord, G as Groundmail, ah as GroundmailAccessToken, ai as GroundmailOptions, aj as GroundmailTokenOptions, ak as GroundmailTokenProvider, al as HeldBackErrorDetails, am as HeldBackReason, an as HeldBackRecipient, ao as ListApiKeysParams, ap as ListApiKeysResult, aq as ListAutomationRunsParams, ar as ListAutomationRunsResult, as as ListAutomationsResult, at as ListCategoryOptOutsParams, au as ListCategoryOptOutsResult, av as ListDomainsParams, aw as ListDomainsResult, ax as ListEmailsParams, ay as ListEmailsResult, az as ListReceivedEmailsParams, aA as ListReceivedEmailsResult, aB as ListSuppressionsParams, aC as ListSuppressionsResult, aD as ListTemplatesParams, aE as ListTemplatesResult, aF as ListTenantDomainsResult, aG as ListTenantsParams, aH as ListTenantsResult, aI as ListTestInboxEmailsParams, aJ as ListTestInboxEmailsResult, aK as MailServerSigningStatus, aL as MailStream, aM as Migration, aN as MigrationDnsChange, aO as MigrationDnsPlan, aP as MigrationDomainItem, aQ as MigrationItemStatus, aR as MigrationProvider, aS as MigrationResource, aT as MigrationSummary, aU as MigrationTemplateItem, aV as MigrationTotals, aW as MigrationWebhookItem, aX as ReceivedEmail, aY as ReceivedEmailAttachment, aZ as ReceivedEmailAttachmentMeta, a_ as RemoteApplyDnsCredentials, a$ as RemoveCategoryOptOutOptions, b0 as RunMigrationOptions, b1 as SendEmailParams, S as SendEmailResult, b2 as StreamDeliverability, b3 as SuppressedErrorDetails, b4 as Suppression, b5 as TEST_INBOX_WAIT_DEFAULT_MS, b6 as TEST_INBOX_WAIT_MAX_SECONDS, b7 as Template, b8 as TemplateFormat, b9 as TemplateLintWarning, ba as TemplateStarter, bb as TemplateStatus, bc as TemplateVersion, bd as Tenant, be as TenantPauseSource, bf as TenantRamp, bg as TenantStats, bh as TenantStatsResult, bi as TenantStatus, bj as TenantStreamPolicy, bk as TestEmailWebhookParams, bl as TestEmailWebhookResult, bm as TestInbox, bn as TestInboxAddressOptions, bo as TestInboxEmail, bp as TestInboxEmailDetail, bq as TestInboxHeader, br as TestInboxResource, bs as TestInboxUsage, bt as TriggerEventParams, bu as TriggerEventResult, bv as TwilioIntegrationResponse, bw as TwilioIntegrationStatus, bx as UpdateAutomationParams, by as UpdateDomainParams, bz as UpdateEmailParams, bA as UpdateTemplateParams, bB as UpdateTenantParams, bC as UpdateWebhookParams, bD as ValidateEmailResult, bE as ValidationReason, bF as ValidationVerdict, bG as VerifyDomainResult, bH as WaitForTestEmailParams, bI as WebhookEmailTag, bJ as WebhookEndpoint, bK as WebhookEndpointWithSecret, bL as WebhookEventType, bM as mergeMigrations, bN as normalizeAccessToken } from './client-DdtHUMEu.js';
|
|
3
3
|
|
|
4
4
|
type GroundmailErrorOptions = {
|
|
5
5
|
code?: string;
|
|
@@ -80,7 +80,7 @@ declare function isTestApiKey(key: string | null | undefined): boolean;
|
|
|
80
80
|
/** Merge `include:host` into an existing SPF record (or create a minimal one). */
|
|
81
81
|
declare function mergeSpfInclude(existing: string | null | undefined, includeHost: string): string;
|
|
82
82
|
|
|
83
|
-
type DnsProviderName = 'cloudflare' | 'godaddy' | 'vercel';
|
|
83
|
+
type DnsProviderName = 'cloudflare' | 'godaddy' | 'vercel' | 'netlify' | 'digitalocean' | 'dnsimple';
|
|
84
84
|
type ApplyDnsRecordResult = {
|
|
85
85
|
purpose: string;
|
|
86
86
|
host: string;
|
|
@@ -95,10 +95,16 @@ type ApplyDnsResult = {
|
|
|
95
95
|
type ApplyDnsCredentials = {
|
|
96
96
|
cloudflareApiToken?: string;
|
|
97
97
|
cloudflareZoneId?: string;
|
|
98
|
+
/** GoDaddy Personal Access Token (preferred over the key and secret). */
|
|
99
|
+
godaddyApiToken?: string;
|
|
98
100
|
godaddyApiKey?: string;
|
|
99
101
|
godaddyApiSecret?: string;
|
|
100
102
|
vercelApiToken?: string;
|
|
101
103
|
vercelTeamId?: string;
|
|
104
|
+
netlifyApiToken?: string;
|
|
105
|
+
digitaloceanApiToken?: string;
|
|
106
|
+
dnsimpleApiToken?: string;
|
|
107
|
+
dnsimpleAccountId?: string;
|
|
102
108
|
};
|
|
103
109
|
|
|
104
110
|
declare function applyDnsRecords(input: {
|
package/dist/index.js
CHANGED
package/dist/payload.d.ts
CHANGED
package/dist/payload.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groundmail",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Groundmail transactional email API client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"prepublishOnly": "npm run build && npm run build:nodemailer-bridge"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"groundmail-nodemailer": "0.15.
|
|
92
|
+
"groundmail-nodemailer": "0.15.16"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@types/nodemailer": "^8.0.1",
|