domainkit 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +213 -41
- package/dist/Approval.mjs +34 -0
- package/dist/Approval.mjs.map +1 -0
- package/dist/Cleanup.mjs +97 -0
- package/dist/Cleanup.mjs.map +1 -0
- package/dist/Cloudflare.mjs +225 -0
- package/dist/Cloudflare.mjs.map +1 -0
- package/dist/Connect.mjs +463 -0
- package/dist/Connect.mjs.map +1 -0
- package/dist/Custody.mjs +64 -0
- package/dist/Custody.mjs.map +1 -0
- package/dist/DnsRecord.mjs +213 -0
- package/dist/DnsRecord.mjs.map +1 -0
- package/dist/DomainKit.mjs +34 -0
- package/dist/DomainKit.mjs.map +1 -0
- package/dist/DomainName.mjs +100 -0
- package/dist/DomainName.mjs.map +1 -0
- package/dist/Plan.mjs +102 -0
- package/dist/Plan.mjs.map +1 -0
- package/dist/Principal.mjs +23 -0
- package/dist/Principal.mjs.map +1 -0
- package/dist/Provider.mjs +130 -0
- package/dist/Provider.mjs.map +1 -0
- package/dist/Providers.mjs +40 -0
- package/dist/Providers.mjs.map +1 -0
- package/dist/Provision.mjs +93 -0
- package/dist/Provision.mjs.map +1 -0
- package/dist/Reason.mjs +162 -0
- package/dist/Reason.mjs.map +1 -0
- package/dist/Receipt.mjs +71 -0
- package/dist/Receipt.mjs.map +1 -0
- package/dist/Resolver.mjs +75 -0
- package/dist/Resolver.mjs.map +1 -0
- package/dist/Server.mjs +516 -0
- package/dist/Server.mjs.map +1 -0
- package/dist/Storage.mjs +236 -0
- package/dist/Storage.mjs.map +1 -0
- package/dist/Testing.mjs +226 -0
- package/dist/Testing.mjs.map +1 -0
- package/dist/Transport.mjs +187 -0
- package/dist/Transport.mjs.map +1 -0
- package/dist/Vercel.mjs +116 -0
- package/dist/Vercel.mjs.map +1 -0
- package/dist/Verify.mjs +292 -0
- package/dist/Verify.mjs.map +1 -0
- package/dist/{rolldown-runtime-D7D4PA-g.mjs → _virtual/_rolldown/runtime.mjs} +1 -1
- package/dist/entry/client.mjs +2 -0
- package/dist/entry/server.mjs +2 -0
- package/dist/entry/testing.mjs +3 -0
- package/dist/index.mjs +33 -462
- package/dist/index.mjs.map +1 -1
- package/dist/internal/aes.mjs +61 -0
- package/dist/internal/aes.mjs.map +1 -0
- package/dist/internal/attempts.mjs +284 -0
- package/dist/internal/attempts.mjs.map +1 -0
- package/dist/internal/cloudflare/client.mjs +100 -0
- package/dist/internal/cloudflare/client.mjs.map +1 -0
- package/dist/internal/cloudflare/protocol.mjs +59 -0
- package/dist/internal/cloudflare/protocol.mjs.map +1 -0
- package/dist/internal/cloudflare/records.mjs +156 -0
- package/dist/internal/cloudflare/records.mjs.map +1 -0
- package/dist/internal/config.mjs +13 -0
- package/dist/internal/config.mjs.map +1 -0
- package/dist/internal/conformance/provider.mjs +207 -0
- package/dist/internal/conformance/provider.mjs.map +1 -0
- package/dist/internal/conformance/storage.mjs +428 -0
- package/dist/internal/conformance/storage.mjs.map +1 -0
- package/dist/internal/digest.mjs +25 -0
- package/dist/internal/digest.mjs.map +1 -0
- package/dist/internal/doh.mjs +153 -0
- package/dist/internal/doh.mjs.map +1 -0
- package/dist/internal/error.mjs +69 -0
- package/dist/internal/error.mjs.map +1 -0
- package/dist/internal/http.mjs +90 -0
- package/dist/internal/http.mjs.map +1 -0
- package/dist/internal/ids.mjs +8 -0
- package/dist/internal/ids.mjs.map +1 -0
- package/dist/internal/oauth.mjs +113 -0
- package/dist/internal/oauth.mjs.map +1 -0
- package/dist/internal/planner.mjs +88 -0
- package/dist/internal/planner.mjs.map +1 -0
- package/dist/internal/provider-async.mjs +83 -0
- package/dist/internal/provider-async.mjs.map +1 -0
- package/dist/internal/storage-memory.mjs +302 -0
- package/dist/internal/storage-memory.mjs.map +1 -0
- package/dist/internal/vercel/client.mjs +122 -0
- package/dist/internal/vercel/client.mjs.map +1 -0
- package/dist/internal/vercel/protocol.mjs +80 -0
- package/dist/internal/vercel/protocol.mjs.map +1 -0
- package/dist/internal/vercel/records.mjs +151 -0
- package/dist/internal/vercel/records.mjs.map +1 -0
- package/dist/package.mjs +6 -0
- package/dist/package.mjs.map +1 -0
- package/dist/types/Approval.d.ts +26 -0
- package/dist/types/Cleanup.d.ts +41 -0
- package/dist/types/Cloudflare.d.ts +36 -0
- package/dist/types/Connect.d.ts +506 -0
- package/dist/types/Custody.d.ts +38 -0
- package/dist/types/DnsRecord.d.ts +158 -0
- package/dist/types/DomainKit.d.ts +31 -0
- package/dist/types/DomainName.d.ts +27 -0
- package/dist/types/Plan.d.ts +76 -0
- package/dist/types/Principal.d.ts +18 -0
- package/dist/types/Provider.d.ts +248 -0
- package/dist/types/Providers.d.ts +16 -0
- package/dist/types/Provision.d.ts +75 -0
- package/dist/types/Reason.d.ts +118 -0
- package/dist/types/Receipt.d.ts +55 -0
- package/dist/types/Resolver.d.ts +135 -0
- package/dist/types/Server.d.ts +6523 -0
- package/dist/types/Storage.d.ts +314 -0
- package/dist/types/Testing.d.ts +84 -0
- package/dist/types/Transport.d.ts +124 -0
- package/dist/types/Vercel.d.ts +25 -0
- package/dist/types/Verify.d.ts +109 -0
- package/dist/types/entry/client.d.ts +2 -0
- package/dist/types/entry/server.d.ts +2 -0
- package/dist/types/entry/testing.d.ts +3 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/internal/aes.d.ts +8 -0
- package/dist/types/internal/attempts.d.ts +40 -0
- package/dist/types/internal/cloudflare/client.d.ts +23 -0
- package/dist/types/internal/cloudflare/protocol.d.ts +71 -0
- package/dist/types/internal/cloudflare/records.d.ts +8 -0
- package/dist/types/internal/config.d.ts +4 -0
- package/dist/types/internal/conformance/provider.d.ts +12 -0
- package/dist/types/internal/conformance/storage.d.ts +14 -0
- package/dist/types/internal/digest.d.ts +10 -0
- package/dist/types/internal/doh.d.ts +19 -0
- package/dist/types/internal/error.d.ts +24 -0
- package/dist/types/internal/http.d.ts +27 -0
- package/dist/types/internal/ids.d.ts +3 -0
- package/dist/types/internal/oauth.d.ts +58 -0
- package/dist/types/internal/planner.d.ts +22 -0
- package/dist/types/internal/provider-async.d.ts +78 -0
- package/dist/types/internal/storage-memory.d.ts +2 -0
- package/dist/types/internal/vercel/client.d.ts +29 -0
- package/dist/types/internal/vercel/protocol.d.ts +124 -0
- package/dist/types/internal/vercel/records.d.ts +7 -0
- package/package.json +88 -12
- package/dist/canonical-json-CQYKsZw7.mjs +0 -310
- package/dist/canonical-json-CQYKsZw7.mjs.map +0 -1
- package/dist/connect-D-X8T9W8.d.mts +0 -1597
- package/dist/connect-oI8hcMxc.mjs +0 -185
- package/dist/connect-oI8hcMxc.mjs.map +0 -1
- package/dist/connection-Dp6ZdSo8.d.mts +0 -186
- package/dist/connection-api-lqG1nBtD.d.mts +0 -26
- package/dist/index.d.mts +0 -1551
- package/dist/managed-dns-connections-C3A_GBaz.mjs +0 -99
- package/dist/managed-dns-connections-C3A_GBaz.mjs.map +0 -1
- package/dist/promise.d.mts +0 -378
- package/dist/promise.mjs +0 -598
- package/dist/promise.mjs.map +0 -1
- package/dist/resolver-BeGz1ukw.mjs +0 -921
- package/dist/resolver-BeGz1ukw.mjs.map +0 -1
- package/dist/resolver-xoSwyXDJ.d.mts +0 -3734
- package/dist/server.d.mts +0 -128
- package/dist/server.mjs +0 -319
- package/dist/server.mjs.map +0 -1
- package/dist/testing.d.mts +0 -62
- package/dist/testing.mjs +0 -507
- package/dist/testing.mjs.map +0 -1
- package/dist/verify-DvGPb5C9.mjs +0 -2402
- package/dist/verify-DvGPb5C9.mjs.map +0 -1
- package/dist/verify-FpunAcM7.d.mts +0 -1335
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { Model as Model$1, fromStringUnsafe } from "./DomainName.mjs";
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
//#region src/DnsRecord.ts
|
|
5
|
+
/**
|
|
6
|
+
* DNS record requirements a product asks a customer to satisfy, and the observed records a
|
|
7
|
+
* provider or resolver reports back.
|
|
8
|
+
*
|
|
9
|
+
* Constructors are lowercase functions (`DnsRecord.cname(...)`), Effect style. `policy` defaults
|
|
10
|
+
* to `exclusive` for CNAME and `append` for everything else; `ttl` defaults to `null` (provider
|
|
11
|
+
* default); `purpose` is an optional human label the UI shows.
|
|
12
|
+
*/
|
|
13
|
+
var DnsRecord_exports = /* @__PURE__ */ __exportAll({
|
|
14
|
+
A: () => A,
|
|
15
|
+
AAAA: () => AAAA,
|
|
16
|
+
CAA: () => CAA,
|
|
17
|
+
CNAME: () => CNAME,
|
|
18
|
+
MX: () => MX,
|
|
19
|
+
Model: () => Model,
|
|
20
|
+
NS: () => NS,
|
|
21
|
+
Observed: () => Observed,
|
|
22
|
+
Opaque: () => Opaque,
|
|
23
|
+
Policy: () => Policy,
|
|
24
|
+
SRV: () => SRV,
|
|
25
|
+
TXT: () => TXT,
|
|
26
|
+
Type: () => Type,
|
|
27
|
+
a: () => a,
|
|
28
|
+
aaaa: () => aaaa,
|
|
29
|
+
caa: () => caa,
|
|
30
|
+
cname: () => cname,
|
|
31
|
+
data: () => data,
|
|
32
|
+
equals: () => equals,
|
|
33
|
+
isDnsRecord: () => isDnsRecord,
|
|
34
|
+
mx: () => mx,
|
|
35
|
+
ns: () => ns,
|
|
36
|
+
sameSet: () => sameSet,
|
|
37
|
+
srv: () => srv,
|
|
38
|
+
txt: () => txt
|
|
39
|
+
});
|
|
40
|
+
const Name = Schema.suspend(() => Model$1);
|
|
41
|
+
const Type = Schema.Literals([
|
|
42
|
+
"A",
|
|
43
|
+
"AAAA",
|
|
44
|
+
"CNAME",
|
|
45
|
+
"TXT",
|
|
46
|
+
"MX",
|
|
47
|
+
"CAA",
|
|
48
|
+
"NS",
|
|
49
|
+
"SRV"
|
|
50
|
+
]);
|
|
51
|
+
const Policy = Schema.Literals(["exclusive", "append"]);
|
|
52
|
+
const Ttl = Schema.NullOr(Schema.Int.check(Schema.isBetween({
|
|
53
|
+
minimum: 1,
|
|
54
|
+
maximum: 2147483647
|
|
55
|
+
})));
|
|
56
|
+
const Port = Schema.Int.check(Schema.isBetween({
|
|
57
|
+
minimum: 0,
|
|
58
|
+
maximum: 65535
|
|
59
|
+
}));
|
|
60
|
+
const Priority = Schema.Int.check(Schema.isBetween({
|
|
61
|
+
minimum: 0,
|
|
62
|
+
maximum: 65535
|
|
63
|
+
}));
|
|
64
|
+
const Ipv4 = Schema.String.check(Schema.makeFilter((value) => isIpv4(value) ? void 0 : "Expected an IPv4 address"));
|
|
65
|
+
const Ipv6 = Schema.String.check(Schema.makeFilter((value) => isIpv6(value) ? void 0 : "Expected an IPv6 address"));
|
|
66
|
+
const NonEmpty = Schema.String.check(Schema.isMinLength(1));
|
|
67
|
+
const Common = {
|
|
68
|
+
name: Name,
|
|
69
|
+
ttl: Ttl,
|
|
70
|
+
policy: Policy,
|
|
71
|
+
purpose: Schema.optionalKey(Schema.String)
|
|
72
|
+
};
|
|
73
|
+
var A = class extends Schema.TaggedClass("@domainkit/DnsRecord/A")("A", {
|
|
74
|
+
...Common,
|
|
75
|
+
address: Ipv4
|
|
76
|
+
}) {};
|
|
77
|
+
var AAAA = class extends Schema.TaggedClass("@domainkit/DnsRecord/AAAA")("AAAA", {
|
|
78
|
+
...Common,
|
|
79
|
+
address: Ipv6
|
|
80
|
+
}) {};
|
|
81
|
+
var CNAME = class extends Schema.TaggedClass("@domainkit/DnsRecord/CNAME")("CNAME", {
|
|
82
|
+
...Common,
|
|
83
|
+
target: Name
|
|
84
|
+
}) {};
|
|
85
|
+
var TXT = class extends Schema.TaggedClass("@domainkit/DnsRecord/TXT")("TXT", {
|
|
86
|
+
...Common,
|
|
87
|
+
value: NonEmpty
|
|
88
|
+
}) {};
|
|
89
|
+
var MX = class extends Schema.TaggedClass("@domainkit/DnsRecord/MX")("MX", {
|
|
90
|
+
...Common,
|
|
91
|
+
exchange: Name,
|
|
92
|
+
priority: Priority
|
|
93
|
+
}) {};
|
|
94
|
+
var CAA = class extends Schema.TaggedClass("@domainkit/DnsRecord/CAA")("CAA", {
|
|
95
|
+
...Common,
|
|
96
|
+
flags: Schema.Int.check(Schema.isBetween({
|
|
97
|
+
minimum: 0,
|
|
98
|
+
maximum: 255
|
|
99
|
+
})),
|
|
100
|
+
tag: NonEmpty,
|
|
101
|
+
value: NonEmpty
|
|
102
|
+
}) {};
|
|
103
|
+
var NS = class extends Schema.TaggedClass("@domainkit/DnsRecord/NS")("NS", {
|
|
104
|
+
...Common,
|
|
105
|
+
nameserver: Name
|
|
106
|
+
}) {};
|
|
107
|
+
var SRV = class extends Schema.TaggedClass("@domainkit/DnsRecord/SRV")("SRV", {
|
|
108
|
+
...Common,
|
|
109
|
+
target: Name,
|
|
110
|
+
port: Port,
|
|
111
|
+
priority: Priority,
|
|
112
|
+
weight: Priority
|
|
113
|
+
}) {};
|
|
114
|
+
const Model = Schema.Union([
|
|
115
|
+
A,
|
|
116
|
+
AAAA,
|
|
117
|
+
CNAME,
|
|
118
|
+
TXT,
|
|
119
|
+
MX,
|
|
120
|
+
CAA,
|
|
121
|
+
NS,
|
|
122
|
+
SRV
|
|
123
|
+
]);
|
|
124
|
+
/** A provider record DomainKit cannot model but must not overwrite. */
|
|
125
|
+
var Opaque = class extends Schema.TaggedClass("@domainkit/DnsRecord/Opaque")("Opaque", {
|
|
126
|
+
name: Schema.String,
|
|
127
|
+
type: Schema.String,
|
|
128
|
+
raw: Schema.Unknown
|
|
129
|
+
}) {};
|
|
130
|
+
const Observed = Schema.Union([Model, Opaque]);
|
|
131
|
+
const common = (name, options, defaultPolicy) => ({
|
|
132
|
+
name: fromStringUnsafe(name),
|
|
133
|
+
ttl: options.ttl ?? null,
|
|
134
|
+
policy: options.policy ?? defaultPolicy,
|
|
135
|
+
...options.purpose === void 0 ? {} : { purpose: options.purpose }
|
|
136
|
+
});
|
|
137
|
+
const a = (input) => new A({
|
|
138
|
+
...common(input.name, input, "append"),
|
|
139
|
+
address: input.address
|
|
140
|
+
});
|
|
141
|
+
const aaaa = (input) => new AAAA({
|
|
142
|
+
...common(input.name, input, "append"),
|
|
143
|
+
address: input.address
|
|
144
|
+
});
|
|
145
|
+
const cname = (input) => new CNAME({
|
|
146
|
+
...common(input.name, input, "exclusive"),
|
|
147
|
+
target: fromStringUnsafe(input.target)
|
|
148
|
+
});
|
|
149
|
+
const txt = (input) => new TXT({
|
|
150
|
+
...common(input.name, input, "append"),
|
|
151
|
+
value: input.value
|
|
152
|
+
});
|
|
153
|
+
const mx = (input) => new MX({
|
|
154
|
+
...common(input.name, input, "append"),
|
|
155
|
+
exchange: fromStringUnsafe(input.exchange),
|
|
156
|
+
priority: input.priority
|
|
157
|
+
});
|
|
158
|
+
const caa = (input) => new CAA({
|
|
159
|
+
...common(input.name, input, "append"),
|
|
160
|
+
flags: input.flags,
|
|
161
|
+
tag: input.tag,
|
|
162
|
+
value: input.value
|
|
163
|
+
});
|
|
164
|
+
const ns = (input) => new NS({
|
|
165
|
+
...common(input.name, input, "append"),
|
|
166
|
+
nameserver: fromStringUnsafe(input.nameserver)
|
|
167
|
+
});
|
|
168
|
+
const srv = (input) => new SRV({
|
|
169
|
+
...common(input.name, input, "append"),
|
|
170
|
+
target: fromStringUnsafe(input.target),
|
|
171
|
+
port: input.port,
|
|
172
|
+
priority: input.priority,
|
|
173
|
+
weight: input.weight
|
|
174
|
+
});
|
|
175
|
+
const isDnsRecord = (input) => Schema.is(Model)(input);
|
|
176
|
+
/** The record's data portion as a canonical string, for display and zone-file rendering. */
|
|
177
|
+
const data = (record) => {
|
|
178
|
+
switch (record._tag) {
|
|
179
|
+
case "A":
|
|
180
|
+
case "AAAA": return record.address;
|
|
181
|
+
case "CNAME": return record.target;
|
|
182
|
+
case "NS": return record.nameserver;
|
|
183
|
+
case "TXT": return record.value;
|
|
184
|
+
case "MX": return `${record.priority} ${record.exchange}`;
|
|
185
|
+
case "CAA": return `${record.flags} ${record.tag} ${record.value}`;
|
|
186
|
+
case "SRV": return `${record.priority} ${record.weight} ${record.port} ${record.target}`;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Structural equality over type, name, and data. `ttl`, `policy`, and `purpose` are requirement
|
|
191
|
+
* metadata, not record identity, so they are ignored; TTL drift is reported on plan operations.
|
|
192
|
+
*/
|
|
193
|
+
const equals = (left, right) => {
|
|
194
|
+
if (left._tag === "Opaque" || right._tag === "Opaque") return left._tag === "Opaque" && right._tag === "Opaque" && left.name === right.name && left.type === right.type && JSON.stringify(left.raw) === JSON.stringify(right.raw);
|
|
195
|
+
return left._tag === right._tag && left.name === right.name && data(left) === data(right);
|
|
196
|
+
};
|
|
197
|
+
/** `true` when both records occupy the same name and type, regardless of data. */
|
|
198
|
+
const sameSet = (left, right) => left.name === right.name && (left._tag === "Opaque" ? left.type : left._tag) === (right._tag === "Opaque" ? right.type : right._tag);
|
|
199
|
+
function isIpv4(value) {
|
|
200
|
+
const parts = value.split(".");
|
|
201
|
+
return parts.length === 4 && parts.every((part) => /^\d{1,3}$/.test(part) && Number(part) <= 255 && String(Number(part)) === part);
|
|
202
|
+
}
|
|
203
|
+
function isIpv6(value) {
|
|
204
|
+
try {
|
|
205
|
+
return new URL(`http://[${value}]/`).hostname.startsWith("[");
|
|
206
|
+
} catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//#endregion
|
|
211
|
+
export { A, AAAA, CAA, CNAME, DnsRecord_exports, MX, Model, NS, Observed, Opaque, Policy, SRV, TXT, Type, a, aaaa, caa, cname, data, equals, isDnsRecord, mx, ns, sameSet, srv, txt };
|
|
212
|
+
|
|
213
|
+
//# sourceMappingURL=DnsRecord.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DnsRecord.mjs","names":["DomainName.Model","DomainName.fromStringUnsafe"],"sources":["../src/DnsRecord.ts"],"sourcesContent":["/**\n * DNS record requirements a product asks a customer to satisfy, and the observed records a\n * provider or resolver reports back.\n *\n * Constructors are lowercase functions (`DnsRecord.cname(...)`), Effect style. `policy` defaults\n * to `exclusive` for CNAME and `append` for everything else; `ttl` defaults to `null` (provider\n * default); `purpose` is an optional human label the UI shows.\n */\nimport { Schema } from \"effect\";\n\nimport * as DomainName from \"./DomainName.ts\";\n\n// DomainName, internal/error, Reason, Plan, and DnsRecord form an import cycle. Field schemas\n// that cross it are read lazily so any module can be the first one evaluated.\nconst Name = Schema.suspend(() => DomainName.Model);\n\nexport const Type = Schema.Literals([\"A\", \"AAAA\", \"CNAME\", \"TXT\", \"MX\", \"CAA\", \"NS\", \"SRV\"]);\nexport type Type = typeof Type.Type;\n\nexport const Policy = Schema.Literals([\"exclusive\", \"append\"]);\nexport type Policy = typeof Policy.Type;\n\nconst Ttl = Schema.NullOr(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 2_147_483_647 })),\n);\nconst Port = Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 65_535 }));\nconst Priority = Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 65_535 }));\nconst Ipv4 = Schema.String.check(\n Schema.makeFilter<string>((value) => (isIpv4(value) ? undefined : \"Expected an IPv4 address\")),\n);\nconst Ipv6 = Schema.String.check(\n Schema.makeFilter<string>((value) => (isIpv6(value) ? undefined : \"Expected an IPv6 address\")),\n);\nconst NonEmpty = Schema.String.check(Schema.isMinLength(1));\n\nconst Common = {\n name: Name,\n ttl: Ttl,\n policy: Policy,\n purpose: Schema.optionalKey(Schema.String),\n};\n\nexport class A extends Schema.TaggedClass<A>(\"@domainkit/DnsRecord/A\")(\"A\", {\n ...Common,\n address: Ipv4,\n}) {}\nexport class AAAA extends Schema.TaggedClass<AAAA>(\"@domainkit/DnsRecord/AAAA\")(\"AAAA\", {\n ...Common,\n address: Ipv6,\n}) {}\nexport class CNAME extends Schema.TaggedClass<CNAME>(\"@domainkit/DnsRecord/CNAME\")(\"CNAME\", {\n ...Common,\n target: Name,\n}) {}\nexport class TXT extends Schema.TaggedClass<TXT>(\"@domainkit/DnsRecord/TXT\")(\"TXT\", {\n ...Common,\n value: NonEmpty,\n}) {}\nexport class MX extends Schema.TaggedClass<MX>(\"@domainkit/DnsRecord/MX\")(\"MX\", {\n ...Common,\n exchange: Name,\n priority: Priority,\n}) {}\nexport class CAA extends Schema.TaggedClass<CAA>(\"@domainkit/DnsRecord/CAA\")(\"CAA\", {\n ...Common,\n flags: Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 255 })),\n tag: NonEmpty,\n value: NonEmpty,\n}) {}\nexport class NS extends Schema.TaggedClass<NS>(\"@domainkit/DnsRecord/NS\")(\"NS\", {\n ...Common,\n nameserver: Name,\n}) {}\nexport class SRV extends Schema.TaggedClass<SRV>(\"@domainkit/DnsRecord/SRV\")(\"SRV\", {\n ...Common,\n target: Name,\n port: Port,\n priority: Priority,\n weight: Priority,\n}) {}\n\nexport const Model = Schema.Union([A, AAAA, CNAME, TXT, MX, CAA, NS, SRV]);\nexport type Model = typeof Model.Type;\nexport type Encoded = typeof Model.Encoded;\n\n/** A provider record DomainKit cannot model but must not overwrite. */\nexport class Opaque extends Schema.TaggedClass<Opaque>(\"@domainkit/DnsRecord/Opaque\")(\"Opaque\", {\n name: Schema.String,\n type: Schema.String,\n raw: Schema.Unknown,\n}) {}\nexport const Observed = Schema.Union([Model, Opaque]);\nexport type Observed = typeof Observed.Type;\n\ntype Options = { readonly ttl?: number; readonly policy?: Policy; readonly purpose?: string };\n\nconst common = (name: string, options: Options, defaultPolicy: Policy) => ({\n name: DomainName.fromStringUnsafe(name),\n ttl: options.ttl ?? null,\n policy: options.policy ?? defaultPolicy,\n ...(options.purpose === undefined ? {} : { purpose: options.purpose }),\n});\n\nexport const a = (input: { readonly name: string; readonly address: string } & Options): A =>\n new A({ ...common(input.name, input, \"append\"), address: input.address });\nexport const aaaa = (input: { readonly name: string; readonly address: string } & Options): AAAA =>\n new AAAA({ ...common(input.name, input, \"append\"), address: input.address });\nexport const cname = (\n input: { readonly name: string; readonly target: string } & Omit<Options, \"policy\">,\n): CNAME =>\n new CNAME({\n ...common(input.name, input, \"exclusive\"),\n target: DomainName.fromStringUnsafe(input.target),\n });\nexport const txt = (input: { readonly name: string; readonly value: string } & Options): TXT =>\n new TXT({ ...common(input.name, input, \"append\"), value: input.value });\nexport const mx = (\n input: { readonly name: string; readonly exchange: string; readonly priority: number } & Options,\n): MX =>\n new MX({\n ...common(input.name, input, \"append\"),\n exchange: DomainName.fromStringUnsafe(input.exchange),\n priority: input.priority,\n });\nexport const caa = (\n input: {\n readonly name: string;\n readonly flags: number;\n readonly tag: string;\n readonly value: string;\n } & Options,\n): CAA =>\n new CAA({\n ...common(input.name, input, \"append\"),\n flags: input.flags,\n tag: input.tag,\n value: input.value,\n });\nexport const ns = (input: { readonly name: string; readonly nameserver: string } & Options): NS =>\n new NS({\n ...common(input.name, input, \"append\"),\n nameserver: DomainName.fromStringUnsafe(input.nameserver),\n });\nexport const srv = (\n input: {\n readonly name: string;\n readonly target: string;\n readonly port: number;\n readonly priority: number;\n readonly weight: number;\n } & Options,\n): SRV =>\n new SRV({\n ...common(input.name, input, \"append\"),\n target: DomainName.fromStringUnsafe(input.target),\n port: input.port,\n priority: input.priority,\n weight: input.weight,\n });\n\nexport const isDnsRecord = (input: unknown): input is Model => Schema.is(Model)(input);\n\n/** The record's data portion as a canonical string, for display and zone-file rendering. */\nexport const data = (record: Model): string => {\n switch (record._tag) {\n case \"A\":\n case \"AAAA\":\n return record.address;\n case \"CNAME\":\n return record.target;\n case \"NS\":\n return record.nameserver;\n case \"TXT\":\n return record.value;\n case \"MX\":\n return `${record.priority} ${record.exchange}`;\n case \"CAA\":\n return `${record.flags} ${record.tag} ${record.value}`;\n case \"SRV\":\n return `${record.priority} ${record.weight} ${record.port} ${record.target}`;\n }\n};\n\n/**\n * Structural equality over type, name, and data. `ttl`, `policy`, and `purpose` are requirement\n * metadata, not record identity, so they are ignored; TTL drift is reported on plan operations.\n */\nexport const equals = (left: Observed, right: Observed): boolean => {\n if (left._tag === \"Opaque\" || right._tag === \"Opaque\") {\n return (\n left._tag === \"Opaque\" &&\n right._tag === \"Opaque\" &&\n left.name === right.name &&\n left.type === right.type &&\n JSON.stringify(left.raw) === JSON.stringify(right.raw)\n );\n }\n return left._tag === right._tag && left.name === right.name && data(left) === data(right);\n};\n\n/** `true` when both records occupy the same name and type, regardless of data. */\nexport const sameSet = (left: Observed, right: Observed): boolean =>\n left.name === right.name &&\n (left._tag === \"Opaque\" ? left.type : left._tag) ===\n (right._tag === \"Opaque\" ? right.type : right._tag);\n\nfunction isIpv4(value: string): boolean {\n const parts = value.split(\".\");\n return (\n parts.length === 4 &&\n parts.every(\n (part) => /^\\d{1,3}$/.test(part) && Number(part) <= 255 && String(Number(part)) === part,\n )\n );\n}\n\nfunction isIpv6(value: string): boolean {\n try {\n return new URL(`http://[${value}]/`).hostname.startsWith(\"[\");\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { DomainKitError } from "./internal/error.mjs";
|
|
3
|
+
import { generateKey, layer as layer$1 } from "./Custody.mjs";
|
|
4
|
+
import { layer as layer$2 } from "./Providers.mjs";
|
|
5
|
+
import { layer as layer$3 } from "./Resolver.mjs";
|
|
6
|
+
import { layerMemory as layerMemory$1 } from "./Storage.mjs";
|
|
7
|
+
import { layer as layer$4 } from "./Connect.mjs";
|
|
8
|
+
import { layer as layer$5 } from "./Provision.mjs";
|
|
9
|
+
import { layer as layer$6 } from "./Cleanup.mjs";
|
|
10
|
+
import { layer as layer$7 } from "./Verify.mjs";
|
|
11
|
+
import { Layer, Redacted } from "effect";
|
|
12
|
+
//#region src/DomainKit.ts
|
|
13
|
+
/**
|
|
14
|
+
* The composed layer. Provides every lifecycle service given a list of providers; the host
|
|
15
|
+
* provides `Storage` and `Custody` beneath it, the same way `Persistence.layer` sits over a
|
|
16
|
+
* backing store in Effect.
|
|
17
|
+
*
|
|
18
|
+
* Defaults: `Resolver.layer` (Cloudflare + Google DoH) and the `Policy` references. Override a
|
|
19
|
+
* policy with `Effect.provideService`; pass `resolver` for a different pool.
|
|
20
|
+
*/
|
|
21
|
+
var DomainKit_exports = /* @__PURE__ */ __exportAll({
|
|
22
|
+
Error: () => DomainKitError,
|
|
23
|
+
isError: () => isError,
|
|
24
|
+
layer: () => layer,
|
|
25
|
+
layerMemory: () => layerMemory
|
|
26
|
+
});
|
|
27
|
+
const isError = (input) => input instanceof DomainKitError;
|
|
28
|
+
const layer = (options) => Layer.mergeAll(layer$5, layer$6, layer$7).pipe(Layer.provideMerge(layer$4), Layer.provideMerge(Layer.mergeAll(layer$2(options.providers), options.resolver ?? layer$3)));
|
|
29
|
+
/** `layer` with `Storage.layerMemory` and a throwaway custody key. Tests and playgrounds only. */
|
|
30
|
+
const layerMemory = (options) => layer(options).pipe(Layer.provideMerge(Layer.mergeAll(layerMemory$1, layer$1({ key: Redacted.make(generateKey()) }))));
|
|
31
|
+
//#endregion
|
|
32
|
+
export { DomainKit_exports, DomainKitError as Error, isError, layer, layerMemory };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=DomainKit.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DomainKit.mjs","names":["Provision.layer","Cleanup.layer","Verify.layer","Connect.layer","Providers.layer","Resolver.layer","Storage.layerMemory","Custody.layer","Custody.generateKey"],"sources":["../src/DomainKit.ts"],"sourcesContent":["/**\n * The composed layer. Provides every lifecycle service given a list of providers; the host\n * provides `Storage` and `Custody` beneath it, the same way `Persistence.layer` sits over a\n * backing store in Effect.\n *\n * Defaults: `Resolver.layer` (Cloudflare + Google DoH) and the `Policy` references. Override a\n * policy with `Effect.provideService`; pass `resolver` for a different pool.\n */\nimport { Layer, Redacted } from \"effect\";\n\nimport * as Cleanup from \"./Cleanup.ts\";\nimport * as Connect from \"./Connect.ts\";\nimport * as Custody from \"./Custody.ts\";\nimport { DomainKitError } from \"./internal/error.ts\";\nimport type * as Provider from \"./Provider.ts\";\nimport * as Providers from \"./Providers.ts\";\nimport * as Provision from \"./Provision.ts\";\nimport * as Resolver from \"./Resolver.ts\";\nimport * as Storage from \"./Storage.ts\";\nimport * as Verify from \"./Verify.ts\";\n\nexport { DomainKitError as Error };\nexport type { Category as ErrorCategory } from \"./internal/error.ts\";\n\nexport const isError = (input: unknown): input is DomainKitError => input instanceof DomainKitError;\n\nexport interface Options {\n readonly providers: ReadonlyArray<Provider.Definition>;\n /** Replace the public DNS pool (e.g. `Testing.resolver()`); default `Resolver.layer`. */\n readonly resolver?: Layer.Layer<Resolver.Service>;\n}\n\nexport type Services =\n | Provision.Service\n | Cleanup.Service\n | Connect.Service\n | Verify.Service\n | Providers.Service\n | Resolver.Service;\n\nexport const layer = (\n options: Options,\n): Layer.Layer<Services, never, Storage.Service | Custody.Service> =>\n Layer.mergeAll(Provision.layer, Cleanup.layer, Verify.layer).pipe(\n Layer.provideMerge(Connect.layer),\n Layer.provideMerge(\n Layer.mergeAll(Providers.layer(options.providers), options.resolver ?? Resolver.layer),\n ),\n );\n\n/** `layer` with `Storage.layerMemory` and a throwaway custody key. Tests and playgrounds only. */\nexport const layerMemory = (\n options: Options,\n): Layer.Layer<Services | Storage.Service | Custody.Service, DomainKitError> =>\n layer(options).pipe(\n Layer.provideMerge(\n Layer.mergeAll(\n Storage.layerMemory,\n Custody.layer({ key: Redacted.make(Custody.generateKey()) }),\n ),\n ),\n );\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,WAAW,UAA4C,iBAAiB;AAgBrF,MAAa,SACX,YAEA,MAAM,SAASA,SAAiBC,SAAeC,OAAY,CAAC,CAAC,KAC3D,MAAM,aAAaC,OAAa,GAChC,MAAM,aACJ,MAAM,SAASC,QAAgB,QAAQ,SAAS,GAAG,QAAQ,YAAYC,OAAc,CACvF,CACF;;AAGF,MAAa,eACX,YAEA,MAAM,OAAO,CAAC,CAAC,KACb,MAAM,aACJ,MAAM,SACJC,eACAC,QAAc,EAAE,KAAK,SAAS,KAAKC,YAAoB,CAAC,EAAE,CAAC,CAC7D,CACF,CACF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { InvalidInput } from "./Reason.mjs";
|
|
3
|
+
import { DomainKitError, fail } from "./internal/error.mjs";
|
|
4
|
+
import { Effect, Option, Schema, SchemaIssue, SchemaTransformation } from "effect";
|
|
5
|
+
import { getDomain } from "tldts";
|
|
6
|
+
//#region src/DomainName.ts
|
|
7
|
+
/**
|
|
8
|
+
* A normalized, IDN-aware hostname. Lifecycle inputs accept plain strings and validate them, so
|
|
9
|
+
* most hosts never construct this directly; it exists for hosts that want the brand in their own
|
|
10
|
+
* types.
|
|
11
|
+
*/
|
|
12
|
+
var DomainName_exports = /* @__PURE__ */ __exportAll({
|
|
13
|
+
Model: () => Model,
|
|
14
|
+
candidates: () => candidates,
|
|
15
|
+
decode: () => decode,
|
|
16
|
+
fromString: () => fromString,
|
|
17
|
+
fromStringUnsafe: () => fromStringUnsafe,
|
|
18
|
+
isDomainName: () => isDomainName,
|
|
19
|
+
isWithin: () => isWithin
|
|
20
|
+
});
|
|
21
|
+
const labelPattern = /^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/;
|
|
22
|
+
const Branded = Schema.String.check(Schema.makeFilter((value) => isNormalized(value) ? void 0 : "Expected a fully qualified DNS name", { identifier: "DomainName" })).pipe(Schema.brand("@domainkit/DomainName"));
|
|
23
|
+
/** Decodes any hostname spelling into its normalized, branded form; encodes back to a string. */
|
|
24
|
+
const Model = Schema.String.pipe(Schema.decodeTo(Branded, SchemaTransformation.transformOrFail({
|
|
25
|
+
decode: (input, options) => Effect.try({
|
|
26
|
+
try: () => normalize(input),
|
|
27
|
+
catch: (cause) => new SchemaIssue.InvalidValue({ message: errorMessage(cause) }, input, options)
|
|
28
|
+
}),
|
|
29
|
+
encode: (domain) => Effect.succeed(domain)
|
|
30
|
+
})));
|
|
31
|
+
/** Validates and normalizes; `None` when the input is not a hostname. */
|
|
32
|
+
const fromString = (input) => {
|
|
33
|
+
try {
|
|
34
|
+
return Option.some(normalizeUnsafe(input));
|
|
35
|
+
} catch {
|
|
36
|
+
return Option.none();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
/** Validates and normalizes; throws `DomainKit.Error` (reason `InvalidInput`) when invalid. */
|
|
40
|
+
const fromStringUnsafe = (input) => {
|
|
41
|
+
try {
|
|
42
|
+
return normalizeUnsafe(input);
|
|
43
|
+
} catch (cause) {
|
|
44
|
+
throw new DomainKitError({ reason: new InvalidInput({
|
|
45
|
+
message: errorMessage(cause),
|
|
46
|
+
field: "domain"
|
|
47
|
+
}) });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/** Validates and normalizes inside Effect; fails with reason `InvalidInput`. */
|
|
51
|
+
const decode = (input, field = "domain") => Effect.suspend(() => {
|
|
52
|
+
try {
|
|
53
|
+
return Effect.succeed(normalizeUnsafe(input));
|
|
54
|
+
} catch (cause) {
|
|
55
|
+
return fail(new InvalidInput({
|
|
56
|
+
message: errorMessage(cause),
|
|
57
|
+
field
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const isDomainName = (input) => typeof input === "string" && isNormalized(input);
|
|
62
|
+
/**
|
|
63
|
+
* Zone candidates from the name itself down to the registrable domain, most specific first:
|
|
64
|
+
* `a.b.example.com` -> `a.b.example.com`, `b.example.com`, `example.com`. Empty when the name has
|
|
65
|
+
* no registrable suffix.
|
|
66
|
+
*/
|
|
67
|
+
const candidates = (domain) => {
|
|
68
|
+
const registrable = getDomain(domain, { allowPrivateDomains: true });
|
|
69
|
+
if (registrable === null) return [];
|
|
70
|
+
const labels = domain.split(".");
|
|
71
|
+
const registrableLabels = registrable.split(".").length;
|
|
72
|
+
const values = [];
|
|
73
|
+
for (let index = 0; index <= labels.length - registrableLabels; index += 1) values.push(labels.slice(index).join("."));
|
|
74
|
+
return values;
|
|
75
|
+
};
|
|
76
|
+
/** `true` when `name` is `zone` or a subdomain of it. */
|
|
77
|
+
const isWithin = (name, zone) => name === zone || name.endsWith(`.${zone}`);
|
|
78
|
+
function isNormalized(value) {
|
|
79
|
+
return value.length <= 253 && value.includes(".") && value.split(".").every((label) => labelPattern.test(label));
|
|
80
|
+
}
|
|
81
|
+
function normalizeUnsafe(input) {
|
|
82
|
+
return normalize(input);
|
|
83
|
+
}
|
|
84
|
+
function normalize(input) {
|
|
85
|
+
const value = input.trim().replace(/\.+$/, "").split(".").map((label) => {
|
|
86
|
+
if (label.includes("_") || [...label].every((character) => character.charCodeAt(0) <= 127)) return label.toLowerCase();
|
|
87
|
+
const normalized = new URL(`http://${label}.example`).hostname.split(".")[0];
|
|
88
|
+
if (normalized === void 0) throw new Error("Domain label could not be normalized");
|
|
89
|
+
return normalized.toLowerCase();
|
|
90
|
+
}).join(".");
|
|
91
|
+
if (!isNormalized(value)) throw new Error(`Expected a fully qualified DNS name, received ${JSON.stringify(input)}`);
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
function errorMessage(cause) {
|
|
95
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { DomainName_exports, Model, candidates, decode, fromString, fromStringUnsafe, isDomainName, isWithin };
|
|
99
|
+
|
|
100
|
+
//# sourceMappingURL=DomainName.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DomainName.mjs","names":["Errors.DomainKitError","Reason.InvalidInput","Errors.fail"],"sources":["../src/DomainName.ts"],"sourcesContent":["/**\n * A normalized, IDN-aware hostname. Lifecycle inputs accept plain strings and validate them, so\n * most hosts never construct this directly; it exists for hosts that want the brand in their own\n * types.\n */\nimport { Effect, Option, Schema, SchemaIssue, SchemaTransformation } from \"effect\";\nimport { getDomain } from \"tldts\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\n\nconst labelPattern = /^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/;\n\nconst Branded = Schema.String.check(\n Schema.makeFilter<string>(\n (value) => (isNormalized(value) ? undefined : \"Expected a fully qualified DNS name\"),\n { identifier: \"DomainName\" },\n ),\n).pipe(Schema.brand(\"@domainkit/DomainName\"));\n\n/** Decodes any hostname spelling into its normalized, branded form; encodes back to a string. */\nexport const Model = Schema.String.pipe(\n Schema.decodeTo(\n Branded,\n SchemaTransformation.transformOrFail({\n decode: (input, options) =>\n Effect.try({\n try: () => normalize(input),\n catch: (cause) =>\n new SchemaIssue.InvalidValue({ message: errorMessage(cause) }, input, options),\n }),\n encode: (domain) => Effect.succeed(domain),\n }),\n ),\n);\nexport type Model = typeof Branded.Type;\n\n/** Validates and normalizes; `None` when the input is not a hostname. */\nexport const fromString = (input: string): Option.Option<Model> => {\n try {\n return Option.some(normalizeUnsafe(input));\n } catch {\n return Option.none();\n }\n};\n\n/** Validates and normalizes; throws `DomainKit.Error` (reason `InvalidInput`) when invalid. */\nexport const fromStringUnsafe = (input: string): Model => {\n try {\n return normalizeUnsafe(input);\n } catch (cause) {\n throw new Errors.DomainKitError({\n reason: new Reason.InvalidInput({ message: errorMessage(cause), field: \"domain\" }),\n });\n }\n};\n\n/** Validates and normalizes inside Effect; fails with reason `InvalidInput`. */\nexport const decode = (\n input: string,\n field = \"domain\",\n): Effect.Effect<Model, Errors.DomainKitError> =>\n Effect.suspend(() => {\n try {\n return Effect.succeed(normalizeUnsafe(input));\n } catch (cause) {\n return Errors.fail(new Reason.InvalidInput({ message: errorMessage(cause), field }));\n }\n });\n\nexport const isDomainName = (input: unknown): input is Model =>\n typeof input === \"string\" && isNormalized(input);\n\n/**\n * Zone candidates from the name itself down to the registrable domain, most specific first:\n * `a.b.example.com` -> `a.b.example.com`, `b.example.com`, `example.com`. Empty when the name has\n * no registrable suffix.\n */\nexport const candidates = (domain: Model): ReadonlyArray<Model> => {\n const registrable = getDomain(domain, { allowPrivateDomains: true });\n if (registrable === null) return [];\n const labels = domain.split(\".\");\n const registrableLabels = registrable.split(\".\").length;\n const values: Array<Model> = [];\n for (let index = 0; index <= labels.length - registrableLabels; index += 1) {\n values.push(labels.slice(index).join(\".\") as Model);\n }\n return values;\n};\n\n/** `true` when `name` is `zone` or a subdomain of it. */\nexport const isWithin = (name: string, zone: string): boolean =>\n name === zone || name.endsWith(`.${zone}`);\n\nfunction isNormalized(value: string): boolean {\n return (\n value.length <= 253 &&\n value.includes(\".\") &&\n value.split(\".\").every((label) => labelPattern.test(label))\n );\n}\n\nfunction normalizeUnsafe(input: string): Model {\n return normalize(input) as Model;\n}\n\nfunction normalize(input: string): string {\n const labels = input\n .trim()\n .replace(/\\.+$/, \"\")\n .split(\".\")\n .map((label) => {\n if (label.includes(\"_\") || [...label].every((character) => character.charCodeAt(0) <= 127)) {\n return label.toLowerCase();\n }\n const hostname = new URL(`http://${label}.example`).hostname;\n const normalized = hostname.split(\".\")[0];\n if (normalized === undefined) throw new Error(\"Domain label could not be normalized\");\n return normalized.toLowerCase();\n });\n const value = labels.join(\".\");\n if (!isNormalized(value)) {\n throw new Error(`Expected a fully qualified DNS name, received ${JSON.stringify(input)}`);\n }\n return value;\n}\n\nfunction errorMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n"],"mappings":"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"}
|
package/dist/Plan.mjs
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { Model as Model$1, Observed as Observed$1, data } from "./DnsRecord.mjs";
|
|
3
|
+
import { decode as decode$1 } from "./internal/error.mjs";
|
|
4
|
+
import { Schema } from "effect";
|
|
5
|
+
//#region src/Plan.ts
|
|
6
|
+
/**
|
|
7
|
+
* A reviewable, digest-bound set of DNS operations. Plans are additive and fail closed: matching
|
|
8
|
+
* records are `Noop`, missing records are `Create`, incompatible state is `Conflict`. A
|
|
9
|
+
* provisioning plan never updates or deletes; a cleanup plan carries `Delete` operations for
|
|
10
|
+
* records a receipt proves DomainKit created.
|
|
11
|
+
*/
|
|
12
|
+
var Plan_exports = /* @__PURE__ */ __exportAll({
|
|
13
|
+
Conflict: () => Conflict,
|
|
14
|
+
Create: () => Create,
|
|
15
|
+
Delete: () => Delete,
|
|
16
|
+
Digest: () => Digest,
|
|
17
|
+
Kind: () => Kind,
|
|
18
|
+
Model: () => Model,
|
|
19
|
+
Noop: () => Noop,
|
|
20
|
+
Operation: () => Operation,
|
|
21
|
+
OperationId: () => OperationId,
|
|
22
|
+
PlanId: () => PlanId,
|
|
23
|
+
Version: () => Version,
|
|
24
|
+
conflicts: () => conflicts,
|
|
25
|
+
decode: () => decode,
|
|
26
|
+
encode: () => encode,
|
|
27
|
+
isApplicable: () => isApplicable,
|
|
28
|
+
renderInstructions: () => renderInstructions,
|
|
29
|
+
writes: () => writes
|
|
30
|
+
});
|
|
31
|
+
const Record = Schema.suspend(() => Model$1);
|
|
32
|
+
const Observed = Schema.suspend(() => Observed$1);
|
|
33
|
+
const PlanId = Schema.String.pipe(Schema.brand("@domainkit/PlanId"));
|
|
34
|
+
const Digest = Schema.String.pipe(Schema.brand("@domainkit/Digest"));
|
|
35
|
+
const OperationId = Schema.String.pipe(Schema.brand("@domainkit/OperationId"));
|
|
36
|
+
const Kind = Schema.Literals(["provisioning", "cleanup"]);
|
|
37
|
+
var Create = class extends Schema.TaggedClass("@domainkit/Plan/Create")("Create", {
|
|
38
|
+
id: OperationId,
|
|
39
|
+
record: Record
|
|
40
|
+
}) {};
|
|
41
|
+
var Noop = class extends Schema.TaggedClass("@domainkit/Plan/Noop")("Noop", {
|
|
42
|
+
id: OperationId,
|
|
43
|
+
record: Record,
|
|
44
|
+
existing: Observed,
|
|
45
|
+
ttlDrift: Schema.Boolean
|
|
46
|
+
}) {};
|
|
47
|
+
var Conflict = class extends Schema.TaggedClass("@domainkit/Plan/Conflict")("Conflict", {
|
|
48
|
+
id: OperationId,
|
|
49
|
+
record: Record,
|
|
50
|
+
existing: Schema.Array(Observed),
|
|
51
|
+
reason: Schema.Literals([
|
|
52
|
+
"exclusive-name",
|
|
53
|
+
"cname-collision",
|
|
54
|
+
"value-mismatch",
|
|
55
|
+
"opaque",
|
|
56
|
+
"missing"
|
|
57
|
+
])
|
|
58
|
+
}) {};
|
|
59
|
+
/** Cleanup only: remove the provider record a receipt proves DomainKit created. */
|
|
60
|
+
var Delete = class extends Schema.TaggedClass("@domainkit/Plan/Delete")("Delete", {
|
|
61
|
+
id: OperationId,
|
|
62
|
+
record: Record,
|
|
63
|
+
providerRecordId: Schema.String
|
|
64
|
+
}) {};
|
|
65
|
+
const Operation = Schema.Union([
|
|
66
|
+
Create,
|
|
67
|
+
Noop,
|
|
68
|
+
Conflict,
|
|
69
|
+
Delete
|
|
70
|
+
]);
|
|
71
|
+
const Version = Schema.Literal("domainkit.plan.v2");
|
|
72
|
+
var Model = class extends Schema.Class("@domainkit/Plan")({
|
|
73
|
+
id: PlanId,
|
|
74
|
+
version: Version,
|
|
75
|
+
kind: Kind,
|
|
76
|
+
digest: Digest,
|
|
77
|
+
domain: Schema.String,
|
|
78
|
+
zone: Schema.String,
|
|
79
|
+
provider: Schema.String,
|
|
80
|
+
attachmentId: Schema.String,
|
|
81
|
+
operations: Schema.Array(Operation),
|
|
82
|
+
createdAt: Schema.DateTimeUtcFromString,
|
|
83
|
+
expiresAt: Schema.DateTimeUtcFromString
|
|
84
|
+
}) {};
|
|
85
|
+
const decode = (input) => decode$1(Model, input);
|
|
86
|
+
const encode = Schema.encodeSync(Model);
|
|
87
|
+
/** `true` when the plan has no conflicts and at least one write (`Create` or `Delete`). */
|
|
88
|
+
const isApplicable = (plan) => conflicts(plan).length === 0 && writes(plan).length > 0;
|
|
89
|
+
const conflicts = (plan) => plan.operations.filter((operation) => operation._tag === "Conflict");
|
|
90
|
+
/** The operations that would touch the provider: creates for provisioning, deletes for cleanup. */
|
|
91
|
+
const writes = (plan) => plan.operations.filter((operation) => operation._tag === "Create" || operation._tag === "Delete");
|
|
92
|
+
/** Manual instructions for hosts whose customers apply records by hand. */
|
|
93
|
+
const renderInstructions = (plan) => plan.operations.map((operation) => {
|
|
94
|
+
const verb = operation._tag === "Create" ? "ADD" : operation._tag === "Delete" ? "REMOVE" : operation._tag === "Noop" ? "KEEP" : `CONFLICT (${operation.reason})`;
|
|
95
|
+
const record = operation.record;
|
|
96
|
+
const ttl = record.ttl === null ? "" : ` ttl=${record.ttl}`;
|
|
97
|
+
return `${verb} ${record._tag} ${record.name} ${data(record)}${ttl}`;
|
|
98
|
+
}).join("\n");
|
|
99
|
+
//#endregion
|
|
100
|
+
export { Conflict, Create, Delete, Digest, Kind, Model, Noop, Operation, OperationId, PlanId, Plan_exports, Version, conflicts, decode, encode, isApplicable, renderInstructions, writes };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=Plan.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Plan.mjs","names":["DnsRecord.Model","DnsRecord.Observed","Errors.decode","DnsRecord.data"],"sources":["../src/Plan.ts"],"sourcesContent":["/**\n * A reviewable, digest-bound set of DNS operations. Plans are additive and fail closed: matching\n * records are `Noop`, missing records are `Create`, incompatible state is `Conflict`. A\n * provisioning plan never updates or deletes; a cleanup plan carries `Delete` operations for\n * records a receipt proves DomainKit created.\n */\nimport { Effect, Schema } from \"effect\";\n\nimport * as DnsRecord from \"./DnsRecord.ts\";\nimport * as Errors from \"./internal/error.ts\";\n\n// Read lazily: DnsRecord sits in the same import cycle (see DnsRecord.ts).\nconst Record = Schema.suspend(() => DnsRecord.Model);\nconst Observed = Schema.suspend(() => DnsRecord.Observed);\n\nexport const PlanId = Schema.String.pipe(Schema.brand(\"@domainkit/PlanId\"));\nexport type PlanId = typeof PlanId.Type;\n\nexport const Digest = Schema.String.pipe(Schema.brand(\"@domainkit/Digest\"));\nexport type Digest = typeof Digest.Type;\n\nexport const OperationId = Schema.String.pipe(Schema.brand(\"@domainkit/OperationId\"));\nexport type OperationId = typeof OperationId.Type;\n\nexport const Kind = Schema.Literals([\"provisioning\", \"cleanup\"]);\nexport type Kind = typeof Kind.Type;\n\nexport class Create extends Schema.TaggedClass<Create>(\"@domainkit/Plan/Create\")(\"Create\", {\n id: OperationId,\n record: Record,\n}) {}\nexport class Noop extends Schema.TaggedClass<Noop>(\"@domainkit/Plan/Noop\")(\"Noop\", {\n id: OperationId,\n record: Record,\n existing: Observed,\n ttlDrift: Schema.Boolean,\n}) {}\nexport class Conflict extends Schema.TaggedClass<Conflict>(\"@domainkit/Plan/Conflict\")(\"Conflict\", {\n id: OperationId,\n record: Record,\n existing: Schema.Array(Observed),\n reason: Schema.Literals([\n \"exclusive-name\",\n \"cname-collision\",\n \"value-mismatch\",\n \"opaque\",\n \"missing\",\n ]),\n}) {}\n/** Cleanup only: remove the provider record a receipt proves DomainKit created. */\nexport class Delete extends Schema.TaggedClass<Delete>(\"@domainkit/Plan/Delete\")(\"Delete\", {\n id: OperationId,\n record: Record,\n providerRecordId: Schema.String,\n}) {}\nexport const Operation = Schema.Union([Create, Noop, Conflict, Delete]);\nexport type Operation = typeof Operation.Type;\n\nexport const Version = Schema.Literal(\"domainkit.plan.v2\");\n\nexport class Model extends Schema.Class<Model>(\"@domainkit/Plan\")({\n id: PlanId,\n version: Version,\n kind: Kind,\n digest: Digest,\n domain: Schema.String,\n zone: Schema.String,\n provider: Schema.String,\n attachmentId: Schema.String,\n operations: Schema.Array(Operation),\n createdAt: Schema.DateTimeUtcFromString,\n expiresAt: Schema.DateTimeUtcFromString,\n}) {}\nexport type Encoded = typeof Model.Encoded;\n\nexport const decode = (input: unknown): Effect.Effect<Model, Errors.DomainKitError> =>\n Errors.decode(Model, input);\nexport const encode: (plan: Model) => Encoded = Schema.encodeSync(Model);\n\n/** `true` when the plan has no conflicts and at least one write (`Create` or `Delete`). */\nexport const isApplicable = (plan: Model): boolean =>\n conflicts(plan).length === 0 && writes(plan).length > 0;\n\nexport const conflicts = (plan: Model): ReadonlyArray<Conflict> =>\n plan.operations.filter((operation): operation is Conflict => operation._tag === \"Conflict\");\n\n/** The operations that would touch the provider: creates for provisioning, deletes for cleanup. */\nexport const writes = (plan: Model): ReadonlyArray<Create | Delete> =>\n plan.operations.filter(\n (operation): operation is Create | Delete =>\n operation._tag === \"Create\" || operation._tag === \"Delete\",\n );\n\n/** Manual instructions for hosts whose customers apply records by hand. */\nexport const renderInstructions = (plan: Model): string =>\n plan.operations\n .map((operation) => {\n const verb =\n operation._tag === \"Create\"\n ? \"ADD\"\n : operation._tag === \"Delete\"\n ? \"REMOVE\"\n : operation._tag === \"Noop\"\n ? \"KEEP\"\n : `CONFLICT (${operation.reason})`;\n const record = operation.record;\n const ttl = record.ttl === null ? \"\" : ` ttl=${record.ttl}`;\n return `${verb} ${record._tag} ${record.name} ${DnsRecord.data(record)}${ttl}`;\n })\n .join(\"\\n\");\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAM,SAAS,OAAO,cAAcA,OAAe;AACnD,MAAM,WAAW,OAAO,cAAcC,UAAkB;AAExD,MAAa,SAAS,OAAO,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAG1E,MAAa,SAAS,OAAO,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAG1E,MAAa,cAAc,OAAO,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAGpF,MAAa,OAAO,OAAO,SAAS,CAAC,gBAAgB,SAAS,CAAC;AAG/D,IAAa,SAAb,cAA4B,OAAO,YAAoB,wBAAwB,CAAC,CAAC,UAAU;CACzF,IAAI;CACJ,QAAQ;AACV,CAAC,CAAC,CAAC,CAAC;AACJ,IAAa,OAAb,cAA0B,OAAO,YAAkB,sBAAsB,CAAC,CAAC,QAAQ;CACjF,IAAI;CACJ,QAAQ;CACR,UAAU;CACV,UAAU,OAAO;AACnB,CAAC,CAAC,CAAC,CAAC;AACJ,IAAa,WAAb,cAA8B,OAAO,YAAsB,0BAA0B,CAAC,CAAC,YAAY;CACjG,IAAI;CACJ,QAAQ;CACR,UAAU,OAAO,MAAM,QAAQ;CAC/B,QAAQ,OAAO,SAAS;EACtB;EACA;EACA;EACA;EACA;CACF,CAAC;AACH,CAAC,CAAC,CAAC,CAAC;;AAEJ,IAAa,SAAb,cAA4B,OAAO,YAAoB,wBAAwB,CAAC,CAAC,UAAU;CACzF,IAAI;CACJ,QAAQ;CACR,kBAAkB,OAAO;AAC3B,CAAC,CAAC,CAAC,CAAC;AACJ,MAAa,YAAY,OAAO,MAAM;CAAC;CAAQ;CAAM;CAAU;AAAM,CAAC;AAGtE,MAAa,UAAU,OAAO,QAAQ,mBAAmB;AAEzD,IAAa,QAAb,cAA2B,OAAO,MAAa,iBAAiB,CAAC,CAAC;CAChE,IAAI;CACJ,SAAS;CACT,MAAM;CACN,QAAQ;CACR,QAAQ,OAAO;CACf,MAAM,OAAO;CACb,UAAU,OAAO;CACjB,cAAc,OAAO;CACrB,YAAY,OAAO,MAAM,SAAS;CAClC,WAAW,OAAO;CAClB,WAAW,OAAO;AACpB,CAAC,CAAC,CAAC,CAAC;AAGJ,MAAa,UAAU,UACrBC,SAAc,OAAO,KAAK;AAC5B,MAAa,SAAmC,OAAO,WAAW,KAAK;;AAGvE,MAAa,gBAAgB,SAC3B,UAAU,IAAI,CAAC,CAAC,WAAW,KAAK,OAAO,IAAI,CAAC,CAAC,SAAS;AAExD,MAAa,aAAa,SACxB,KAAK,WAAW,QAAQ,cAAqC,UAAU,SAAS,UAAU;;AAG5F,MAAa,UAAU,SACrB,KAAK,WAAW,QACb,cACC,UAAU,SAAS,YAAY,UAAU,SAAS,QACtD;;AAGF,MAAa,sBAAsB,SACjC,KAAK,WACF,KAAK,cAAc;CAClB,MAAM,OACJ,UAAU,SAAS,WACf,QACA,UAAU,SAAS,WACjB,WACA,UAAU,SAAS,SACjB,SACA,aAAa,UAAU,OAAO;CACxC,MAAM,SAAS,UAAU;CACzB,MAAM,MAAM,OAAO,QAAQ,OAAO,KAAK,QAAQ,OAAO;CACtD,OAAO,GAAG,KAAK,GAAG,OAAO,KAAK,GAAG,OAAO,KAAK,GAAGC,KAAe,MAAM,IAAI;AAC3E,CAAC,CAAC,CACD,KAAK,IAAI"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { Context, Layer } from "effect";
|
|
3
|
+
//#region src/Principal.ts
|
|
4
|
+
/**
|
|
5
|
+
* Who is acting. Required by every lifecycle operation and every Storage query; there is no
|
|
6
|
+
* default, so cross-tenant access is a type error rather than a runtime check. `domainkit/server`
|
|
7
|
+
* provides it per request from the host's `Identity`.
|
|
8
|
+
*/
|
|
9
|
+
var Principal_exports = /* @__PURE__ */ __exportAll({
|
|
10
|
+
Service: () => Service,
|
|
11
|
+
layer: () => layer,
|
|
12
|
+
make: () => make
|
|
13
|
+
});
|
|
14
|
+
var Service = class extends Context.Service()("@domainkit/Principal") {};
|
|
15
|
+
const make = (input) => ({
|
|
16
|
+
ownerId: input.ownerId,
|
|
17
|
+
actorId: input.actorId
|
|
18
|
+
});
|
|
19
|
+
const layer = (input) => Layer.succeed(Service)(make(input));
|
|
20
|
+
//#endregion
|
|
21
|
+
export { Principal_exports, Service, layer, make };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=Principal.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Principal.mjs","names":[],"sources":["../src/Principal.ts"],"sourcesContent":["/**\n * Who is acting. Required by every lifecycle operation and every Storage query; there is no\n * default, so cross-tenant access is a type error rather than a runtime check. `domainkit/server`\n * provides it per request from the host's `Identity`.\n */\nimport { Context, Layer } from \"effect\";\n\nexport interface Interface {\n /** Tenant boundary: organization, workspace, account. Storage scopes every row by it. */\n readonly ownerId: string;\n /** The user or automation acting on the tenant's behalf; recorded on approvals and receipts. */\n readonly actorId: string;\n}\n\nexport class Service extends Context.Service<Service, Interface>()(\"@domainkit/Principal\") {}\n\nexport const make = (input: Interface): Interface => ({\n ownerId: input.ownerId,\n actorId: input.actorId,\n});\n\nexport const layer = (input: Interface): Layer.Layer<Service> =>\n Layer.succeed(Service)(make(input));\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAa,UAAb,cAA6B,QAAQ,QAA4B,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC;AAE5F,MAAa,QAAQ,WAAiC;CACpD,SAAS,MAAM;CACf,SAAS,MAAM;AACjB;AAEA,MAAa,SAAS,UACpB,MAAM,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,CAAC"}
|