domainkit 0.2.2 → 0.3.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.
Files changed (58) hide show
  1. package/README.md +26 -26
  2. package/dist/index.d.mts +639 -187
  3. package/dist/index.mjs +301 -300
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/promise.d.mts +464 -0
  6. package/dist/promise.mjs +636 -0
  7. package/dist/promise.mjs.map +1 -0
  8. package/dist/{resolver-CxE-VDw4.mjs → resolver-CvK7JoJM.mjs} +401 -54
  9. package/dist/resolver-CvK7JoJM.mjs.map +1 -0
  10. package/dist/{resolver-Dc0hwV-J.d.mts → resolver-uqe1h5Vz.d.mts} +1513 -25
  11. package/dist/testing.d.mts +4 -5
  12. package/dist/testing.mjs +17 -3
  13. package/dist/testing.mjs.map +1 -1
  14. package/dist/verify-BoWy70ew.mjs +2420 -0
  15. package/dist/verify-BoWy70ew.mjs.map +1 -0
  16. package/dist/{verify-Dls29YC-.d.mts → verify-CkgVrwyl.d.mts} +318 -21
  17. package/package.json +6 -30
  18. package/dist/auth-BR-19zj-.mjs +0 -738
  19. package/dist/auth-BR-19zj-.mjs.map +0 -1
  20. package/dist/auth-g-waCHcz.mjs +0 -671
  21. package/dist/auth-g-waCHcz.mjs.map +0 -1
  22. package/dist/authorization-OeaSR47S.mjs +0 -284
  23. package/dist/authorization-OeaSR47S.mjs.map +0 -1
  24. package/dist/canonical-json-CpvqGMcr.mjs +0 -57
  25. package/dist/canonical-json-CpvqGMcr.mjs.map +0 -1
  26. package/dist/cloudflare-BrZPU9li.d.mts +0 -32
  27. package/dist/cloudflare-CGmasR8A.mjs +0 -69
  28. package/dist/cloudflare-CGmasR8A.mjs.map +0 -1
  29. package/dist/cloudflare.d.mts +0 -3
  30. package/dist/cloudflare.mjs +0 -2
  31. package/dist/connection-BfkloPZy.d.mts +0 -186
  32. package/dist/connection-BwtOwpH6.mjs +0 -195
  33. package/dist/connection-BwtOwpH6.mjs.map +0 -1
  34. package/dist/connection-CjNQe_E-.mjs +0 -58
  35. package/dist/connection-CjNQe_E-.mjs.map +0 -1
  36. package/dist/connection-api-DNuEZ_jR.d.mts +0 -7
  37. package/dist/dns-record-BLeqo56C.mjs +0 -289
  38. package/dist/dns-record-BLeqo56C.mjs.map +0 -1
  39. package/dist/effect-cloudflare.d.mts +0 -2
  40. package/dist/effect-cloudflare.mjs +0 -2
  41. package/dist/effect-vercel.d.mts +0 -2
  42. package/dist/effect-vercel.mjs +0 -2
  43. package/dist/effect.d.mts +0 -36
  44. package/dist/effect.mjs +0 -51
  45. package/dist/effect.mjs.map +0 -1
  46. package/dist/index-BHWRTThN.d.mts +0 -159
  47. package/dist/index-D3PVknwE.d.mts +0 -145
  48. package/dist/resolver-CxE-VDw4.mjs.map +0 -1
  49. package/dist/vercel-BsNDu4Np.d.mts +0 -31
  50. package/dist/vercel-CfoJaaCu.mjs +0 -60
  51. package/dist/vercel-CfoJaaCu.mjs.map +0 -1
  52. package/dist/vercel.d.mts +0 -3
  53. package/dist/vercel.mjs +0 -2
  54. package/dist/verify-BKbvq7IN.mjs +0 -642
  55. package/dist/verify-BKbvq7IN.mjs.map +0 -1
  56. package/dist/zone-discovery-BPnH3sLU.d.mts +0 -1397
  57. package/dist/zones-DKHTpX9C.mjs +0 -19
  58. package/dist/zones-DKHTpX9C.mjs.map +0 -1
@@ -1,642 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { E as decode$1, O as parse$1, T as Schema$2, _ as equals, b as Service$1, k as Error$1, m as data } from "./dns-record-BLeqo56C.mjs";
3
- import { t as candidates } from "./zones-DKHTpX9C.mjs";
4
- import { a as authorizationError, i as assertGrant, t as AuthorizationError } from "./connection-CjNQe_E-.mjs";
5
- import { i as toAsync$3, n as Service$2, t as Error$2, x as authorize$1 } from "./resolver-CxE-VDw4.mjs";
6
- import { Context, Data, Effect, Layer, Option, Schema, SchemaIssue, SchemaTransformation } from "effect";
7
- import * as DnsPacket from "@leichtgewicht/dns-packet";
8
- //#region package.json
9
- var version = "0.2.2";
10
- //#endregion
11
- //#region src/auth/diagnostic.ts
12
- var diagnostic_exports = /* @__PURE__ */ __exportAll({
13
- Category: () => Category,
14
- Fields: () => Fields,
15
- RetryAdvice: () => RetryAdvice,
16
- from: () => from
17
- });
18
- const Category = Schema.Literals([
19
- "authorization",
20
- "configuration",
21
- "provider",
22
- "storage",
23
- "validation"
24
- ]);
25
- const RetryAdvice = Schema.Literals([
26
- "never",
27
- "after-user-action",
28
- "safe",
29
- "unknown"
30
- ]);
31
- const Fields = {
32
- category: Category,
33
- message: Schema.String,
34
- operation: Schema.String,
35
- retry: RetryAdvice
36
- };
37
- function from(error) {
38
- return {
39
- category: error.category,
40
- message: error.message,
41
- operation: error.operation,
42
- retry: error.retry,
43
- tag: error._tag
44
- };
45
- }
46
- //#endregion
47
- //#region src/auth/manifest.ts
48
- var manifest_exports = /* @__PURE__ */ __exportAll({
49
- Method: () => Method,
50
- Schema: () => Schema$1,
51
- decode: () => decode
52
- });
53
- const Method = Schema.TaggedUnion({
54
- integration: {
55
- capabilities: Schema.Array(Schema.Literals(["dns:read", "dns:write"])),
56
- installUrl: Schema.String,
57
- tokenEndpoint: Schema.String
58
- },
59
- oauth2: {
60
- authorizationServer: Schema.Struct({
61
- authorization_endpoint: Schema.String,
62
- issuer: Schema.String,
63
- revocation_endpoint: Schema.optionalKey(Schema.String),
64
- token_endpoint: Schema.String
65
- }),
66
- capabilities: Schema.Array(Schema.Literals(["dns:read", "dns:write"])),
67
- clientAuth: Schema.Literals([
68
- "none",
69
- "client_secret_basic",
70
- "client_secret_post"
71
- ]),
72
- scopes: Schema.Array(Schema.String)
73
- },
74
- token: {
75
- capabilities: Schema.Array(Schema.Literals(["dns:read", "dns:write"])),
76
- instructionsUrl: Schema.String
77
- }
78
- });
79
- const Schema$1 = Schema.Struct({
80
- methods: Schema.Array(Method),
81
- providerId: Schema.String
82
- });
83
- const decode = Effect.fn("ProviderAuth.decode")((input) => Schema.decodeUnknownEffect(Schema$1)(input).pipe(Effect.mapError((cause) => new Error$1({ message: cause.message }))));
84
- //#endregion
85
- //#region src/discovery/selection.ts
86
- var selection_exports = /* @__PURE__ */ __exportAll({
87
- Evidence: () => Evidence,
88
- Selection: () => Selection,
89
- select: () => select
90
- });
91
- const Evidence = Schema.Struct({
92
- accountId: Schema.String,
93
- connectionId: Schema.String,
94
- decisiveNameserverMatch: Schema.Boolean,
95
- matchedNameservers: Schema.Array(Schema$2),
96
- providerId: Schema.String,
97
- zone: Schema$2
98
- });
99
- const Selection = Schema.TaggedUnion({
100
- selected: {
101
- candidate: Evidence,
102
- evidence: Schema.Array(Evidence),
103
- reason: Schema.Literals(["explicit", "unique-nameserver-match"])
104
- },
105
- manual: {
106
- evidence: Schema.Array(Evidence),
107
- reason: Schema.Literals(["ambiguous", "unsupported"])
108
- }
109
- });
110
- function select(input) {
111
- const domain = parse$1(input.domain);
112
- const zoneCandidates = new Set(candidates(domain));
113
- const authoritative = nameserverSet(input.authoritativeNameservers);
114
- const eligible = input.connectedZones.filter((connected) => {
115
- if (!zoneCandidates.has(parse$1(connected.zone))) return false;
116
- try {
117
- assertGrant(connected.connection, connected.authorization, {
118
- capability: "dns:read",
119
- domain,
120
- ...input.now === void 0 ? {} : { now: input.now },
121
- providerId: connected.providerId
122
- });
123
- return true;
124
- } catch {
125
- return false;
126
- }
127
- });
128
- const evidence = eligible.map((connected) => evidenceFor(connected, authoritative));
129
- if (input.explicit !== void 0) {
130
- const explicitZone = parse$1(input.explicit.zone);
131
- const index = eligible.findIndex((connected) => connected.providerId === input.explicit?.providerId && connected.authorization.providerAccountId === input.explicit.accountId && parse$1(connected.zone) === explicitZone);
132
- if (index < 0) throw authorizationError("Explicit provider zone is not connected or granted", "ProviderDiscovery.select");
133
- const candidate = evidence[index];
134
- if (candidate === void 0) throw new Error("Eligible provider evidence is missing");
135
- return {
136
- _tag: "selected",
137
- candidate,
138
- evidence,
139
- reason: "explicit"
140
- };
141
- }
142
- const decisive = evidence.filter(({ decisiveNameserverMatch }) => decisiveNameserverMatch);
143
- const candidate = decisive[0];
144
- return decisive.length === 1 && candidate !== void 0 ? {
145
- _tag: "selected",
146
- candidate,
147
- evidence,
148
- reason: "unique-nameserver-match"
149
- } : {
150
- _tag: "manual",
151
- evidence,
152
- reason: decisive.length > 1 ? "ambiguous" : "unsupported"
153
- };
154
- }
155
- function evidenceFor(connected, authoritative) {
156
- const configured = new Set(nameserverSet(connected.nameservers));
157
- const matchedNameservers = authoritative.filter((nameserver) => configured.has(nameserver));
158
- return {
159
- accountId: connected.authorization.providerAccountId,
160
- connectionId: connected.connection.id,
161
- decisiveNameserverMatch: authoritative.length > 0 && matchedNameservers.length === authoritative.length,
162
- matchedNameservers,
163
- providerId: connected.providerId,
164
- zone: parse$1(connected.zone)
165
- };
166
- }
167
- function nameserverSet(nameservers) {
168
- return [...new Set(nameservers.map(parse$1))].sort();
169
- }
170
- //#endregion
171
- //#region src/plan/connection-authorization.ts
172
- var connection_authorization_exports = /* @__PURE__ */ __exportAll({ authorize: () => authorize });
173
- const authorize = Effect.fn("ConnectionAuthorization.authorize")(function* (input) {
174
- const domain = yield* Effect.try({
175
- try: () => assertGrant(input.connection, input.authorization, {
176
- capability: "dns:write",
177
- domain: input.domain,
178
- providerId: input.plan.providerId
179
- }),
180
- catch: (cause) => cause instanceof AuthorizationError || cause instanceof Error$1 ? cause : authorizationError("Connection grant is invalid", "ConnectionAuthorization.authorize")
181
- });
182
- const authorization = yield* authorize$1(input.plan, input.operationIds, input.allowPartial === void 0 ? {} : { allowPartial: input.allowPartial });
183
- const selected = new Set(authorization.operationIds);
184
- if (input.plan.operations.filter((operation) => operation._tag === "create" && selected.has(operation.id) && operation.requirement.name !== domain && !operation.requirement.name.endsWith(`.${domain}`)).length > 0) return yield* authorizationError(`Plan operations are outside the granted domain ${domain}`, "ConnectionAuthorization.authorize");
185
- return authorization;
186
- });
187
- //#endregion
188
- //#region src/verification/dns-data.ts
189
- var dns_data_exports = /* @__PURE__ */ __exportAll({ parse: () => parse });
190
- const CanonicalAddress = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transform({
191
- decode: (value) => value.trim().toLowerCase(),
192
- encode: (value) => value
193
- })));
194
- const CanonicalDomain = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transformOrFail({
195
- decode: (value, options) => Effect.try({
196
- try: () => parse$1(value).toString(),
197
- catch: (cause) => new SchemaIssue.InvalidValue({ message: cause instanceof Error ? cause.message : String(cause) }, value, options)
198
- }),
199
- encode: (value) => Effect.succeed(value)
200
- })));
201
- const CanonicalMx = tokenizedDomain(2, 1);
202
- const CanonicalSrv = tokenizedDomain(4, 3);
203
- const CanonicalTxt = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transform({
204
- decode: (value) => {
205
- const trimmed = value.trim();
206
- const chunks = [...trimmed.matchAll(/"((?:\\.|[^"])*)"/g)];
207
- return chunks.length === 0 ? trimmed : chunks.map((match) => (match[1] ?? "").replace(/\\"/g, "\"").replace(/\\\\/g, "\\")).join("");
208
- },
209
- encode: (value) => value
210
- })));
211
- const CanonicalCaa = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transform({
212
- decode: (value) => value.trim().replace(/\s+"([\s\S]*)"$/, " $1"),
213
- encode: (value) => value
214
- })));
215
- function parse(type, input) {
216
- const schema = (() => {
217
- switch (type) {
218
- case "A":
219
- case "AAAA": return CanonicalAddress;
220
- case "CNAME":
221
- case "NS": return CanonicalDomain;
222
- case "MX": return CanonicalMx;
223
- case "SRV": return CanonicalSrv;
224
- case "TXT": return CanonicalTxt;
225
- case "CAA": return CanonicalCaa;
226
- }
227
- })();
228
- try {
229
- return Schema.decodeUnknownSync(schema)(input);
230
- } catch (cause) {
231
- throw new Error$1({ message: cause instanceof Error ? cause.message : String(cause) });
232
- }
233
- }
234
- function tokenizedDomain(length, domainIndex) {
235
- return Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transformOrFail({
236
- decode: (value, options) => Effect.try({
237
- try: () => {
238
- const parts = value.trim().split(/\s+/);
239
- if (parts.length !== length) throw new Error("DNS record data has an invalid field count");
240
- const domain = parts[domainIndex];
241
- if (domain === void 0) throw new Error("DNS record target is missing");
242
- parts[domainIndex] = parse$1(domain);
243
- return parts.join(" ");
244
- },
245
- catch: (cause) => new SchemaIssue.InvalidValue({ message: cause instanceof Error ? cause.message : String(cause) }, value, options)
246
- }),
247
- encode: (value) => Effect.succeed(value)
248
- })));
249
- }
250
- //#endregion
251
- //#region src/verification/doh.ts
252
- var doh_exports = /* @__PURE__ */ __exportAll({
253
- layer: () => layer$2,
254
- make: () => make$3,
255
- toAsync: () => toAsync$2
256
- });
257
- function make$3(options) {
258
- const fetch = options.fetch ?? globalThis.fetch;
259
- const timeoutMs = options.timeoutMs ?? 5e3;
260
- return { resolve: Effect.fn("DnsOverHttps.resolve")((query) => Effect.tryPromise({
261
- try: (effectSignal) => request({
262
- effectSignal,
263
- fetch,
264
- query,
265
- timeoutMs,
266
- endpoint: options.endpoint
267
- }),
268
- catch: (cause) => cause instanceof Error$2 ? cause : new Error$2({
269
- cause,
270
- message: cause instanceof Error ? cause.message : "DNS resolution failed",
271
- reason: "transport"
272
- })
273
- }).pipe(Effect.flatMap((message) => decodeResolution(query, message)))) };
274
- }
275
- const layer$2 = (options) => Layer.succeed(Service$2, make$3(options));
276
- const toAsync$2 = (options) => toAsync$3(make$3(options));
277
- function decodeResolution(query, message) {
278
- return Effect.try({
279
- try: () => DnsPacket.decode(message),
280
- catch: (cause) => new Error$2({
281
- cause,
282
- message: "DoH returned an invalid DNS message",
283
- reason: "response"
284
- })
285
- }).pipe(Effect.flatMap((packet) => validatePacket(query, packet)), Effect.flatMap(decodePacket));
286
- }
287
- function decodePacket(packet) {
288
- if (packet.rcode === "NXDOMAIN") return Effect.succeed({ _tag: "nodata" });
289
- if (packet.rcode !== "NOERROR") return Effect.fail(new Error$2({
290
- message: `DNS resolver returned ${packet.rcode ?? "an unknown response code"}`,
291
- reason: "response"
292
- }));
293
- if (packet.answers === void 0 || packet.answers.length === 0) return Effect.succeed({ _tag: "nodata" });
294
- return Effect.forEach(packet.answers, decodeAnswer, { concurrency: "unbounded" }).pipe(Effect.map((answers) => {
295
- const supportedAnswers = answers.filter((answer) => answer !== null);
296
- return supportedAnswers.length === 0 ? { _tag: "nodata" } : {
297
- _tag: "answer",
298
- answers: supportedAnswers
299
- };
300
- }));
301
- }
302
- function validatePacket(query, packet) {
303
- return Effect.try({
304
- try: () => {
305
- if (packet.type !== "response") throw new Error("DoH returned a DNS query");
306
- if (packet.id !== 0) throw new Error("DoH response used an unexpected message ID");
307
- if (packet.flag_tc) throw new Error("DoH returned a truncated DNS response");
308
- const questions = packet.questions ?? [];
309
- if (questions.length !== 1) throw new Error("DoH returned an unexpected question count");
310
- const question = questions[0];
311
- if (question === void 0) throw new Error("DoH response omitted the DNS question");
312
- if (question.class !== "IN" || question.type !== query.type || parse$1(question.name) !== query.name) throw new Error("DoH response did not match the DNS question");
313
- return packet;
314
- },
315
- catch: (cause) => new Error$2({
316
- cause,
317
- message: cause instanceof Error ? cause.message : "DoH returned an invalid DNS response",
318
- reason: "response"
319
- })
320
- });
321
- }
322
- function decodeAnswer(answer) {
323
- return Effect.gen(function* () {
324
- if (answer.class !== "IN") return null;
325
- const decoded = yield* Effect.try({
326
- try: () => answerData(answer),
327
- catch: (cause) => new Error$2({
328
- cause,
329
- message: "DoH returned invalid DNS record data",
330
- reason: "response"
331
- })
332
- });
333
- if (decoded === void 0) return null;
334
- const name = yield* decode$1(answer.name);
335
- const data = yield* Effect.try({
336
- try: () => parse(decoded.type, decoded.data),
337
- catch: (cause) => new Error$2({
338
- cause,
339
- message: "DoH returned invalid DNS record data",
340
- reason: "response"
341
- })
342
- });
343
- if (answer.ttl === void 0) return yield* new Error$2({
344
- message: "DoH response omitted the DNS record TTL",
345
- reason: "response"
346
- });
347
- return {
348
- data,
349
- name,
350
- ttl: answer.ttl,
351
- type: decoded.type
352
- };
353
- }).pipe(Effect.mapError((cause) => cause instanceof Error$2 ? cause : new Error$2({
354
- cause,
355
- message: cause.message,
356
- reason: "response"
357
- })));
358
- }
359
- function answerData(answer) {
360
- switch (answer.type) {
361
- case "A":
362
- case "AAAA":
363
- case "CNAME":
364
- case "NS": return {
365
- data: answer.data,
366
- type: answer.type
367
- };
368
- case "CAA": return {
369
- data: `${answer.data.flags ?? 0} ${answer.data.tag} ${answer.data.value}`,
370
- type: answer.type
371
- };
372
- case "MX": return {
373
- data: `${requiredNumber(answer.data.preference, "MX preference")} ${answer.data.exchange}`,
374
- type: answer.type
375
- };
376
- case "SRV": return {
377
- data: [
378
- requiredNumber(answer.data.priority, "SRV priority"),
379
- requiredNumber(answer.data.weight, "SRV weight"),
380
- requiredNumber(answer.data.port, "SRV port"),
381
- answer.data.target
382
- ].join(" "),
383
- type: answer.type
384
- };
385
- case "TXT": return {
386
- data: decodeTxt(answer.data),
387
- type: answer.type
388
- };
389
- default: return;
390
- }
391
- }
392
- function decodeTxt(data) {
393
- const encoded = (Array.isArray(data) ? data : [data]).map((chunk) => typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
394
- const length = encoded.reduce((total, chunk) => total + chunk.length, 0);
395
- const joined = new Uint8Array(length);
396
- let offset = 0;
397
- for (const chunk of encoded) {
398
- joined.set(chunk, offset);
399
- offset += chunk.length;
400
- }
401
- return new TextDecoder("utf-8", { fatal: true }).decode(joined);
402
- }
403
- function requiredNumber(value, field) {
404
- if (value === void 0) throw new Error(`DoH response omitted ${field}`);
405
- return value;
406
- }
407
- async function request(input) {
408
- const controller = new AbortController();
409
- let timedOut = false;
410
- const abortFromEffect = () => controller.abort(input.effectSignal.reason);
411
- const abortFromHost = () => controller.abort(input.query.signal?.reason);
412
- input.effectSignal.addEventListener("abort", abortFromEffect, { once: true });
413
- input.query.signal?.addEventListener("abort", abortFromHost, { once: true });
414
- const timer = setTimeout(() => {
415
- timedOut = true;
416
- controller.abort(/* @__PURE__ */ new Error("DNS resolution timed out"));
417
- }, input.timeoutMs);
418
- try {
419
- const query = Uint8Array.from(DnsPacket.encode({
420
- flags: DnsPacket.RECURSION_DESIRED,
421
- id: 0,
422
- questions: [{
423
- name: input.query.name,
424
- type: input.query.type
425
- }],
426
- type: "query"
427
- }));
428
- const response = await input.fetch(new URL(input.endpoint), {
429
- body: query,
430
- headers: {
431
- accept: "application/dns-message",
432
- "content-type": "application/dns-message"
433
- },
434
- method: "POST",
435
- signal: controller.signal
436
- });
437
- if (!response.ok) throw new Error$2({
438
- message: `DoH returned HTTP ${response.status}`,
439
- reason: "transport"
440
- });
441
- const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
442
- if (contentType !== "application/dns-message") throw new Error$2({
443
- message: `DoH returned unsupported content type ${contentType ?? "<missing>"}`,
444
- reason: "response"
445
- });
446
- return new Uint8Array(await response.arrayBuffer());
447
- } catch (cause) {
448
- if (timedOut) throw new Error$2({
449
- message: "DNS query timed out",
450
- reason: "timeout"
451
- });
452
- throw cause;
453
- } finally {
454
- clearTimeout(timer);
455
- input.effectSignal.removeEventListener("abort", abortFromEffect);
456
- input.query.signal?.removeEventListener("abort", abortFromHost);
457
- }
458
- }
459
- //#endregion
460
- //#region src/verification/cloudflare-doh.ts
461
- var cloudflare_doh_exports = /* @__PURE__ */ __exportAll({
462
- layer: () => layer$1,
463
- make: () => make$2,
464
- toAsync: () => toAsync$1
465
- });
466
- const endpoint$1 = "https://cloudflare-dns.com/dns-query";
467
- function make$2(options = {}) {
468
- return make$3({
469
- ...options,
470
- endpoint: options.endpoint ?? endpoint$1
471
- });
472
- }
473
- const layer$1 = (options = {}) => Layer.succeed(Service$2, make$2(options));
474
- const toAsync$1 = (options = {}) => toAsync$3(make$2(options));
475
- //#endregion
476
- //#region src/verification/google-doh.ts
477
- var google_doh_exports = /* @__PURE__ */ __exportAll({
478
- layer: () => layer,
479
- make: () => make$1,
480
- toAsync: () => toAsync
481
- });
482
- const endpoint = "https://dns.google/dns-query";
483
- function make$1(options = {}) {
484
- return make$3({
485
- ...options,
486
- endpoint: options.endpoint ?? endpoint
487
- });
488
- }
489
- const layer = (options = {}) => Layer.succeed(Service$2, make$1(options));
490
- const toAsync = (options = {}) => toAsync$3(make$1(options));
491
- //#endregion
492
- //#region src/verification/resolver-pool.ts
493
- var resolver_pool_exports = /* @__PURE__ */ __exportAll({
494
- Observation: () => Observation,
495
- Policy: () => Policy,
496
- Service: () => Service,
497
- defaultLayer: () => defaultLayer,
498
- defaultMake: () => defaultMake,
499
- make: () => make
500
- });
501
- const Observation = Data.taggedEnum();
502
- const PolicyVariants = Data.taggedEnum();
503
- const QuorumMinimum = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));
504
- const PolicySchema = Schema.TaggedUnion({
505
- AllMatch: {},
506
- AnyMatch: {},
507
- Quorum: { minimum: QuorumMinimum }
508
- });
509
- const Policy = {
510
- AllMatch: PolicyVariants.AllMatch,
511
- AnyMatch: PolicyVariants.AnyMatch,
512
- Quorum: ({ minimum }) => PolicyVariants.Quorum({ minimum: Schema.decodeUnknownSync(QuorumMinimum)(minimum) }),
513
- Schema: PolicySchema
514
- };
515
- var Service = class extends Context.Service()("@domainkit/DnsResolverPool") {};
516
- function make(entries) {
517
- return Service.of({ observe: Effect.fn("DnsResolverPool.observe")((query) => Effect.forEach(entries, (entry) => observe$1(entry, query), { concurrency: "unbounded" })) });
518
- }
519
- /** Cloudflare and Google RFC wire-format DoH resolvers. */
520
- function defaultMake(options = {}) {
521
- const timeoutMs = options.timeoutMs ?? 5e3;
522
- return make([{
523
- id: "cloudflare",
524
- resolver: make$2(options),
525
- timeoutMs
526
- }, {
527
- id: "google",
528
- resolver: make$1(options),
529
- timeoutMs
530
- }]);
531
- }
532
- const defaultLayer = (options = {}) => Layer.succeed(Service, defaultMake(options));
533
- function observe$1(entry, query) {
534
- const timeoutMs = entry.timeoutMs ?? 5e3;
535
- return entry.resolver.resolve(query).pipe(Effect.timeout(timeoutMs), Effect.match({
536
- onFailure: (failure) => {
537
- if (failure._tag === "TimeoutError" || failure._tag === "ResolverError" && failure.reason === "timeout") return Observation.TimedOut({
538
- resolverId: entry.id,
539
- timeoutMs
540
- });
541
- return Observation.Failed({
542
- message: failure.message,
543
- reason: failure.reason === "response" ? "response" : "transport",
544
- resolverId: entry.id
545
- });
546
- },
547
- onSuccess: (resolution) => resolution._tag === "nodata" ? Observation.NoData({ resolverId: entry.id }) : Observation.Answer({
548
- answers: resolution.answers,
549
- resolverId: entry.id
550
- })
551
- }));
552
- }
553
- //#endregion
554
- //#region src/verification/verify.ts
555
- var verify_exports = /* @__PURE__ */ __exportAll({
556
- Provider: () => Provider,
557
- ProviderObservation: () => ProviderObservation,
558
- PublicDns: () => PublicDns,
559
- PublicDnsObservation: () => PublicDnsObservation,
560
- Result: () => Result,
561
- observe: () => observe
562
- });
563
- const PublicDns = Data.taggedEnum();
564
- const Provider = Data.taggedEnum();
565
- const ProviderObservation = Data.taggedEnum();
566
- const PublicDnsObservation = Data.taggedEnum();
567
- const Result = Data.taggedEnum();
568
- function observe(input) {
569
- return observeEffect(input);
570
- }
571
- const observeEffect = Effect.fn("Verification.observe")(function* (input) {
572
- const publicDns = input.publicDns ?? PublicDns.Enabled({});
573
- const provider = input.provider ?? Provider.Disabled();
574
- const publicEffect = publicDns._tag === "Disabled" ? Effect.succeed(null) : observePublicDns(input.record, publicDns.policy ?? Policy.AnyMatch());
575
- const providerEffect = provider._tag === "Disabled" ? Effect.succeed(null) : Effect.flatMap(Service$1, (service) => observeProvider(service, provider.zone, input.record).pipe(Effect.catch((failure) => Effect.succeed(ProviderObservation.Unavailable({ message: failure.message })))));
576
- const [providerObservation, publicDnsObservation] = yield* Effect.all([providerEffect, publicEffect], { concurrency: "unbounded" });
577
- return aggregate({
578
- provider: providerObservation,
579
- publicDns: publicDnsObservation
580
- });
581
- });
582
- function observeProvider(provider, zone, requirement) {
583
- return provider.listRecords(zone).pipe(Effect.map((records) => {
584
- if (records.some((existing) => existing._tag !== "Opaque" && equals(existing, requirement))) return ProviderObservation.Matched();
585
- const sameSet = records.filter((existing) => existing._tag !== "Opaque" && existing.name === requirement.name && existing._tag === requirement._tag);
586
- return sameSet.length === 0 ? ProviderObservation.Pending() : ProviderObservation.Mismatch({ records: sameSet });
587
- }));
588
- }
589
- function observePublicDns(requirement, policy) {
590
- return Effect.gen(function* () {
591
- const validatedPolicy = yield* Schema.decodeUnknownEffect(Policy.Schema)(policy).pipe(Effect.mapError((cause) => new Error$1({ message: cause.message })));
592
- const configuredPool = yield* Effect.serviceOption(Service);
593
- const evidence = yield* Option.getOrElse(configuredPool, () => defaultMake()).observe({
594
- name: requirement.name,
595
- type: requirement._tag
596
- });
597
- if (validatedPolicy._tag === "Quorum" && validatedPolicy.minimum > evidence.length) return yield* new Error$1({ message: `Quorum minimum ${validatedPolicy.minimum} exceeds the ${evidence.length} configured resolvers` });
598
- return evaluatePublicDns(requirement, validatedPolicy, evidence);
599
- });
600
- }
601
- function evaluatePublicDns(requirement, policy, evidence) {
602
- const matchedResolverIds = evidence.flatMap((observation) => observation._tag === "Answer" && answersMatch(requirement, observation.answers) ? [observation.resolverId] : []);
603
- const required = policy._tag === "AnyMatch" ? 1 : policy._tag === "AllMatch" ? evidence.length : policy.minimum;
604
- if (required > 0 && matchedResolverIds.length >= required) return PublicDnsObservation.Verified({
605
- evidence,
606
- matchedResolverIds
607
- });
608
- const unavailable = evidence.filter((observation) => observation._tag === "TimedOut" || observation._tag === "Failed").length;
609
- if (unavailable > 0 && matchedResolverIds.length + unavailable >= required) return PublicDnsObservation.Unavailable({ evidence });
610
- if (evidence.some((observation) => observation._tag === "Answer" && !answersMatch(requirement, observation.answers))) return PublicDnsObservation.Mismatch({ evidence });
611
- if (evidence.some((observation) => observation._tag === "NoData")) return PublicDnsObservation.Pending({ evidence });
612
- return PublicDnsObservation.Unavailable({ evidence });
613
- }
614
- function answersMatch(requirement, answers) {
615
- const expected = parse(requirement._tag, recordValue(requirement));
616
- return answers.some((answer) => answer.name === requirement.name && answer.type === requirement._tag && parse(requirement._tag, answer.data) === expected);
617
- }
618
- function aggregate(evidence) {
619
- const requested = [evidence.provider, evidence.publicDns].filter((observation) => observation !== null);
620
- if (requested.length === 0) return Result.NotObserved(evidence);
621
- if (requested.every((observation) => observation._tag === "Matched" || observation._tag === "Verified")) return Result.Verified(evidence);
622
- if (requested.some((observation) => observation._tag === "Unavailable")) return Result.Unavailable(evidence);
623
- if (requested.some((observation) => observation._tag === "Mismatch")) return Result.Mismatch(evidence);
624
- return Result.Pending(evidence);
625
- }
626
- function recordValue(requirement) {
627
- const data$1 = data(requirement);
628
- switch (requirement._tag) {
629
- case "A":
630
- case "AAAA": return String(data$1.address);
631
- case "CNAME":
632
- case "NS": return String(data$1.target);
633
- case "TXT": return String(data$1.value);
634
- case "MX": return `${data$1.priority} ${data$1.exchange}`;
635
- case "CAA": return `${data$1.flags} ${data$1.tag} ${data$1.value}`;
636
- case "SRV": return `${data$1.priority} ${data$1.weight} ${data$1.port} ${data$1.target}`;
637
- }
638
- }
639
- //#endregion
640
- export { selection_exports as C, manifest_exports as D, decode as E, diagnostic_exports as O, connection_authorization_exports as S, Schema$1 as T, toAsync$1 as _, Result as a, dns_data_exports as b, Observation as c, defaultMake as d, make as f, cloudflare_doh_exports as g, toAsync as h, PublicDnsObservation as i, version as k, Policy as l, google_doh_exports as m, ProviderObservation as n, observe as o, resolver_pool_exports as p, PublicDns as r, verify_exports as s, Provider as t, Service as u, doh_exports as v, Method as w, authorize as x, toAsync$2 as y };
641
-
642
- //# sourceMappingURL=verify-BKbvq7IN.mjs.map