domainkit 0.6.0 → 0.8.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/README.md +20 -18
- package/dist/{canonical-json-9x7gHIoS.mjs → canonical-json-CQYKsZw7.mjs} +10 -4
- package/dist/canonical-json-CQYKsZw7.mjs.map +1 -0
- package/dist/{connect-Db830jad.d.mts → connect-D-X8T9W8.d.mts} +305 -95
- package/dist/{connect-ks3cpqBD.mjs → connect-oI8hcMxc.mjs} +4 -4
- package/dist/connect-oI8hcMxc.mjs.map +1 -0
- package/dist/{connection-DuYDgWir.d.mts → connection-Dp6ZdSo8.d.mts} +2 -2
- package/dist/{connection-api-B__0M3PA.d.mts → connection-api-lqG1nBtD.d.mts} +2 -2
- package/dist/index.d.mts +703 -34
- package/dist/index.mjs +137 -30
- package/dist/index.mjs.map +1 -1
- package/dist/{managed-dns-connections-CaXts84E.mjs → managed-dns-connections-C3A_GBaz.mjs} +2 -2
- package/dist/{managed-dns-connections-CaXts84E.mjs.map → managed-dns-connections-C3A_GBaz.mjs.map} +1 -1
- package/dist/promise.d.mts +72 -13
- package/dist/promise.mjs +13 -8
- package/dist/promise.mjs.map +1 -1
- package/dist/{resolver-DxJPsq6l.mjs → resolver-BeGz1ukw.mjs} +132 -50
- package/dist/resolver-BeGz1ukw.mjs.map +1 -0
- package/dist/{resolver-DUAIlm2I.d.mts → resolver-xoSwyXDJ.d.mts} +889 -15
- package/dist/server.d.mts +3 -3
- package/dist/server.mjs +3 -3
- package/dist/testing.d.mts +2 -2
- package/dist/testing.mjs +5 -7
- package/dist/testing.mjs.map +1 -1
- package/dist/{verify-DAtUAEeg.mjs → verify-DvGPb5C9.mjs} +51 -45
- package/dist/verify-DvGPb5C9.mjs.map +1 -0
- package/dist/{verify-yAy-r9no.d.mts → verify-FpunAcM7.d.mts} +83 -6
- package/package.json +4 -2
- package/dist/canonical-json-9x7gHIoS.mjs.map +0 -1
- package/dist/connect-ks3cpqBD.mjs.map +0 -1
- package/dist/resolver-DxJPsq6l.mjs.map +0 -1
- package/dist/verify-DAtUAEeg.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# DomainKit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Add custom domains to a TypeScript SaaS application.
|
|
4
4
|
|
|
5
|
-
DomainKit turns DNS requirements into
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
architecture.
|
|
5
|
+
DomainKit turns DNS requirements into plans you can review, requires approval for the exact plan
|
|
6
|
+
before a write, records applied changes in receipts, and uses those receipts to plan cleanup. It
|
|
7
|
+
supports Cloudflare and Vercel without making either provider's API your product architecture.
|
|
9
8
|
|
|
10
9
|
## Install
|
|
11
10
|
|
|
@@ -22,16 +21,15 @@ import { Digest, DnsRecord, DomainName, Provisioning } from "domainkit";
|
|
|
22
21
|
import { InMemoryDnsProvider } from "domainkit/testing";
|
|
23
22
|
import { Effect, Layer } from "effect";
|
|
24
23
|
|
|
25
|
-
const requirement = DnsRecord.
|
|
26
|
-
_tag: "CNAME",
|
|
24
|
+
const requirement = DnsRecord.Cname({
|
|
27
25
|
metadata: {
|
|
28
26
|
ownership: "customer",
|
|
29
27
|
provenance: "product-onboarding",
|
|
30
28
|
purpose: "tracking",
|
|
31
29
|
},
|
|
32
|
-
name: "track.example.com",
|
|
30
|
+
name: DomainName.parse("track.example.com"),
|
|
33
31
|
policy: "exclusive",
|
|
34
|
-
target: "tracking.example.net",
|
|
32
|
+
target: DomainName.parse("tracking.example.net"),
|
|
35
33
|
ttl: 300,
|
|
36
34
|
});
|
|
37
35
|
|
|
@@ -50,23 +48,27 @@ const program = Effect.gen(function* () {
|
|
|
50
48
|
Planning is additive and fail-closed: exact records become no-ops, missing records become creates,
|
|
51
49
|
and incompatible state becomes a conflict. DomainKit never silently overwrites DNS.
|
|
52
50
|
|
|
51
|
+
Tagged values use callable case constructors such as `DnsRecord.Txt({...})` and
|
|
52
|
+
`DnsPlan.Operation.create({...})`; use the exported schemas when decoding persisted or provider
|
|
53
|
+
data.
|
|
54
|
+
|
|
53
55
|
## Public entry points
|
|
54
56
|
|
|
55
|
-
- `domainkit` —
|
|
56
|
-
- `domainkit/promise` — Promise
|
|
57
|
-
- `domainkit/server` —
|
|
58
|
-
- `domainkit/testing` — in-memory services and provider
|
|
57
|
+
- `domainkit` — Effect services, schemas, plans, providers, and verification;
|
|
58
|
+
- `domainkit/promise` — Promise API for apps that use async/await;
|
|
59
|
+
- `domainkit/server` — provider connection routes and an async Web handler factory;
|
|
60
|
+
- `domainkit/testing` — in-memory services and provider tests.
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
Your app owns provider credentials, OAuth state, saved connections, plans, receipts, authorization,
|
|
63
|
+
and audit history. DomainKit supplies the domain model and operations, not a hosted control plane.
|
|
64
|
+
Cloudflare's provider namespace includes credential refresh; the host owns refresh locking,
|
|
65
|
+
encrypted rotation, retry policy, and reconnect UX.
|
|
64
66
|
|
|
65
67
|
## Learn more
|
|
66
68
|
|
|
67
69
|
- [Executable quickstart](https://github.com/AryaLabsHQ/domainkit/blob/main/packages/domainkit/examples/effect/quickstart.ts)
|
|
68
70
|
- [Architecture decisions](https://github.com/AryaLabsHQ/domainkit/tree/main/docs/adr)
|
|
69
|
-
- [Provider behavior](https://
|
|
71
|
+
- [Provider behavior](https://domain-kit.dev/docs/reference/providers)
|
|
70
72
|
- [Examples](https://github.com/AryaLabsHQ/domainkit/tree/main/packages/domainkit/examples)
|
|
71
73
|
- [Issues](https://github.com/AryaLabsHQ/domainkit/issues)
|
|
72
74
|
|
|
@@ -199,10 +199,16 @@ const CapabilityEvidence = Schema.Struct({
|
|
|
199
199
|
capability: Capability,
|
|
200
200
|
evidence: EvidenceSchema
|
|
201
201
|
});
|
|
202
|
-
const
|
|
202
|
+
const RevocationSchema = Schema.TaggedUnion({
|
|
203
203
|
Active: {},
|
|
204
204
|
Pending: { requestedAt: Schema.DateFromString }
|
|
205
205
|
});
|
|
206
|
+
/** Revocation state schema and callable constructors for trusted lifecycle values. */
|
|
207
|
+
const Revocation = {
|
|
208
|
+
Schema: RevocationSchema,
|
|
209
|
+
Active: () => RevocationSchema.cases.Active.make({}),
|
|
210
|
+
Pending: (input) => RevocationSchema.cases.Pending.make(input)
|
|
211
|
+
};
|
|
206
212
|
/** A provider credential authorization shared by one or more organization connections. */
|
|
207
213
|
const Schema$1 = Schema.Struct({
|
|
208
214
|
authorizedById: Schema.String,
|
|
@@ -217,7 +223,7 @@ const Schema$1 = Schema.Struct({
|
|
|
217
223
|
providerContext: Envelope,
|
|
218
224
|
providerId: Schema.String,
|
|
219
225
|
requiredCapabilities: Schema.Array(Capability),
|
|
220
|
-
revocation: Revocation,
|
|
226
|
+
revocation: Revocation.Schema,
|
|
221
227
|
scopes: Schema.Array(Schema.String)
|
|
222
228
|
});
|
|
223
229
|
const decode = Effect.fn("ProviderAuthorization.decode")((input) => Schema.decodeUnknownEffect(Schema$1)(input).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message }))));
|
|
@@ -299,6 +305,6 @@ const webCryptoLayer = Layer.succeed(Crypto.Crypto, Crypto.make({
|
|
|
299
305
|
})
|
|
300
306
|
}));
|
|
301
307
|
//#endregion
|
|
302
|
-
export {
|
|
308
|
+
export { Error$2 as A, encode$2 as C, decode$3 as D, Schema$2 as E, domain_name_exports as O, decode$2 as S, validate$1 as T, ProviderTarget as _, AggregateSchema as a, assertAttachment as b, Evidence as c, codec as d, provider_context_exports as f, ProviderConnection as g, DomainAttachment as h, webCryptoLayer as i, invalid_input_exports as j, parse as k, Revocation as l, ConnectionStatus as m, sha256Encoded as n, Error$1 as o, AuthorizationError as p, stringify as r, Service as s, canonical_json_exports as t, authorization_exports as u, ProviderTargetEvidence as v, project as w, authorizationError as x, StoredConnection as y };
|
|
303
309
|
|
|
304
|
-
//# sourceMappingURL=canonical-json-
|
|
310
|
+
//# sourceMappingURL=canonical-json-CQYKsZw7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-json-CQYKsZw7.mjs","names":["Error","S","Schema","decode","InvalidInputError","S","DomainName.Schema","decode","InvalidInputError","validate","encode","DomainName.parse","InvalidInputError","decode","encode","S","Schema","ProviderContext.Envelope","InvalidInputError","ProviderAuthorization.Schema","Connection.StoredConnection","Connection.DomainAttachment","Error"],"sources":["../src/invalid-input.ts","../src/domain/domain-name.ts","../src/auth/connection.ts","../src/auth/provider-context.ts","../src/auth/authorization.ts","../src/auth/lifecycle-repository.ts","../src/plan/canonical-json.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nexport class Error extends Schema.TaggedError<Error>()(\"InvalidInputError\", {\n message: Schema.String,\n}) {}\n","import { Effect, Schema as S, SchemaIssue, SchemaTransformation } from \"effect\";\n\nimport { Error as InvalidInputError } from \"../invalid-input.ts\";\n\nconst labelPattern = /^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/;\n\nconst Type = S.String.check(\n S.makeFilter<string>(\n (value) =>\n value.length <= 253 &&\n value.includes(\".\") &&\n value.split(\".\").every((label) => labelPattern.test(label))\n ? undefined\n : \"Expected a fully qualified DNS name\",\n { identifier: \"DomainName\" },\n ),\n).pipe(S.brand(\"DomainName\"));\n\n/** A lower-case, fully qualified DNS name without a trailing dot. */\nexport type DomainName = typeof Type.Type;\n\n/** Decodes user and wire strings into canonical domain names. */\nexport const Schema = S.String.pipe(\n S.decodeTo(\n Type,\n SchemaTransformation.transformOrFail({\n decode: (input, options) =>\n Effect.try({\n try: () => normalize(input),\n catch: (cause) =>\n new SchemaIssue.InvalidValue(\n { message: cause instanceof Error ? cause.message : String(cause) },\n input,\n options,\n ),\n }),\n encode: (domain) => Effect.succeed(domain),\n }),\n ),\n);\n\nexport const decode = Effect.fn(\"DomainName.decode\")((input: unknown) =>\n S.decodeUnknownEffect(Schema)(input).pipe(\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n);\n\nexport function parse(input: unknown): DomainName {\n try {\n return S.decodeUnknownSync(Schema)(input);\n } catch (cause) {\n throw new InvalidInputError({\n message: cause instanceof Error ? cause.message : String(cause),\n });\n }\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 return labels.join(\".\");\n}\n","import { Effect, Schema as S } from \"effect\";\n\nimport * as DomainName from \"../domain/domain-name.ts\";\nimport { Error as InvalidInputError } from \"../invalid-input.ts\";\nimport type { OAuthMethod } from \"./manifest.ts\";\nimport type * as ProviderAuthorization from \"./authorization.ts\";\nimport type { Value as Secret } from \"./secret.ts\";\n\n/** A provider account and authoritative zone selected for one domain attachment. */\nexport const ProviderTargetEvidence = S.Struct({\n /** The account display name observed during discovery, when the provider exposes one. */\n accountName: S.optionalKey(S.String),\n /** Nameserver and provider-state evidence observed during discovery. */\n nameservers: S.Array(DomainName.Schema),\n status: S.String,\n /** Provider-specific authoritative-zone type, such as Cloudflare's `full` or Vercel's `external`. */\n zoneType: S.String,\n});\nexport interface ProviderTargetEvidence extends S.Schema.Type<typeof ProviderTargetEvidence> {}\n\nexport const ProviderTarget = S.Struct({\n accountId: S.String,\n accountKind: S.NullOr(S.Literals([\"account\", \"personal\", \"team\"])),\n evidence: S.optionalKey(ProviderTargetEvidence),\n zoneId: S.String,\n zoneName: DomainName.Schema,\n});\nexport interface ProviderTarget extends S.Schema.Type<typeof ProviderTarget> {}\n\n/** The lifecycle state visible to a host for an organization connection. */\nexport const ConnectionStatus = S.Literals([\"active\", \"expired\", \"revocation-pending\"]);\nexport type ConnectionStatus = typeof ConnectionStatus.Type;\n\n/** An organization-scoped provider connection. */\nexport const ProviderConnection = S.Struct({\n createdAt: S.DateFromString,\n id: S.String,\n method: S.Literals([\"integration\", \"oauth2\", \"token\"]),\n ownerId: S.String,\n providerId: S.String,\n status: ConnectionStatus,\n});\nexport interface ProviderConnection extends S.Schema.Type<typeof ProviderConnection> {}\n\n/** An exact provider target attached to one organization domain. */\nexport const DomainAttachment = S.Struct({\n connectionId: S.String,\n createdAt: S.DateFromString,\n domain: DomainName.Schema,\n id: S.String,\n target: ProviderTarget,\n});\nexport interface DomainAttachment extends S.Schema.Type<typeof DomainAttachment> {}\n\n/** Internal connection row; the authorization id is intentionally not part of the public shape. */\nexport const StoredConnection = S.Struct({\n authorizationId: S.String,\n createdAt: S.DateFromString,\n id: S.String,\n method: S.Literals([\"integration\", \"oauth2\", \"token\"]),\n ownerId: S.String,\n providerId: S.String,\n});\nexport interface StoredConnection extends S.Schema.Type<typeof StoredConnection> {}\n\n/** Internal credential material retained by the host's persistence implementation. */\nexport interface StoredCredential {\n readonly accessToken: Secret;\n readonly expiresAt: Date | null;\n readonly refreshToken: Secret | null;\n readonly tokenType: string;\n}\n\n/** The provider context carried through an interactive connection continuation. */\nexport interface OAuthContinuation {\n readonly clientId: string;\n readonly codeVerifier: Secret;\n readonly expiresAt: Date;\n readonly authorizationId?: string;\n readonly method: OAuthMethod;\n readonly ownerId: string;\n readonly redirectUri: string;\n readonly stateHash: string;\n readonly authorizedById: string;\n}\n\nexport class AuthorizationError extends S.TaggedError<AuthorizationError>()(\"AuthorizationError\", {\n category: S.Literal(\"authorization\"),\n message: S.String,\n operation: S.String,\n retry: S.Literals([\"never\", \"after-user-action\", \"safe\", \"unknown\"]),\n}) {}\n\nexport const authorizationError = (message: string, operation: string): AuthorizationError =>\n new AuthorizationError({\n category: \"authorization\",\n message,\n operation,\n retry: \"after-user-action\",\n });\n\n/** Decode a public connection snapshot returned by a host. */\nexport const decode = Effect.fn(\"ProviderConnection.decode\")((input: unknown) =>\n S.decodeUnknownEffect(ProviderConnection)(input).pipe(\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n);\n\nexport const validate = Effect.fn(\"ProviderConnection.validate\")((input: unknown) =>\n S.decodeUnknownEffect(S.toType(ProviderConnection))(input).pipe(\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n);\n\nexport const encode = S.encodeSync(ProviderConnection);\n\n/** Derive a public connection projection from its private authorization state. */\nexport function project(\n connection: StoredConnection,\n authorization: ProviderAuthorization.ProviderAuthorization,\n credential: StoredCredential,\n now = new Date(),\n): ProviderConnection {\n const status: ConnectionStatus =\n authorization.revocation._tag === \"Pending\"\n ? \"revocation-pending\"\n : credential.refreshToken === null &&\n credential.expiresAt !== null &&\n (Number.isNaN(credential.expiresAt.valueOf()) || credential.expiresAt <= now)\n ? \"expired\"\n : \"active\";\n return {\n createdAt: connection.createdAt,\n id: connection.id,\n method: connection.method,\n ownerId: connection.ownerId,\n providerId: connection.providerId,\n status,\n };\n}\n\n/** Assert that an exact attachment is usable for one DNS operation. */\nexport function assertAttachment(input: {\n readonly attachment: DomainAttachment;\n readonly authorization: ProviderAuthorization.ProviderAuthorization;\n readonly capability: ProviderAuthorization.Capability;\n readonly connection: StoredConnection | ProviderConnection;\n readonly credential?: StoredCredential;\n readonly domain: string;\n readonly now?: Date;\n readonly providerId: string;\n}): DomainName.DomainName {\n const credentialStatus =\n \"status\" in input.connection\n ? input.connection.status\n : input.credential === undefined\n ? null\n : project(input.connection, input.authorization, input.credential, input.now).status;\n if (\n input.connection.providerId !== input.providerId ||\n input.authorization.providerId !== input.providerId ||\n input.authorization.revocation._tag !== \"Active\" ||\n input.attachment.connectionId !== input.connection.id ||\n credentialStatus !== \"active\"\n ) {\n throw authorizationError(\n \"Domain attachment is not active for this provider\",\n \"Connection.assertAttachment\",\n );\n }\n if (!input.authorization.requiredCapabilities.includes(input.capability)) {\n throw authorizationError(\n `Provider authorization lacks the ${input.capability} capability`,\n \"Connection.assertAttachment\",\n );\n }\n if (\n !input.authorization.capabilityEvidence.some((item) => item.capability === input.capability)\n ) {\n throw authorizationError(\n `Provider authorization has no evidence for the ${input.capability} capability`,\n \"Connection.assertAttachment\",\n );\n }\n let domain: DomainName.DomainName;\n try {\n domain = DomainName.parse(input.domain);\n } catch (cause) {\n if (cause instanceof InvalidInputError) throw cause;\n throw new InvalidInputError({\n message: cause instanceof Error ? cause.message : String(cause),\n });\n }\n if (input.attachment.domain !== domain && !domain.endsWith(`.${input.attachment.domain}`)) {\n throw authorizationError(\n \"Domain attachment does not match the requested domain\",\n \"Connection.assertAttachment\",\n );\n }\n return domain;\n}\n","import { Effect, Schema } from \"effect\";\n\nimport { Error as InvalidInputError } from \"../invalid-input.ts\";\n\n/** A provider-owned, versioned, non-secret context value persisted by the host. */\nexport const Envelope = Schema.Struct({\n value: Schema.Json,\n version: Schema.String,\n});\nexport interface Envelope extends Schema.Schema.Type<typeof Envelope> {}\n\nexport interface Codec<A> {\n readonly decode: (envelope: Envelope) => Effect.Effect<A, InvalidInputError>;\n readonly encode: (value: A) => Effect.Effect<Envelope, InvalidInputError>;\n readonly version: string;\n}\n\n/** Build an adapter-owned context codec from a schema and stable version identifier. */\nexport function codec<A, I>(version: string, schema: Schema.Codec<A, I>): Codec<A> {\n return {\n decode: Effect.fn(\"ProviderContext.decode\")((envelope) =>\n envelope.version !== version\n ? Effect.fail(\n new InvalidInputError({\n message: `Unsupported provider context version: ${envelope.version}`,\n }),\n )\n : Schema.decodeUnknownEffect(schema)(envelope.value).pipe(\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n ),\n encode: Effect.fn(\"ProviderContext.encode\")((value) =>\n Schema.encodeEffect(schema)(value).pipe(\n Effect.flatMap((encoded) => Schema.decodeUnknownEffect(Schema.Json)(encoded)),\n Effect.map((encoded) => ({ value: encoded, version })),\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n ),\n version,\n };\n}\n\nexport const decode = Effect.fn(\"ProviderContext.Envelope.decode\")((input: unknown) =>\n Schema.decodeUnknownEffect(Envelope)(input).pipe(\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n);\n\nexport const encode = Schema.encodeSync(Envelope);\n","import { Data, Effect, Schema as S } from \"effect\";\n\nimport { Error as InvalidInputError } from \"../invalid-input.ts\";\nimport * as ProviderContext from \"./provider-context.ts\";\n\nexport const Capability = S.Literals([\"dns:read\", \"dns:write\"]);\nexport type Capability = typeof Capability.Type;\n\nexport type Evidence = Data.TaggedEnum<{\n Declared: {};\n Exercised: { readonly observedAt: Date };\n Introspected: { readonly observedAt: Date };\n}>;\nexport const Evidence = Data.taggedEnum<Evidence>();\n\nexport const EvidenceSchema = S.TaggedUnion({\n Declared: {},\n Exercised: { observedAt: S.DateFromString },\n Introspected: { observedAt: S.DateFromString },\n});\n\nexport const CapabilityEvidence = S.Struct({\n capability: Capability,\n evidence: EvidenceSchema,\n});\nexport interface CapabilityEvidence extends S.Schema.Type<typeof CapabilityEvidence> {}\n\nconst RevocationSchema = S.TaggedUnion({\n Active: {},\n Pending: { requestedAt: S.DateFromString },\n});\n/** Revocation state schema and callable constructors for trusted lifecycle values. */\nexport const Revocation = {\n Schema: RevocationSchema,\n Active: () => RevocationSchema.cases.Active.make({}),\n Pending: (input: Parameters<typeof RevocationSchema.cases.Pending.make>[0]) =>\n RevocationSchema.cases.Pending.make(input),\n};\nexport type Revocation = typeof RevocationSchema.Type;\n\n/** A provider credential authorization shared by one or more organization connections. */\nexport const Schema = S.Struct({\n authorizedById: S.String,\n capabilityEvidence: S.Array(CapabilityEvidence),\n createdAt: S.DateFromString,\n id: S.String,\n method: S.Literals([\"integration\", \"oauth2\", \"token\"]),\n providerContext: ProviderContext.Envelope,\n providerId: S.String,\n requiredCapabilities: S.Array(Capability),\n revocation: Revocation.Schema,\n scopes: S.Array(S.String),\n});\nexport interface ProviderAuthorization extends S.Schema.Type<typeof Schema> {}\n\nexport const decode = Effect.fn(\"ProviderAuthorization.decode\")((input: unknown) =>\n S.decodeUnknownEffect(Schema)(input).pipe(\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n);\n\nexport const validate = Effect.fn(\"ProviderAuthorization.validate\")((input: unknown) =>\n S.decodeUnknownEffect(S.toType(Schema))(input).pipe(\n Effect.mapError((cause) => new InvalidInputError({ message: cause.message })),\n ),\n);\n\nexport const encode = S.encodeSync(Schema);\n\nexport function evidenceFor(\n authorization: ProviderAuthorization,\n capability: Capability,\n): Evidence | undefined {\n return authorization.capabilityEvidence.find((item) => item.capability === capability)?.evidence;\n}\n","import { Context, Effect, Schema } from \"effect\";\n\nimport * as ProviderAuthorization from \"./authorization.ts\";\nimport * as Connection from \"./connection.ts\";\n\n/** Private aggregate owned by the managed-DNS persistence capability. */\nexport interface Aggregate {\n readonly authorization: ProviderAuthorization.ProviderAuthorization;\n readonly connections: ReadonlyArray<Connection.StoredConnection>;\n readonly attachments: ReadonlyArray<Connection.DomainAttachment>;\n readonly credential: Connection.StoredCredential;\n}\n\n/** Serializable durable state. Credential material is deliberately sealed separately. */\nexport const AggregateSchema = Schema.Struct({\n authorization: ProviderAuthorization.Schema,\n connections: Schema.Array(Connection.StoredConnection),\n attachments: Schema.Array(Connection.DomainAttachment),\n});\n\nexport interface ConnectInput {\n readonly authorization: ProviderAuthorization.ProviderAuthorization;\n readonly connection: Connection.StoredConnection;\n readonly credential: Connection.StoredCredential;\n /** The authorization id observed before building a reuse update, if any. */\n readonly expectedAuthorizationId?: string;\n /** The owner connection id observed before building a reuse update, if any. */\n readonly expectedConnectionId?: string;\n}\n\nexport interface AttachmentResult {\n readonly attachment: Connection.DomainAttachment;\n readonly connection: Connection.ProviderConnection;\n}\n\nexport interface DetachResult {\n readonly attachment: Connection.DomainAttachment;\n readonly connection: Connection.ProviderConnection;\n readonly remainingAttachments: number;\n}\n\nexport interface DisconnectResult {\n readonly connection: Connection.ProviderConnection;\n readonly remainingConnections: number;\n readonly revokedAuthorization: boolean;\n}\n\nexport class Error extends Schema.TaggedError<Error>()(\"ManagedDnsLifecycleError\", {\n category: Schema.Literal(\"storage\"),\n message: Schema.String,\n operation: Schema.String,\n retry: Schema.Literals([\"never\", \"after-user-action\", \"safe\", \"unknown\"]),\n}) {}\n\n/**\n * Persistence capability for the managed-DNS model.\n *\n * Implementations own the atomic aggregate containing one provider credential authorization,\n * organization connections, and exact domain attachments. Provider authorization is deliberately\n * an implementation detail of the capability; public callers operate on the projections returned\n * by the connection and attachment methods.\n */\nexport interface Interface {\n readonly attach: (input: {\n readonly attachment: Connection.DomainAttachment;\n readonly connectionId: string;\n readonly ownerId: string;\n }) => Effect.Effect<AttachmentResult, Error>;\n readonly connect: (input: ConnectInput) => Effect.Effect<Aggregate, Error>;\n readonly detach: (input: {\n readonly attachmentId: string;\n readonly ownerId: string;\n }) => Effect.Effect<DetachResult, Error>;\n readonly disconnect: <E>(input: {\n readonly connectionId: string;\n readonly ownerId: string;\n readonly revoke: (\n authorization: ProviderAuthorization.ProviderAuthorization,\n ) => Effect.Effect<void, E>;\n }) => Effect.Effect<DisconnectResult, Error | E>;\n readonly findConnection: (\n ownerId: string,\n authorizationId: string,\n ) => Effect.Effect<Connection.StoredConnection | null, Error>;\n readonly get: (authorizationId: string) => Effect.Effect<Aggregate | null, Error>;\n readonly getAttachment: (\n attachmentId: string,\n ) => Effect.Effect<Connection.DomainAttachment | null, Error>;\n readonly getByConnectionId: (connectionId: string) => Effect.Effect<Aggregate | null, Error>;\n readonly listAttachments: (\n connectionId: string,\n ownerId: string,\n ) => Effect.Effect<ReadonlyArray<Connection.DomainAttachment>, Error>;\n readonly promoteEvidence: (\n authorizationId: string,\n evidence: ReadonlyArray<ProviderAuthorization.CapabilityEvidence>,\n ) => Effect.Effect<Aggregate, Error>;\n readonly recover: <E>(input: {\n readonly authorizationId: string;\n readonly revoke: (\n authorization: ProviderAuthorization.ProviderAuthorization,\n ) => Effect.Effect<void, E>;\n }) => Effect.Effect<DisconnectResult, Error | E>;\n readonly rotate: (\n authorizationId: string,\n credential: Connection.StoredCredential,\n ) => Effect.Effect<Aggregate, Error>;\n}\n\nexport class Service extends Context.Service<Service, Interface>()(\n \"@domainkit/ManagedDnsConnections\",\n) {}\n","import { Crypto, Effect, Layer, PlatformError, Schema } from \"effect\";\n\nexport class CryptoError extends Schema.TaggedError<CryptoError>()(\"CryptoError\", {\n message: Schema.String,\n}) {}\n\nexport type Json =\n | null\n | boolean\n | number\n | string\n | ReadonlyArray<Json>\n | { readonly [key: string]: Json };\n\n/** Deterministic JSON serialization for already schema-encoded protocol values. */\nexport function stringify(value: Json): string {\n if (value === null || typeof value !== \"object\") {\n const encoded = JSON.stringify(value);\n if (encoded === undefined) throw new TypeError(\"Value is not representable as JSON\");\n return encoded;\n }\n if (isJsonArray(value)) return `[${value.map(stringify).join(\",\")}]`;\n return `{${Object.entries(value)\n .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))\n .map(([key, entry]) => `${JSON.stringify(key)}:${stringify(entry)}`)\n .join(\",\")}}`;\n}\n\nfunction isJsonArray(value: Json): value is ReadonlyArray<Json> {\n return Array.isArray(value);\n}\n\nexport const sha256Text = Effect.fn(\"Digest.sha256Text\")(function* (value: string) {\n const cryptoService = yield* Crypto.Crypto;\n const digest = yield* cryptoService\n .digest(\"SHA-256\", new TextEncoder().encode(value))\n .pipe(Effect.mapError((cause) => new CryptoError({ message: cause.message })));\n return [...digest].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n});\n\nexport const sha256Json = Effect.fn(\"Digest.sha256Json\")((value: Json) =>\n Effect.try({\n try: () => stringify(value),\n catch: (cause) =>\n new CryptoError({ message: cause instanceof Error ? cause.message : String(cause) }),\n }).pipe(Effect.flatMap(sha256Text)),\n);\n\nfunction sha256EncodedProgram<S extends Schema.Constraint>(\n schema: S,\n value: S[\"Type\"],\n): Effect.Effect<string, CryptoError, Crypto.Crypto | S[\"EncodingServices\"]> {\n return Schema.encodeEffect(schema)(value).pipe(\n Effect.mapError((cause) => new CryptoError({ message: cause.message })),\n Effect.flatMap(Schema.decodeUnknownEffect(Schema.Json)),\n Effect.mapError((cause) => new CryptoError({ message: cause.message })),\n Effect.flatMap(sha256Json),\n );\n}\n\nexport const sha256Encoded = Effect.fn(\"Digest.sha256Encoded\")(sha256EncodedProgram);\n\n/** Portable Web Crypto implementation for hosts that want a ready-made Layer. */\nexport const webCryptoLayer: Layer.Layer<Crypto.Crypto> = Layer.succeed(\n Crypto.Crypto,\n Crypto.make({\n randomBytes: (size) => crypto.getRandomValues(new Uint8Array(size)),\n digest: (algorithm, data) =>\n Effect.tryPromise({\n try: async () => {\n const bytes = new Uint8Array(data.byteLength);\n bytes.set(data);\n return new Uint8Array(await crypto.subtle.digest(algorithm, bytes.buffer));\n },\n catch: (cause) =>\n PlatformError.systemError({\n _tag: \"Unknown\",\n module: \"WebCrypto\",\n method: \"digest\",\n cause,\n }),\n }),\n }),\n);\n"],"mappings":"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"}
|