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,225 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { decode } from "./DomainName.mjs";
|
|
3
|
+
import { Unauthenticated, Unsupported } from "./Reason.mjs";
|
|
4
|
+
import { fail } from "./internal/error.mjs";
|
|
5
|
+
import { authorizationUrl, exchangeCode, refresh, revoke } from "./internal/oauth.mjs";
|
|
6
|
+
import { make, resolveAmong, tokenAuth } from "./Provider.mjs";
|
|
7
|
+
import { dns, listZones, provider as provider$1, tokenExpiry, verifyToken } from "./internal/cloudflare/client.mjs";
|
|
8
|
+
import { resolve } from "./internal/config.mjs";
|
|
9
|
+
import { Effect, Redacted, Schema } from "effect";
|
|
10
|
+
//#region src/Cloudflare.ts
|
|
11
|
+
/** Cloudflare: personal API tokens and OAuth. */
|
|
12
|
+
var Cloudflare_exports = /* @__PURE__ */ __exportAll({
|
|
13
|
+
AccountContext: () => AccountContext,
|
|
14
|
+
TokenFields: () => TokenFields,
|
|
15
|
+
provider: () => provider,
|
|
16
|
+
server: () => server
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Authorization context: `accountId` is `null` when the credential spans several accounts or
|
|
20
|
+
* none yet. Target context: the zone's account and zone id.
|
|
21
|
+
*/
|
|
22
|
+
const AccountContext = Schema.Struct({
|
|
23
|
+
accountId: Schema.NullOr(Schema.String),
|
|
24
|
+
/** How the token was verified: user tokens span accounts, account tokens are pinned. */
|
|
25
|
+
tokenKind: Schema.optionalKey(Schema.Literals(["user", "account"])),
|
|
26
|
+
zoneId: Schema.optionalKey(Schema.String)
|
|
27
|
+
});
|
|
28
|
+
/** Token-method input: the API token, and the account id for account-owned tokens. */
|
|
29
|
+
const TokenFields = Schema.Struct({
|
|
30
|
+
token: Schema.RedactedFromValue(Schema.String),
|
|
31
|
+
accountId: Schema.optionalKey(Schema.String)
|
|
32
|
+
});
|
|
33
|
+
const server = {
|
|
34
|
+
authorization_endpoint: "https://dash.cloudflare.com/oauth2/auth",
|
|
35
|
+
issuer: "https://dash.cloudflare.com",
|
|
36
|
+
revocation_endpoint: "https://dash.cloudflare.com/oauth2/revoke",
|
|
37
|
+
token_endpoint: "https://dash.cloudflare.com/oauth2/token"
|
|
38
|
+
};
|
|
39
|
+
const defaultScopes = [
|
|
40
|
+
"zone:read",
|
|
41
|
+
"dns_records:edit",
|
|
42
|
+
"offline_access"
|
|
43
|
+
];
|
|
44
|
+
const capabilities = ["dns:read", "dns:write"];
|
|
45
|
+
/** OAuth credentials pack both tokens into `secret`; token credentials are the token itself. */
|
|
46
|
+
const Secret = Schema.fromJsonString(Schema.Struct({
|
|
47
|
+
accessToken: Schema.String,
|
|
48
|
+
refreshToken: Schema.NullOr(Schema.String)
|
|
49
|
+
}));
|
|
50
|
+
const parseSecret = (secret) => {
|
|
51
|
+
const raw = Redacted.value(secret);
|
|
52
|
+
const parsed = raw.startsWith("{") ? Schema.decodeUnknownOption(Secret)(raw) : void 0;
|
|
53
|
+
return parsed !== void 0 && parsed._tag === "Some" ? parsed.value : {
|
|
54
|
+
accessToken: raw,
|
|
55
|
+
refreshToken: null
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const packSecret = (tokens) => Redacted.make(Schema.encodeSync(Secret)({
|
|
59
|
+
accessToken: tokens.accessToken,
|
|
60
|
+
refreshToken: tokens.refreshToken
|
|
61
|
+
}));
|
|
62
|
+
const provider = (options = {}) => {
|
|
63
|
+
const fetch = options.fetch ?? globalThis.fetch;
|
|
64
|
+
const baseUrl = (options.baseUrl ?? "https://api.cloudflare.com/client/v4").replace(/\/$/, "");
|
|
65
|
+
const client = (token) => ({
|
|
66
|
+
token,
|
|
67
|
+
fetch,
|
|
68
|
+
baseUrl
|
|
69
|
+
});
|
|
70
|
+
const discoverAccount = (token) => listZones(client(token)).pipe(Effect.map((zones) => {
|
|
71
|
+
const accounts = new Set(zones.map((zone) => zone.account.id));
|
|
72
|
+
const [only] = accounts;
|
|
73
|
+
return accounts.size === 1 && only !== void 0 ? only : null;
|
|
74
|
+
}));
|
|
75
|
+
const targetOf = (zone) => ({
|
|
76
|
+
zone: zone.name,
|
|
77
|
+
context: {
|
|
78
|
+
accountId: zone.account.id,
|
|
79
|
+
zoneId: zone.id
|
|
80
|
+
},
|
|
81
|
+
label: `${zone.name} (${zone.account.name})`,
|
|
82
|
+
nameservers: zone.name_servers ?? []
|
|
83
|
+
});
|
|
84
|
+
const oauthClient = (oauth) => Effect.gen(function* () {
|
|
85
|
+
return {
|
|
86
|
+
clientId: yield* resolve(oauth.clientId, "oauth.clientId"),
|
|
87
|
+
clientSecret: yield* resolve(oauth.clientSecret, "oauth.clientSecret"),
|
|
88
|
+
clientAuth: oauth.clientAuth ?? "client_secret_basic"
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
const issued = (tokens) => discoverAccount(tokens.accessToken).pipe(Effect.map((accountId) => ({
|
|
92
|
+
secret: packSecret(tokens),
|
|
93
|
+
context: { accountId },
|
|
94
|
+
expiresAt: tokens.expiresAt
|
|
95
|
+
})));
|
|
96
|
+
const oauth = options.oauth === void 0 ? void 0 : oauthAuth(options.oauth);
|
|
97
|
+
function oauthAuth(settings) {
|
|
98
|
+
const scopes = settings.scopes ?? defaultScopes;
|
|
99
|
+
return {
|
|
100
|
+
label: "Sign in with Cloudflare",
|
|
101
|
+
scopes,
|
|
102
|
+
start: (input) => oauthClient(settings).pipe(Effect.map(({ clientId }) => ({ authorizationUrl: authorizationUrl({
|
|
103
|
+
server,
|
|
104
|
+
clientId,
|
|
105
|
+
scopes,
|
|
106
|
+
state: input.state,
|
|
107
|
+
callbackUrl: input.callbackUrl,
|
|
108
|
+
codeChallenge: input.codeChallenge
|
|
109
|
+
}) }))),
|
|
110
|
+
complete: (input) => oauthClient(settings).pipe(Effect.flatMap((oauthClientValue) => exchangeCode({
|
|
111
|
+
provider: provider$1,
|
|
112
|
+
server,
|
|
113
|
+
client: oauthClientValue,
|
|
114
|
+
code: input.code,
|
|
115
|
+
state: input.params.state ?? "",
|
|
116
|
+
callbackUrl: input.callbackUrl,
|
|
117
|
+
codeVerifier: input.codeVerifier,
|
|
118
|
+
fetch
|
|
119
|
+
})), Effect.flatMap(issued)),
|
|
120
|
+
refresh: (credential) => Effect.gen(function* () {
|
|
121
|
+
const { refreshToken } = parseSecret(credential.secret);
|
|
122
|
+
if (refreshToken === null) return yield* fail(new Unauthenticated({ message: "Cloudflare credential has no refresh token" }));
|
|
123
|
+
const tokens = yield* refresh({
|
|
124
|
+
provider: provider$1,
|
|
125
|
+
server,
|
|
126
|
+
client: yield* oauthClient(settings),
|
|
127
|
+
refreshToken,
|
|
128
|
+
fetch
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
secret: packSecret(tokens),
|
|
132
|
+
context: credential.context,
|
|
133
|
+
expiresAt: tokens.expiresAt
|
|
134
|
+
};
|
|
135
|
+
}),
|
|
136
|
+
revoke: (credential) => Effect.gen(function* () {
|
|
137
|
+
const { accessToken } = parseSecret(credential.secret);
|
|
138
|
+
yield* revoke({
|
|
139
|
+
provider: provider$1,
|
|
140
|
+
server,
|
|
141
|
+
client: yield* oauthClient(settings),
|
|
142
|
+
token: accessToken,
|
|
143
|
+
fetch
|
|
144
|
+
});
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return make({
|
|
149
|
+
id: "cloudflare",
|
|
150
|
+
name: "Cloudflare",
|
|
151
|
+
context: AccountContext,
|
|
152
|
+
contextVersion: "cloudflare.v1",
|
|
153
|
+
auth: {
|
|
154
|
+
token: tokenAuth({
|
|
155
|
+
label: "API token",
|
|
156
|
+
docsUrl: "https://developers.cloudflare.com/fundamentals/api/get-started/create-token/",
|
|
157
|
+
requiredCapabilities: capabilities,
|
|
158
|
+
fields: TokenFields,
|
|
159
|
+
authenticate: ({ token, accountId }) => Effect.gen(function* () {
|
|
160
|
+
const raw = Redacted.value(token);
|
|
161
|
+
if (accountId !== void 0) {
|
|
162
|
+
const expiresAt = yield* verifyToken(client(raw), `/accounts/${encodeURIComponent(accountId)}/tokens/verify`);
|
|
163
|
+
return {
|
|
164
|
+
secret: token,
|
|
165
|
+
context: {
|
|
166
|
+
accountId,
|
|
167
|
+
tokenKind: "account"
|
|
168
|
+
},
|
|
169
|
+
expiresAt
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const discovered = yield* discoverAccount(raw);
|
|
173
|
+
const verified = yield* tokenExpiry(client(raw), discovered);
|
|
174
|
+
return {
|
|
175
|
+
secret: token,
|
|
176
|
+
context: {
|
|
177
|
+
accountId: discovered,
|
|
178
|
+
tokenKind: verified.kind
|
|
179
|
+
},
|
|
180
|
+
expiresAt: verified.expiresAt
|
|
181
|
+
};
|
|
182
|
+
})
|
|
183
|
+
}),
|
|
184
|
+
...oauth === void 0 ? {} : { oauth }
|
|
185
|
+
},
|
|
186
|
+
session: (credential) => {
|
|
187
|
+
const { accessToken } = parseSecret(credential.secret);
|
|
188
|
+
const clientOptions = client(accessToken);
|
|
189
|
+
const context = Schema.decodeUnknownOption(AccountContext)(credential.context);
|
|
190
|
+
const accountId = context._tag === "Some" ? context.value.accountId ?? void 0 : void 0;
|
|
191
|
+
const listTargets = () => listZones(clientOptions, accountId).pipe(Effect.map((zones) => zones.map(targetOf)));
|
|
192
|
+
return {
|
|
193
|
+
capabilities: () => Effect.succeed(capabilities),
|
|
194
|
+
listTargets,
|
|
195
|
+
resolveTarget: (domain) => Effect.gen(function* () {
|
|
196
|
+
const name = yield* decode(domain);
|
|
197
|
+
const targets = yield* listTargets();
|
|
198
|
+
return resolveAmong(name, targets);
|
|
199
|
+
}),
|
|
200
|
+
dns: (target) => {
|
|
201
|
+
const zone = Schema.decodeUnknownOption(AccountContext)(target.context);
|
|
202
|
+
const zoneId = zone._tag === "Some" ? zone.value.zoneId : void 0;
|
|
203
|
+
if (zoneId === void 0) {
|
|
204
|
+
const failure = fail(new Unsupported({
|
|
205
|
+
provider: "cloudflare",
|
|
206
|
+
operation: "dns",
|
|
207
|
+
message: "Cloudflare target has no zone id; only zone targets host records"
|
|
208
|
+
}));
|
|
209
|
+
return {
|
|
210
|
+
list: () => failure,
|
|
211
|
+
create: () => failure,
|
|
212
|
+
get: () => failure,
|
|
213
|
+
delete: () => failure
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return dns(clientOptions, zoneId);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
//#endregion
|
|
223
|
+
export { AccountContext, Cloudflare_exports, TokenFields, provider, server };
|
|
224
|
+
|
|
225
|
+
//# sourceMappingURL=Cloudflare.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cloudflare.mjs","names":["Client.listZones","OAuth.authorizationUrl","OAuth.exchangeCode","Client.provider","Errors.fail","Reason.Unauthenticated","OAuth.refresh","OAuth.revoke","Provider.make","Provider.tokenAuth","Client.verifyToken","Client.tokenExpiry","DomainName.decode","Provider.resolveAmong","Reason.Unsupported","Client.dns"],"sources":["../src/Cloudflare.ts"],"sourcesContent":["/** Cloudflare: personal API tokens and OAuth. */\nimport { type Config, Effect, Redacted, Schema } from \"effect\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\nimport * as DomainName from \"./DomainName.ts\";\nimport * as Client from \"./internal/cloudflare/client.ts\";\nimport type * as Protocol from \"./internal/cloudflare/protocol.ts\";\nimport { resolve } from \"./internal/config.ts\";\nimport type { Fetch } from \"./internal/http.ts\";\nimport * as OAuth from \"./internal/oauth.ts\";\nimport * as Provider from \"./Provider.ts\";\n\n/**\n * Authorization context: `accountId` is `null` when the credential spans several accounts or\n * none yet. Target context: the zone's account and zone id.\n */\nexport const AccountContext = Schema.Struct({\n accountId: Schema.NullOr(Schema.String),\n /** How the token was verified: user tokens span accounts, account tokens are pinned. */\n tokenKind: Schema.optionalKey(Schema.Literals([\"user\", \"account\"])),\n zoneId: Schema.optionalKey(Schema.String),\n});\n\n/** Token-method input: the API token, and the account id for account-owned tokens. */\nexport const TokenFields = Schema.Struct({\n token: Schema.RedactedFromValue(Schema.String),\n accountId: Schema.optionalKey(Schema.String),\n});\nexport type AccountContext = typeof AccountContext.Type;\n\nexport interface Options {\n /** Omit to offer tokens only. */\n readonly oauth?: {\n readonly clientId: string | Config.Config<string>;\n readonly clientSecret: Redacted.Redacted<string> | Config.Config<Redacted.Redacted<string>>;\n /** Scope ids assigned to the OAuth client. Default: `zone:read`, `dns_records:edit`, `offline_access`. */\n readonly scopes?: ReadonlyArray<string>;\n /** Default `client_secret_basic`. */\n readonly clientAuth?: OAuth.ClientAuth;\n };\n readonly fetch?: Fetch;\n readonly baseUrl?: string;\n}\n\nexport const server: OAuth.Server = {\n authorization_endpoint: \"https://dash.cloudflare.com/oauth2/auth\",\n issuer: \"https://dash.cloudflare.com\",\n revocation_endpoint: \"https://dash.cloudflare.com/oauth2/revoke\",\n token_endpoint: \"https://dash.cloudflare.com/oauth2/token\",\n};\n\nconst defaultScopes = [\"zone:read\", \"dns_records:edit\", \"offline_access\"];\nconst capabilities = [\"dns:read\", \"dns:write\"] as const;\n\n/** OAuth credentials pack both tokens into `secret`; token credentials are the token itself. */\nconst Secret = Schema.fromJsonString(\n Schema.Struct({ accessToken: Schema.String, refreshToken: Schema.NullOr(Schema.String) }),\n);\n\nconst parseSecret = (secret: Redacted.Redacted<string>) => {\n const raw = Redacted.value(secret);\n const parsed = raw.startsWith(\"{\") ? Schema.decodeUnknownOption(Secret)(raw) : undefined;\n return parsed !== undefined && parsed._tag === \"Some\"\n ? parsed.value\n : { accessToken: raw, refreshToken: null };\n};\n\nconst packSecret = (tokens: OAuth.Tokens) =>\n Redacted.make(\n Schema.encodeSync(Secret)({\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n }),\n );\n\nexport const provider = (options: Options = {}): Provider.Definition<AccountContext> => {\n const fetch = options.fetch ?? globalThis.fetch;\n const baseUrl = (options.baseUrl ?? \"https://api.cloudflare.com/client/v4\").replace(/\\/$/, \"\");\n const client = (token: string): Client.Options => ({ token, fetch, baseUrl });\n\n const discoverAccount = (token: string) =>\n Client.listZones(client(token)).pipe(\n Effect.map((zones) => {\n const accounts = new Set(zones.map((zone) => zone.account.id));\n const [only] = accounts;\n return accounts.size === 1 && only !== undefined ? only : null;\n }),\n );\n\n const targetOf = (zone: Protocol.Zone): Provider.Target => ({\n zone: zone.name,\n context: { accountId: zone.account.id, zoneId: zone.id } satisfies AccountContext,\n label: `${zone.name} (${zone.account.name})`,\n nameservers: zone.name_servers ?? [],\n });\n\n const oauthClient = (oauth: NonNullable<Options[\"oauth\"]>) =>\n Effect.gen(function* () {\n const clientId = yield* resolve(oauth.clientId, \"oauth.clientId\");\n const clientSecret = yield* resolve(oauth.clientSecret, \"oauth.clientSecret\");\n return {\n clientId,\n clientSecret,\n clientAuth: oauth.clientAuth ?? \"client_secret_basic\",\n } satisfies OAuth.Client;\n });\n\n const issued = (\n tokens: OAuth.Tokens,\n ): Effect.Effect<Provider.IssuedCredential, Errors.DomainKitError> =>\n discoverAccount(tokens.accessToken).pipe(\n Effect.map((accountId) => ({\n secret: packSecret(tokens),\n context: { accountId } satisfies AccountContext,\n expiresAt: tokens.expiresAt,\n })),\n );\n\n const oauth = options.oauth === undefined ? undefined : oauthAuth(options.oauth);\n\n function oauthAuth(settings: NonNullable<Options[\"oauth\"]>): Provider.OAuthAuth {\n const scopes = settings.scopes ?? defaultScopes;\n return {\n label: \"Sign in with Cloudflare\",\n scopes,\n start: (input) =>\n oauthClient(settings).pipe(\n Effect.map(({ clientId }) => ({\n authorizationUrl: OAuth.authorizationUrl({\n server,\n clientId,\n scopes,\n state: input.state,\n callbackUrl: input.callbackUrl,\n codeChallenge: input.codeChallenge,\n }),\n })),\n ),\n complete: (input) =>\n oauthClient(settings).pipe(\n Effect.flatMap((oauthClientValue) =>\n OAuth.exchangeCode({\n provider: Client.provider,\n server,\n client: oauthClientValue,\n code: input.code,\n state: input.params.state ?? \"\",\n callbackUrl: input.callbackUrl,\n codeVerifier: input.codeVerifier,\n fetch,\n }),\n ),\n Effect.flatMap(issued),\n ),\n refresh: (credential) =>\n Effect.gen(function* () {\n const { refreshToken } = parseSecret(credential.secret);\n if (refreshToken === null) {\n return yield* Errors.fail(\n new Reason.Unauthenticated({\n message: \"Cloudflare credential has no refresh token\",\n }),\n );\n }\n const tokens = yield* OAuth.refresh({\n provider: Client.provider,\n server,\n client: yield* oauthClient(settings),\n refreshToken,\n fetch,\n });\n return {\n secret: packSecret(tokens),\n context: credential.context,\n expiresAt: tokens.expiresAt,\n };\n }),\n revoke: (credential) =>\n Effect.gen(function* () {\n const { accessToken } = parseSecret(credential.secret);\n yield* OAuth.revoke({\n provider: Client.provider,\n server,\n client: yield* oauthClient(settings),\n token: accessToken,\n fetch,\n });\n }),\n };\n }\n\n return Provider.make<AccountContext>({\n id: \"cloudflare\",\n name: \"Cloudflare\",\n context: AccountContext,\n contextVersion: \"cloudflare.v1\",\n auth: {\n token: Provider.tokenAuth({\n label: \"API token\",\n docsUrl: \"https://developers.cloudflare.com/fundamentals/api/get-started/create-token/\",\n requiredCapabilities: capabilities,\n fields: TokenFields,\n authenticate: ({ token, accountId }) =>\n Effect.gen(function* () {\n const raw = Redacted.value(token);\n if (accountId !== undefined) {\n const expiresAt = yield* Client.verifyToken(\n client(raw),\n `/accounts/${encodeURIComponent(accountId)}/tokens/verify`,\n );\n return {\n secret: token,\n context: { accountId, tokenKind: \"account\" } satisfies AccountContext,\n expiresAt,\n };\n }\n const discovered = yield* discoverAccount(raw);\n const verified = yield* Client.tokenExpiry(client(raw), discovered);\n return {\n secret: token,\n context: { accountId: discovered, tokenKind: verified.kind } satisfies AccountContext,\n expiresAt: verified.expiresAt,\n };\n }),\n }),\n ...(oauth === undefined ? {} : { oauth }),\n },\n session: (credential) => {\n const { accessToken } = parseSecret(credential.secret);\n const clientOptions = client(accessToken);\n const context = Schema.decodeUnknownOption(AccountContext)(credential.context);\n const accountId =\n context._tag === \"Some\" ? (context.value.accountId ?? undefined) : undefined;\n const listTargets = () =>\n Client.listZones(clientOptions, accountId).pipe(Effect.map((zones) => zones.map(targetOf)));\n return {\n capabilities: () => Effect.succeed(capabilities),\n listTargets,\n resolveTarget: (domain) =>\n Effect.gen(function* () {\n const name = yield* DomainName.decode(domain);\n const targets = yield* listTargets();\n return Provider.resolveAmong(name, targets);\n }),\n dns: (target) => {\n const zone = Schema.decodeUnknownOption(AccountContext)(target.context);\n const zoneId = zone._tag === \"Some\" ? zone.value.zoneId : undefined;\n if (zoneId === undefined) {\n const failure = Errors.fail(\n new Reason.Unsupported({\n provider: \"cloudflare\",\n operation: \"dns\",\n message: \"Cloudflare target has no zone id; only zone targets host records\",\n }),\n );\n return {\n list: () => failure,\n create: () => failure,\n get: () => failure,\n delete: () => failure,\n };\n }\n return Client.dns(clientOptions, zoneId);\n },\n };\n },\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAiBA,MAAa,iBAAiB,OAAO,OAAO;CAC1C,WAAW,OAAO,OAAO,OAAO,MAAM;;CAEtC,WAAW,OAAO,YAAY,OAAO,SAAS,CAAC,QAAQ,SAAS,CAAC,CAAC;CAClE,QAAQ,OAAO,YAAY,OAAO,MAAM;AAC1C,CAAC;;AAGD,MAAa,cAAc,OAAO,OAAO;CACvC,OAAO,OAAO,kBAAkB,OAAO,MAAM;CAC7C,WAAW,OAAO,YAAY,OAAO,MAAM;AAC7C,CAAC;AAiBD,MAAa,SAAuB;CAClC,wBAAwB;CACxB,QAAQ;CACR,qBAAqB;CACrB,gBAAgB;AAClB;AAEA,MAAM,gBAAgB;CAAC;CAAa;CAAoB;AAAgB;AACxE,MAAM,eAAe,CAAC,YAAY,WAAW;;AAG7C,MAAM,SAAS,OAAO,eACpB,OAAO,OAAO;CAAE,aAAa,OAAO;CAAQ,cAAc,OAAO,OAAO,OAAO,MAAM;AAAE,CAAC,CAC1F;AAEA,MAAM,eAAe,WAAsC;CACzD,MAAM,MAAM,SAAS,MAAM,MAAM;CACjC,MAAM,SAAS,IAAI,WAAW,GAAG,IAAI,OAAO,oBAAoB,MAAM,CAAC,CAAC,GAAG,IAAI,KAAA;CAC/E,OAAO,WAAW,KAAA,KAAa,OAAO,SAAS,SAC3C,OAAO,QACP;EAAE,aAAa;EAAK,cAAc;CAAK;AAC7C;AAEA,MAAM,cAAc,WAClB,SAAS,KACP,OAAO,WAAW,MAAM,CAAC,CAAC;CACxB,aAAa,OAAO;CACpB,cAAc,OAAO;AACvB,CAAC,CACH;AAEF,MAAa,YAAY,UAAmB,CAAC,MAA2C;CACtF,MAAM,QAAQ,QAAQ,SAAS,WAAW;CAC1C,MAAM,WAAW,QAAQ,WAAW,uCAAA,CAAwC,QAAQ,OAAO,EAAE;CAC7F,MAAM,UAAU,WAAmC;EAAE;EAAO;EAAO;CAAQ;CAE3E,MAAM,mBAAmB,UACvBA,UAAiB,OAAO,KAAK,CAAC,CAAC,CAAC,KAC9B,OAAO,KAAK,UAAU;EACpB,MAAM,WAAW,IAAI,IAAI,MAAM,KAAK,SAAS,KAAK,QAAQ,EAAE,CAAC;EAC7D,MAAM,CAAC,QAAQ;EACf,OAAO,SAAS,SAAS,KAAK,SAAS,KAAA,IAAY,OAAO;CAC5D,CAAC,CACH;CAEF,MAAM,YAAY,UAA0C;EAC1D,MAAM,KAAK;EACX,SAAS;GAAE,WAAW,KAAK,QAAQ;GAAI,QAAQ,KAAK;EAAG;EACvD,OAAO,GAAG,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAK;EAC1C,aAAa,KAAK,gBAAgB,CAAC;CACrC;CAEA,MAAM,eAAe,UACnB,OAAO,IAAI,aAAa;EAGtB,OAAO;GACL,UAAA,OAHsB,QAAQ,MAAM,UAAU,gBAAgB;GAI9D,cAAA,OAH0B,QAAQ,MAAM,cAAc,oBAAoB;GAI1E,YAAY,MAAM,cAAc;EAClC;CACF,CAAC;CAEH,MAAM,UACJ,WAEA,gBAAgB,OAAO,WAAW,CAAC,CAAC,KAClC,OAAO,KAAK,eAAe;EACzB,QAAQ,WAAW,MAAM;EACzB,SAAS,EAAE,UAAU;EACrB,WAAW,OAAO;CACpB,EAAE,CACJ;CAEF,MAAM,QAAQ,QAAQ,UAAU,KAAA,IAAY,KAAA,IAAY,UAAU,QAAQ,KAAK;CAE/E,SAAS,UAAU,UAA6D;EAC9E,MAAM,SAAS,SAAS,UAAU;EAClC,OAAO;GACL,OAAO;GACP;GACA,QAAQ,UACN,YAAY,QAAQ,CAAC,CAAC,KACpB,OAAO,KAAK,EAAE,gBAAgB,EAC5B,kBAAkBC,iBAAuB;IACvC;IACA;IACA;IACA,OAAO,MAAM;IACb,aAAa,MAAM;IACnB,eAAe,MAAM;GACvB,CAAC,EACH,EAAE,CACJ;GACF,WAAW,UACT,YAAY,QAAQ,CAAC,CAAC,KACpB,OAAO,SAAS,qBACdC,aAAmB;IACjB,UAAUC;IACV;IACA,QAAQ;IACR,MAAM,MAAM;IACZ,OAAO,MAAM,OAAO,SAAS;IAC7B,aAAa,MAAM;IACnB,cAAc,MAAM;IACpB;GACF,CAAC,CACH,GACA,OAAO,QAAQ,MAAM,CACvB;GACF,UAAU,eACR,OAAO,IAAI,aAAa;IACtB,MAAM,EAAE,iBAAiB,YAAY,WAAW,MAAM;IACtD,IAAI,iBAAiB,MACnB,OAAO,OAAOC,KACZ,IAAIC,gBAAuB,EACzB,SAAS,6CACX,CAAC,CACH;IAEF,MAAM,SAAS,OAAOC,QAAc;KAClC,UAAUH;KACV;KACA,QAAQ,OAAO,YAAY,QAAQ;KACnC;KACA;IACF,CAAC;IACD,OAAO;KACL,QAAQ,WAAW,MAAM;KACzB,SAAS,WAAW;KACpB,WAAW,OAAO;IACpB;GACF,CAAC;GACH,SAAS,eACP,OAAO,IAAI,aAAa;IACtB,MAAM,EAAE,gBAAgB,YAAY,WAAW,MAAM;IACrD,OAAOI,OAAa;KAClB,UAAUJ;KACV;KACA,QAAQ,OAAO,YAAY,QAAQ;KACnC,OAAO;KACP;IACF,CAAC;GACH,CAAC;EACL;CACF;CAEA,OAAOK,KAA8B;EACnC,IAAI;EACJ,MAAM;EACN,SAAS;EACT,gBAAgB;EAChB,MAAM;GACJ,OAAOC,UAAmB;IACxB,OAAO;IACP,SAAS;IACT,sBAAsB;IACtB,QAAQ;IACR,eAAe,EAAE,OAAO,gBACtB,OAAO,IAAI,aAAa;KACtB,MAAM,MAAM,SAAS,MAAM,KAAK;KAChC,IAAI,cAAc,KAAA,GAAW;MAC3B,MAAM,YAAY,OAAOC,YACvB,OAAO,GAAG,GACV,aAAa,mBAAmB,SAAS,EAAE,eAC7C;MACA,OAAO;OACL,QAAQ;OACR,SAAS;QAAE;QAAW,WAAW;OAAU;OAC3C;MACF;KACF;KACA,MAAM,aAAa,OAAO,gBAAgB,GAAG;KAC7C,MAAM,WAAW,OAAOC,YAAmB,OAAO,GAAG,GAAG,UAAU;KAClE,OAAO;MACL,QAAQ;MACR,SAAS;OAAE,WAAW;OAAY,WAAW,SAAS;MAAK;MAC3D,WAAW,SAAS;KACtB;IACF,CAAC;GACL,CAAC;GACD,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;EACzC;EACA,UAAU,eAAe;GACvB,MAAM,EAAE,gBAAgB,YAAY,WAAW,MAAM;GACrD,MAAM,gBAAgB,OAAO,WAAW;GACxC,MAAM,UAAU,OAAO,oBAAoB,cAAc,CAAC,CAAC,WAAW,OAAO;GAC7E,MAAM,YACJ,QAAQ,SAAS,SAAU,QAAQ,MAAM,aAAa,KAAA,IAAa,KAAA;GACrE,MAAM,oBACJX,UAAiB,eAAe,SAAS,CAAC,CAAC,KAAK,OAAO,KAAK,UAAU,MAAM,IAAI,QAAQ,CAAC,CAAC;GAC5F,OAAO;IACL,oBAAoB,OAAO,QAAQ,YAAY;IAC/C;IACA,gBAAgB,WACd,OAAO,IAAI,aAAa;KACtB,MAAM,OAAO,OAAOY,OAAkB,MAAM;KAC5C,MAAM,UAAU,OAAO,YAAY;KACnC,OAAOC,aAAsB,MAAM,OAAO;IAC5C,CAAC;IACH,MAAM,WAAW;KACf,MAAM,OAAO,OAAO,oBAAoB,cAAc,CAAC,CAAC,OAAO,OAAO;KACtE,MAAM,SAAS,KAAK,SAAS,SAAS,KAAK,MAAM,SAAS,KAAA;KAC1D,IAAI,WAAW,KAAA,GAAW;MACxB,MAAM,UAAUT,KACd,IAAIU,YAAmB;OACrB,UAAU;OACV,WAAW;OACX,SAAS;MACX,CAAC,CACH;MACA,OAAO;OACL,YAAY;OACZ,cAAc;OACd,WAAW;OACX,cAAc;MAChB;KACF;KACA,OAAOC,IAAW,eAAe,MAAM;IACzC;GACF;EACF;CACF,CAAC;AACH"}
|