domainkit 0.1.0 → 0.2.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 +91 -71
- package/dist/{auth-Vi-hhXbV.mjs → auth-CZ1pZHMZ.mjs} +301 -38
- package/dist/auth-CZ1pZHMZ.mjs.map +1 -0
- package/dist/{client-BnD7QLRF.mjs → auth-CzhZ3Cuc.mjs} +235 -131
- package/dist/auth-CzhZ3Cuc.mjs.map +1 -0
- package/dist/authorization-DOg2Re1D.mjs +247 -0
- package/dist/authorization-DOg2Re1D.mjs.map +1 -0
- package/dist/canonical-json-CpvqGMcr.mjs +57 -0
- package/dist/canonical-json-CpvqGMcr.mjs.map +1 -0
- package/dist/{cloudflare-C6ryPlCZ.mjs → cloudflare-BedFw4cX.mjs} +28 -7
- package/dist/cloudflare-BedFw4cX.mjs.map +1 -0
- package/dist/cloudflare-FDl5q7Dm.d.mts +32 -0
- package/dist/cloudflare.d.mts +3 -3
- package/dist/cloudflare.mjs +2 -2
- package/dist/connection-BWrBwqjk.mjs +58 -0
- package/dist/connection-BWrBwqjk.mjs.map +1 -0
- package/dist/connection-CEqadXSm.d.mts +182 -0
- package/dist/connection-CcQokgrd.mjs +186 -0
- package/dist/connection-CcQokgrd.mjs.map +1 -0
- package/dist/connection-api-DftK7eHo.d.mts +7 -0
- package/dist/{dns-record-C_KwGPLf.mjs → dns-record-BLeqo56C.mjs} +23 -3
- package/dist/dns-record-BLeqo56C.mjs.map +1 -0
- package/dist/effect-cloudflare.d.mts +2 -2
- package/dist/effect-cloudflare.mjs +2 -2
- package/dist/effect-vercel.d.mts +2 -2
- package/dist/effect-vercel.mjs +2 -2
- package/dist/effect.d.mts +9 -46
- package/dist/effect.mjs +29 -7
- package/dist/effect.mjs.map +1 -1
- package/dist/index-B1opsgls.d.mts +159 -0
- package/dist/{index-CEzk2gbZ.d.mts → index-Ewc__bQu.d.mts} +58 -7
- package/dist/index.d.mts +169 -113
- package/dist/index.mjs +201 -138
- package/dist/index.mjs.map +1 -1
- package/dist/{resolver-BHPsADzE.d.mts → resolver-CJOR9mQ8.d.mts} +620 -263
- package/dist/resolver-CxE-VDw4.mjs +598 -0
- package/dist/resolver-CxE-VDw4.mjs.map +1 -0
- package/dist/testing.d.mts +53 -44
- package/dist/testing.mjs +379 -107
- package/dist/testing.mjs.map +1 -1
- package/dist/{vercel-DD89DCqH.mjs → vercel-CWZ33NUS.mjs} +23 -3
- package/dist/vercel-CWZ33NUS.mjs.map +1 -0
- package/dist/vercel-DgJaUX9D.d.mts +31 -0
- package/dist/vercel.d.mts +3 -3
- package/dist/vercel.mjs +2 -2
- package/dist/verify-BzpiA0Es.mjs +642 -0
- package/dist/verify-BzpiA0Es.mjs.map +1 -0
- package/dist/verify-DZWLM91T.d.mts +805 -0
- package/dist/zone-discovery-BA5I24vu.d.mts +1390 -0
- package/dist/zones-DKHTpX9C.mjs +19 -0
- package/dist/zones-DKHTpX9C.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/auth-Vi-hhXbV.mjs.map +0 -1
- package/dist/client-BnD7QLRF.mjs.map +0 -1
- package/dist/cloudflare-C6ryPlCZ.mjs.map +0 -1
- package/dist/cloudflare-tdjNS8vE.d.mts +0 -23
- package/dist/dns-record-C_KwGPLf.mjs.map +0 -1
- package/dist/index-CS9Rl5LQ.d.mts +0 -71
- package/dist/manifest-CP85ePFn.d.mts +0 -583
- package/dist/receipt-CGSnfZQ6.mjs +0 -28
- package/dist/receipt-CGSnfZQ6.mjs.map +0 -1
- package/dist/resolver-tEXpKxmH.mjs +0 -200
- package/dist/resolver-tEXpKxmH.mjs.map +0 -1
- package/dist/vercel-D-E2aqb1.d.mts +0 -22
- package/dist/vercel-DD89DCqH.mjs.map +0 -1
- package/dist/verify-B80xCBh2.d.mts +0 -1407
- package/dist/verify-BjrR_4NF.mjs +0 -1401
- package/dist/verify-BjrR_4NF.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-CZ1pZHMZ.mjs","names":["Secret.make","failure","Connection.Error","S","Data","S","decode","DomainName.decode","failure","DnsRecord.decode","DnsRecord.Opaque","DnsProvider.Error","Protocol.ZoneListEnvelope","Protocol.TokenEnvelope","Zones.candidates","Protocol.RecordListEnvelope","Records.decode","Records.encode","Protocol.RecordEnvelope","DomainName.decode","S","Protocol.BaseEnvelope","DnsProvider.Error","Context","ProviderContext.codec","Client.discoverAuthorizationAccount","Client.make","Client.validateDomainToken","AuthorizationCode.complete","Secret.make","AuthorizationCode.start"],"sources":["../src/auth/authorization-code.ts","../src/providers/cloudflare/protocol.ts","../src/providers/cloudflare/records.ts","../src/providers/cloudflare/client.ts","../src/providers/cloudflare/auth.ts"],"sourcesContent":["import { Crypto, Effect, Schema } from \"effect\";\nimport * as oauth from \"oauth4webapi\";\n\nimport type * as ProviderAuth from \"./manifest.ts\";\nimport * as Connection from \"./connect.ts\";\nimport * as Secret from \"./secret.ts\";\n\nexport type Fetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nexport interface Payload {\n readonly codeVerifier: string;\n readonly redirectUri: string;\n readonly state: string;\n}\n\nexport const start = Effect.fn(\"AuthorizationCode.start\")(function* (input: {\n readonly client: ProviderAuth.OAuthClientConfiguration;\n readonly method: ProviderAuth.OAuthMethod;\n readonly redirectUri: string;\n readonly state: string;\n}) {\n const crypto = yield* Crypto.Crypto;\n const codeVerifier = base64Url(yield* randomBytes(crypto, 32));\n const challenge = base64Url(yield* digest(crypto, codeVerifier));\n const authorizationUrl = new URL(input.method.authorizationServer.authorization_endpoint);\n authorizationUrl.search = new URLSearchParams({\n client_id: input.client.clientId,\n code_challenge: challenge,\n code_challenge_method: \"S256\",\n redirect_uri: input.redirectUri,\n response_type: \"code\",\n scope: input.method.scopes.join(\" \"),\n state: input.state,\n }).toString();\n return {\n authorizationUrl,\n payload: Secret.make(\n JSON.stringify({ codeVerifier, redirectUri: input.redirectUri, state: input.state }),\n ),\n };\n});\n\nexport const complete = Effect.fn(\"AuthorizationCode.complete\")(function* (input: {\n readonly callbackUrl: URL;\n readonly client: ProviderAuth.OAuthClientConfiguration;\n readonly fetch?: Fetch;\n readonly method: ProviderAuth.OAuthMethod;\n readonly payload: Secret.Value;\n readonly providerId: string;\n}) {\n const payload = yield* decodePayload(input.payload);\n if (input.callbackUrl.searchParams.get(\"state\") !== payload.state) {\n return yield* failure(\"Authorization callback state does not match its continuation\");\n }\n const server = input.method.authorizationServer as oauth.AuthorizationServer;\n const client: oauth.Client = { client_id: input.client.clientId };\n const authentication = yield* clientAuthentication(input.method, input.client);\n return yield* Effect.tryPromise({\n try: async (signal) => {\n const callback = oauth.validateAuthResponse(server, client, input.callbackUrl, payload.state);\n const response = await oauth.authorizationCodeGrantRequest(\n server,\n client,\n authentication,\n callback,\n payload.redirectUri,\n payload.codeVerifier,\n requestOptions(input.fetch, signal),\n );\n return oauth.processAuthorizationCodeResponse(server, client, response);\n },\n catch: (cause) =>\n new Connection.Error({\n category: \"provider\",\n message: cause instanceof globalThis.Error ? cause.name : \"OAuth provider request failed\",\n operation: \"AuthorizationCode.complete\",\n retry: \"unknown\",\n }),\n });\n});\n\nconst PayloadSchema = Schema.Struct({\n codeVerifier: Schema.String,\n redirectUri: Schema.String,\n state: Schema.String,\n});\n\nfunction decodePayload(payload: Secret.Value): Effect.Effect<Payload, Connection.Error> {\n return Schema.decodeUnknownEffect(Schema.fromJsonString(PayloadSchema))(payload.expose()).pipe(\n Effect.mapError(\n () =>\n new Connection.Error({\n category: \"authorization\",\n message: \"OAuth continuation payload is invalid\",\n operation: \"AuthorizationCode\",\n retry: \"after-user-action\",\n }),\n ),\n );\n}\n\nfunction clientAuthentication(\n method: ProviderAuth.OAuthMethod,\n client: ProviderAuth.OAuthClientConfiguration,\n): Effect.Effect<oauth.ClientAuth, Connection.Error> {\n switch (method.clientAuth) {\n case \"none\":\n return Effect.succeed(oauth.None());\n case \"client_secret_basic\":\n return client.clientSecret === undefined\n ? failure(\"OAuth client secret is required\")\n : Effect.succeed(oauth.ClientSecretBasic(client.clientSecret.expose()));\n case \"client_secret_post\":\n return client.clientSecret === undefined\n ? failure(\"OAuth client secret is required\")\n : Effect.succeed(oauth.ClientSecretPost(client.clientSecret.expose()));\n }\n}\n\nfunction requestOptions(\n fetchImplementation: Fetch | undefined,\n signal: AbortSignal,\n): oauth.TokenEndpointRequestOptions {\n return fetchImplementation === undefined\n ? { signal }\n : {\n signal,\n [oauth.customFetch]: (url, options) =>\n fetchImplementation(url, { ...options, body: options.body }),\n };\n}\n\nconst failure = (message: string): Effect.Effect<never, Connection.Error> =>\n Effect.fail(\n new Connection.Error({\n category: \"authorization\",\n message,\n operation: \"AuthorizationCode\",\n retry: \"after-user-action\",\n }),\n );\n\nfunction randomBytes(\n crypto: Crypto.Crypto,\n size: number,\n): Effect.Effect<Uint8Array, Connection.Error> {\n return crypto.randomBytes(size).pipe(\n Effect.mapError(\n (cause) =>\n new Connection.Error({\n category: \"validation\",\n message: cause.message,\n operation: \"AuthorizationCode.start\",\n retry: \"safe\",\n }),\n ),\n );\n}\n\nfunction digest(crypto: Crypto.Crypto, value: string): Effect.Effect<Uint8Array, Connection.Error> {\n return crypto.digest(\"SHA-256\", new TextEncoder().encode(value)).pipe(\n Effect.mapError(\n (cause) =>\n new Connection.Error({\n category: \"validation\",\n message: cause.message,\n operation: \"AuthorizationCode.start\",\n retry: \"safe\",\n }),\n ),\n );\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\n","import { Schema as S } from \"effect\";\n\nexport const ErrorDetail = S.Struct({\n code: S.Number,\n message: S.String,\n});\nexport interface ErrorDetail extends S.Schema.Type<typeof ErrorDetail> {}\n\nexport const ResultInfo = S.Struct({\n count: S.optionalKey(S.Number),\n page: S.optionalKey(S.Number),\n per_page: S.optionalKey(S.Number),\n total_count: S.optionalKey(S.Number),\n total_pages: S.optionalKey(S.Number),\n});\n\nconst Message = S.Struct({\n code: S.optionalKey(S.Number),\n message: S.String,\n});\n\nexport const BaseEnvelope = S.Struct({\n errors: S.Array(ErrorDetail),\n messages: S.Array(Message),\n success: S.Boolean,\n});\n\nexport const Account = S.Struct({\n id: S.String,\n name: S.String,\n});\nexport interface Account extends S.Schema.Type<typeof Account> {}\n\nexport const Zone = S.Struct({\n account: Account,\n id: S.String,\n name: S.String,\n name_servers: S.Array(S.String),\n status: S.optionalKey(S.String),\n});\nexport interface Zone extends S.Schema.Type<typeof Zone> {}\n\nexport const Record = S.Struct({\n content: S.optionalKey(S.String),\n data: S.optionalKey(S.Unknown),\n id: S.String,\n name: S.String,\n priority: S.optionalKey(S.Number),\n proxied: S.optionalKey(S.Boolean),\n ttl: S.Number,\n type: S.String,\n});\nexport interface Record extends S.Schema.Type<typeof Record> {}\n\nexport const Token = S.Struct({\n expires_on: S.optionalKey(S.String),\n id: S.String,\n not_before: S.optionalKey(S.String),\n status: S.Literals([\"active\", \"disabled\", \"expired\"]),\n});\nexport interface Token extends S.Schema.Type<typeof Token> {}\n\nexport const ZoneListEnvelope = S.Struct({\n errors: S.Array(ErrorDetail),\n messages: S.Array(Message),\n result: S.Array(Zone),\n result_info: S.optionalKey(ResultInfo),\n success: S.Boolean,\n});\nexport const RecordListEnvelope = S.Struct({\n errors: S.Array(ErrorDetail),\n messages: S.Array(Message),\n result: S.Array(Record),\n result_info: S.optionalKey(ResultInfo),\n success: S.Boolean,\n});\nexport const RecordEnvelope = S.Struct({\n errors: S.Array(ErrorDetail),\n messages: S.Array(Message),\n result: Record,\n success: S.Boolean,\n});\nexport const TokenEnvelope = S.Struct({\n errors: S.Array(ErrorDetail),\n messages: S.Array(Message),\n result: Token,\n success: S.Boolean,\n});\n","import { Effect, Schema as S } from \"effect\";\n\nimport * as DomainName from \"../../domain/domain-name.ts\";\nimport * as DnsRecord from \"../../domain/dns-record.ts\";\nimport * as DnsProvider from \"../../provider/provider.ts\";\nimport type * as Protocol from \"./protocol.ts\";\n\nconst Data = S.Struct({\n flags: S.optionalKey(S.Number),\n port: S.optionalKey(S.Number),\n priority: S.optionalKey(S.Number),\n tag: S.optionalKey(S.String),\n target: S.optionalKey(S.String),\n value: S.optionalKey(S.String),\n weight: S.optionalKey(S.Number),\n});\n\nexport type CreateBody = Readonly<Record<string, unknown>>;\n\nexport const decode = Effect.fn(\"CloudflareRecords.decode\")((record: Protocol.Record) =>\n Effect.gen(function* () {\n const name = yield* DomainName.decode(record.name).pipe(\n Effect.match({ onFailure: () => null, onSuccess: (value) => value }),\n );\n if (name === null) return yield* decodeOpaque(record);\n const common = {\n metadata: {\n ownership: \"provider\",\n provenance: record.proxied === true ? \"cloudflare:proxied\" : \"cloudflare\",\n purpose: \"existing DNS record\",\n },\n name,\n policy: record.type === \"CNAME\" ? \"exclusive\" : \"append\",\n ttl: record.ttl === 1 ? null : record.ttl,\n } as const;\n const content = () =>\n record.content === undefined\n ? Effect.fail(failure(\"decodeRecord\", `Cloudflare ${record.type} record has no content`))\n : Effect.succeed(record.content);\n\n switch (record.type) {\n case \"A\":\n case \"AAAA\":\n return yield* DnsRecord.decode({\n ...common,\n _tag: record.type,\n address: yield* content(),\n }).pipe(Effect.mapError((cause) => failure(\"decodeRecord\", cause.message)));\n case \"CNAME\":\n case \"NS\":\n return yield* DnsRecord.decode({\n ...common,\n _tag: record.type,\n target: yield* content(),\n }).pipe(Effect.mapError((cause) => failure(\"decodeRecord\", cause.message)));\n case \"TXT\":\n return yield* DnsRecord.decode({\n ...common,\n _tag: \"TXT\",\n value: yield* content(),\n }).pipe(Effect.mapError((cause) => failure(\"decodeRecord\", cause.message)));\n case \"MX\":\n return yield* DnsRecord.decode({\n ...common,\n _tag: \"MX\",\n exchange: yield* content(),\n priority: record.priority,\n }).pipe(Effect.mapError((cause) => failure(\"decodeRecord\", cause.message)));\n case \"CAA\": {\n const data = yield* decodeData(record);\n return yield* DnsRecord.decode({ ...common, _tag: \"CAA\", ...data }).pipe(\n Effect.mapError((cause) => failure(\"decodeRecord\", cause.message)),\n );\n }\n case \"SRV\": {\n const data = yield* decodeData(record);\n return yield* DnsRecord.decode({ ...common, _tag: \"SRV\", ...data }).pipe(\n Effect.mapError((cause) => failure(\"decodeRecord\", cause.message)),\n );\n }\n default:\n return yield* decodeOpaque(record);\n }\n }),\n);\n\nconst decodeOpaque = Effect.fn(\"CloudflareRecords.decodeOpaque\")((record: Protocol.Record) =>\n S.decodeUnknownEffect(DnsRecord.Opaque)({\n _tag: \"Opaque\",\n name: record.name,\n providerRecordId: record.id,\n providerType: record.type,\n }).pipe(Effect.mapError((cause) => failure(\"decodeRecord\", cause.message))),\n);\n\nexport function encode(record: DnsRecord.DnsRecord): CreateBody {\n const common = {\n name: record.name,\n proxied: false,\n ttl: record.ttl ?? 1,\n type: record._tag,\n };\n switch (record._tag) {\n case \"A\":\n case \"AAAA\":\n return { ...common, content: record.address };\n case \"CNAME\":\n case \"NS\":\n return { ...common, content: record.target };\n case \"TXT\":\n return { ...common, content: record.value };\n case \"MX\":\n return { ...common, content: record.exchange, priority: record.priority };\n case \"CAA\":\n return {\n ...common,\n data: { flags: record.flags, tag: record.tag, value: record.value },\n };\n case \"SRV\":\n return {\n ...common,\n data: {\n port: record.port,\n priority: record.priority,\n target: record.target,\n weight: record.weight,\n },\n };\n }\n}\n\nconst decodeData = Effect.fn(\"CloudflareRecords.decodeData\")((record: Protocol.Record) =>\n S.decodeUnknownEffect(Data)(record.data).pipe(\n Effect.mapError((cause) => failure(\"decodeRecord\", cause.message)),\n ),\n);\n\nfunction failure(\n operation: string,\n message: string,\n fields: Partial<Pick<DnsProvider.Error, \"reason\">> = {},\n): DnsProvider.Error {\n return new DnsProvider.Error({\n message,\n operation,\n providerId: \"cloudflare\",\n reason: fields.reason ?? \"response\",\n });\n}\n","import { Effect, Schema as S } from \"effect\";\n\nimport type * as ProviderAuth from \"../../auth/manifest.ts\";\nimport type * as Secret from \"../../auth/secret.ts\";\nimport * as DomainName from \"../../domain/domain-name.ts\";\nimport type * as DnsRecord from \"../../domain/dns-record.ts\";\nimport type * as ZoneDiscovery from \"../../discovery/zone-discovery.ts\";\nimport * as Zones from \"../../discovery/zones.ts\";\nimport * as DnsProvider from \"../../provider/provider.ts\";\nimport * as Protocol from \"./protocol.ts\";\nimport * as Records from \"./records.ts\";\n\nexport type Fetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\n/** Configuration for an Effect-native Cloudflare authoritative-DNS client. */\nexport interface Options {\n readonly accountId: string;\n readonly baseUrl?: string;\n /** Capabilities the host required when issuing or authorizing this credential. */\n readonly capabilities: ProviderAuth.TokenValidation[\"capabilities\"];\n readonly fetch?: Fetch;\n readonly token: Secret.Value;\n readonly tokenKind?: \"account\" | \"user\";\n}\n\nexport interface ListZonesInput {\n readonly accountId?: string;\n readonly name?: DomainName.DomainName;\n}\n\nexport type Account = Protocol.Account;\n\n/** A portable Cloudflare authoritative zone with normalized nameserver evidence. */\nexport interface Zone {\n readonly accountId: string;\n readonly id: string;\n readonly name: DomainName.DomainName;\n readonly nameservers: ReadonlyArray<DomainName.DomainName>;\n readonly status: string | null;\n}\n\nexport interface Interface extends DnsProvider.Interface {\n readonly listAccounts: () => Effect.Effect<ReadonlyArray<Account>, DnsProvider.Error>;\n readonly listZones: (\n input?: ListZonesInput,\n ) => Effect.Effect<ReadonlyArray<Zone>, DnsProvider.Error>;\n readonly validateToken: () => Effect.Effect<ProviderAuth.TokenValidation, DnsProvider.Error>;\n}\n\n/** Exposes Cloudflare zone lookup as the optional provider discovery capability. */\nexport function discovery(client: Interface): ZoneDiscovery.Source {\n return {\n listZones: (name) =>\n client.listZones({ name }).pipe(\n Effect.map((zones) =>\n zones.map((zone) => ({\n ...zone,\n status: zone.status === \"active\" || zone.status === \"pending\" ? zone.status : \"unknown\",\n })),\n ),\n ),\n provider: client,\n };\n}\n\ninterface CredentialOptions {\n readonly baseUrl?: string;\n readonly fetch?: Fetch;\n readonly token: Secret.Value;\n}\n\ninterface DomainCredentialOptions extends CredentialOptions {\n readonly capabilities: ProviderAuth.TokenValidation[\"capabilities\"];\n readonly domain: DomainName.DomainName;\n readonly tokenKind?: \"account\" | \"user\";\n}\n\nconst makeTransport = (options: CredentialOptions) => {\n const fetch = options.fetch ?? globalThis.fetch;\n const baseUrl = (options.baseUrl ?? \"https://api.cloudflare.com/client/v4\").replace(/\\/$/, \"\");\n\n const request = Effect.fn(\"CloudflareClient.request\")(\n (path: string, operation: string, init?: RequestInit) =>\n Effect.gen(function* () {\n const response = yield* Effect.tryPromise({\n try: () =>\n fetch(`${baseUrl}${path}`, {\n ...init,\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${options.token.expose()}`,\n ...(init?.body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n ...init?.headers,\n },\n }),\n catch: () =>\n failure(operation, \"Cloudflare request failed\", {\n reason: \"transport\",\n }),\n });\n const body = yield* Effect.tryPromise({\n try: () => response.json() as Promise<unknown>,\n catch: () => {\n const retryAfterMs = retryAfter(response.headers.get(\"retry-after\"));\n return failure(\n operation,\n response.ok\n ? \"Cloudflare returned a non-JSON response\"\n : `Cloudflare request failed with HTTP ${response.status}`,\n {\n reason: response.ok ? \"response\" : reason(response.status),\n ...(retryAfterMs === undefined ? {} : { retryAfterMs }),\n status: response.status,\n },\n );\n },\n });\n return { body, response } as const;\n }),\n );\n\n const listZonesPage = Effect.fn(\"CloudflareClient.listZonesPage\")(\n (accountId: string | undefined, name: DomainName.DomainName | undefined, page: number) =>\n Effect.gen(function* () {\n const query = new URLSearchParams({ page: String(page), per_page: \"50\" });\n query.set(\"type\", \"full,partial,secondary,internal\");\n if (accountId !== undefined) query.set(\"account.id\", accountId);\n if (name !== undefined) query.set(\"name\", name);\n const { body, response } = yield* request(`/zones?${query}`, \"listZones\");\n yield* ensureSuccess(body, \"listZones\", response);\n return yield* decode(Protocol.ZoneListEnvelope, body, \"listZones\", response);\n }),\n );\n\n const allZones = Effect.fn(\"CloudflareClient.allZones\")(\n (accountId?: string, name?: DomainName.DomainName) =>\n Effect.gen(function* () {\n const zones: Array<Protocol.Zone> = [];\n let page = 1;\n while (true) {\n const envelope = yield* listZonesPage(accountId, name, page);\n zones.push(...envelope.result);\n const totalPages = envelope.result_info?.total_pages;\n if (\n (totalPages !== undefined && page >= totalPages) ||\n (totalPages === undefined && envelope.result.length < 50)\n ) {\n return zones;\n }\n page += 1;\n }\n }),\n );\n\n const inspectToken = Effect.fn(\"CloudflareClient.inspectToken\")((path: string) =>\n Effect.gen(function* () {\n const { body, response } = yield* request(path, \"validateToken\");\n yield* ensureSuccess(body, \"validateToken\", response);\n const envelope = yield* decode(Protocol.TokenEnvelope, body, \"validateToken\", response);\n if (envelope.result.status !== \"active\") {\n return yield* Effect.fail(\n failure(\"validateToken\", `Cloudflare token is ${envelope.result.status}`, {\n reason: \"authentication\",\n status: response.status,\n }),\n );\n }\n const expiresAt =\n envelope.result.expires_on === undefined ? null : new Date(envelope.result.expires_on);\n if (expiresAt !== null && Number.isNaN(expiresAt.valueOf())) {\n return yield* Effect.fail(\n failure(\"validateToken\", \"Cloudflare token expiry is not a valid timestamp\", {\n reason: \"response\",\n status: response.status,\n }),\n );\n }\n return expiresAt;\n }),\n );\n\n return { allZones, inspectToken, request } as const;\n};\n\nconst discoverAccount = Effect.fn(\"CloudflareClient.discoverAccount\")(\n (options: CredentialOptions & { readonly domain: DomainName.DomainName }) =>\n Effect.gen(function* () {\n const { allZones } = makeTransport(options);\n for (const candidate of Zones.candidates(options.domain)) {\n const matches = yield* allZones(undefined, candidate);\n const match = matches[0];\n if (matches.length === 0) continue;\n if (matches.length === 1 && match !== undefined) return match.account;\n return yield* Effect.fail(\n failure(\n \"discoverAccount\",\n `Cloudflare returned multiple accessible zones named ${candidate}`,\n { reason: \"conflict\" },\n ),\n );\n }\n return yield* Effect.fail(\n failure(\n \"discoverAccount\",\n `Cloudflare did not expose an accessible zone for ${options.domain}`,\n { reason: \"not_found\" },\n ),\n );\n }),\n);\n\nexport const discoverAuthorizationAccount = discoverAccount;\n\nexport const validateDomainToken = Effect.fn(\"CloudflareClient.validateDomainToken\")(\n (options: DomainCredentialOptions) =>\n Effect.gen(function* () {\n const transport = makeTransport(options);\n const account = options.tokenKind === \"account\" ? yield* discoverAccount(options) : undefined;\n const expiresAt = yield* transport.inspectToken(\n account === undefined\n ? \"/user/tokens/verify\"\n : `/accounts/${encodeURIComponent(account.id)}/tokens/verify`,\n );\n const discoveredAccount = account ?? (yield* discoverAccount(options));\n return {\n accountId: discoveredAccount.id,\n capabilities: options.capabilities,\n expiresAt,\n scopes: [],\n } satisfies ProviderAuth.TokenValidation;\n }),\n);\n\n/** Creates an Effect-native Cloudflare client without owning the credential lifecycle. */\nexport function make(options: Options): Interface {\n const { allZones, inspectToken, request } = makeTransport(options);\n\n const resolveZone = Effect.fn(\"CloudflareClient.resolveZone\")((name: DomainName.DomainName) =>\n Effect.gen(function* () {\n const matches = yield* allZones(options.accountId, name);\n const match = matches[0];\n if (matches.length === 1 && match !== undefined) return match;\n return yield* Effect.fail(\n failure(\n \"resolveZone\",\n matches.length === 0\n ? `Cloudflare zone ${name} was not found in account ${options.accountId}`\n : `Cloudflare returned multiple zones named ${name} in account ${options.accountId}`,\n { reason: matches.length === 0 ? \"not_found\" : \"response\" },\n ),\n );\n }),\n );\n\n const listRecords = Effect.fn(\"CloudflareClient.listRecords\")((zoneName: DomainName.DomainName) =>\n Effect.gen(function* () {\n const zone = yield* resolveZone(zoneName);\n const records: Array<DnsRecord.Observed> = [];\n let page = 1;\n while (true) {\n const query = new URLSearchParams({ page: String(page), per_page: \"100\" });\n const { body, response } = yield* request(\n `/zones/${encodeURIComponent(zone.id)}/dns_records?${query}`,\n \"listRecords\",\n );\n yield* ensureSuccess(body, \"listRecords\", response);\n const envelope = yield* decode(Protocol.RecordListEnvelope, body, \"listRecords\", response);\n records.push(...(yield* Effect.forEach(envelope.result, Records.decode)));\n const totalPages = envelope.result_info?.total_pages;\n if (\n (totalPages !== undefined && page >= totalPages) ||\n (totalPages === undefined && envelope.result.length < 100)\n ) {\n return records;\n }\n page += 1;\n }\n }),\n );\n\n const createRecord = Effect.fn(\"CloudflareClient.createRecord\")(\n (zoneName: DomainName.DomainName, record: DnsRecord.DnsRecord) =>\n Effect.gen(function* () {\n const zone = yield* resolveZone(zoneName);\n const { body, response } = yield* request(\n `/zones/${encodeURIComponent(zone.id)}/dns_records`,\n \"createRecord\",\n { body: JSON.stringify(Records.encode(record)), method: \"POST\" },\n );\n yield* ensureSuccess(body, \"createRecord\", response);\n const envelope = yield* decode(Protocol.RecordEnvelope, body, \"createRecord\", response);\n return { providerRecordId: envelope.result.id };\n }),\n );\n\n const getRecord = Effect.fn(\"CloudflareClient.getRecord\")(\n (zoneName: DomainName.DomainName, providerRecordId: string) =>\n Effect.gen(function* () {\n const zone = yield* resolveZone(zoneName);\n const { body, response } = yield* request(\n `/zones/${encodeURIComponent(zone.id)}/dns_records/${encodeURIComponent(providerRecordId)}`,\n \"getRecord\",\n );\n if (response.status === 404) return null;\n yield* ensureSuccess(body, \"getRecord\", response);\n const envelope = yield* decode(Protocol.RecordEnvelope, body, \"getRecord\", response);\n return yield* Records.decode(envelope.result);\n }),\n );\n\n const deleteRecord = Effect.fn(\"CloudflareClient.deleteRecord\")(\n (zoneName: DomainName.DomainName, providerRecordId: string) =>\n Effect.gen(function* () {\n const zone = yield* resolveZone(zoneName);\n const { body, response } = yield* request(\n `/zones/${encodeURIComponent(zone.id)}/dns_records/${encodeURIComponent(providerRecordId)}`,\n \"deleteRecord\",\n { method: \"DELETE\" },\n );\n yield* ensureSuccess(body, \"deleteRecord\", response);\n }),\n );\n\n const listAccounts = Effect.fn(\"CloudflareClient.listAccounts\")(() =>\n allZones().pipe(\n Effect.map((zones) => {\n const accounts = new Map<string, Protocol.Account>();\n for (const zone of zones) accounts.set(zone.account.id, zone.account);\n return [...accounts.values()].sort((left, right) => left.name.localeCompare(right.name));\n }),\n ),\n );\n\n const listZones = Effect.fn(\"CloudflareClient.listZones\")((input: ListZonesInput = {}) =>\n allZones(input.accountId ?? options.accountId, input.name).pipe(\n Effect.flatMap((zones) => Effect.forEach(zones, projectZone)),\n ),\n );\n\n const validateToken = Effect.fn(\"CloudflareClient.validateToken\")(() =>\n Effect.gen(function* () {\n const path =\n options.tokenKind === \"account\"\n ? `/accounts/${encodeURIComponent(options.accountId)}/tokens/verify`\n : \"/user/tokens/verify\";\n const expiresAt = yield* inspectToken(path);\n yield* allZones(options.accountId);\n return {\n accountId: options.accountId,\n capabilities: options.capabilities,\n expiresAt,\n scopes: [],\n };\n }),\n );\n\n return {\n id: \"cloudflare\",\n createRecord,\n deleteRecord,\n getRecord,\n listAccounts,\n listRecords,\n listZones,\n validateToken,\n };\n}\n\nconst projectZone = Effect.fn(\"CloudflareClient.projectZone\")((zone: Protocol.Zone) =>\n Effect.gen(function* () {\n const name = yield* DomainName.decode(zone.name).pipe(\n Effect.mapError((cause) => failure(\"listZones\", cause.message, { reason: \"response\" })),\n );\n const nameservers = yield* Effect.forEach(zone.name_servers, (nameserver) =>\n DomainName.decode(nameserver).pipe(\n Effect.mapError((cause) => failure(\"listZones\", cause.message, { reason: \"response\" })),\n ),\n );\n return {\n accountId: zone.account.id,\n id: zone.id,\n name,\n nameservers,\n status: zone.status ?? null,\n };\n }),\n);\n\nfunction decode<A>(\n schema: S.ConstraintCodec<A, unknown, never, unknown>,\n input: unknown,\n operation: string,\n response: Response,\n): Effect.Effect<A, DnsProvider.Error> {\n return S.decodeUnknownEffect(schema)(input).pipe(\n Effect.mapError((cause) =>\n failure(operation, `Cloudflare response did not match its API contract: ${cause.message}`, {\n reason: \"response\",\n status: response.status,\n }),\n ),\n );\n}\n\nfunction ensureSuccess(\n input: unknown,\n operation: string,\n response: Response,\n): Effect.Effect<void, DnsProvider.Error> {\n return S.decodeUnknownEffect(Protocol.BaseEnvelope)(input).pipe(\n Effect.mapError(() =>\n failure(operation, \"Cloudflare response did not contain a valid API envelope\", {\n reason: \"response\",\n status: response.status,\n }),\n ),\n Effect.flatMap((envelope) => {\n if (response.ok && envelope.success) return Effect.void;\n const detail = envelope.errors[0];\n const retryAfterMs = retryAfter(response.headers.get(\"retry-after\"));\n return Effect.fail(\n failure(\n operation,\n detail?.message ?? `Cloudflare request failed with HTTP ${response.status}`,\n {\n ...(detail === undefined ? {} : { code: detail.code }),\n reason: reason(response.status, detail?.code),\n ...(retryAfterMs === undefined ? {} : { retryAfterMs }),\n status: response.status,\n },\n ),\n );\n }),\n );\n}\n\nfunction reason(status: number, code?: number): DnsProvider.ErrorReason {\n if (status === 401) return \"authentication\";\n if (status === 403) return \"authorization\";\n if (status === 404) return \"not_found\";\n if (status === 409 || code === 81056 || code === 81057 || code === 81058) return \"conflict\";\n if (status === 429) return \"rate_limit\";\n if (status >= 500) return \"response\";\n return \"request\";\n}\n\nfunction retryAfter(value: string | null): number | undefined {\n if (value === null) return undefined;\n const seconds = Number(value);\n if (Number.isFinite(seconds)) return Math.max(0, seconds * 1_000);\n const date = Date.parse(value);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n}\n\nfunction failure(\n operation: string,\n message: string,\n fields: Partial<Pick<DnsProvider.Error, \"code\" | \"reason\" | \"retryAfterMs\" | \"status\">> = {},\n): DnsProvider.Error {\n return new DnsProvider.Error({\n ...fields,\n message,\n operation,\n providerId: \"cloudflare\",\n });\n}\n","import type * as oauth from \"oauth4webapi\";\nimport { Clock, Effect, Schema } from \"effect\";\n\nimport * as AuthorizationCode from \"../../auth/authorization-code.ts\";\nimport * as Connection from \"../../auth/connect.ts\";\nimport * as ProviderAuthorization from \"../../auth/authorization.ts\";\nimport type * as ProviderAuth from \"../../auth/manifest.ts\";\nimport * as ProviderContext from \"../../auth/provider-context.ts\";\nimport * as Secret from \"../../auth/secret.ts\";\nimport type * as DomainName from \"../../domain/domain-name.ts\";\nimport * as Client from \"./client.ts\";\n\nconst authorizationServer = {\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} as const;\n\nconst Context = Schema.Struct({ tokenKind: Schema.Literals([\"account\", \"user\"]) });\nexport type Context = typeof Context.Type;\nexport const contextCodec = ProviderContext.codec(\"cloudflare.v1\", Context);\n\n/** Describes Cloudflare's caller-created API-token authorization method. */\nexport function tokenMethod(\n capabilities: ProviderAuth.TokenValidation[\"capabilities\"],\n): Extract<ProviderAuth.Manifest[\"methods\"][number], { readonly _tag: \"token\" }> {\n return {\n _tag: \"token\",\n capabilities: [...capabilities],\n instructionsUrl: \"https://developers.cloudflare.com/fundamentals/api/get-started/create-token/\",\n };\n}\n\nexport interface OAuthMethodOptions {\n /** Scope IDs assigned to the OAuth client by Cloudflare. */\n readonly scopes: ReadonlyArray<string>;\n /** Capabilities represented by those assigned scope IDs. */\n readonly capabilities: ProviderAuth.TokenValidation[\"capabilities\"];\n readonly clientAuth: ProviderAuth.OAuthMethod[\"clientAuth\"];\n}\n\n/** Describes a registered Cloudflare OAuth client and its assigned scope IDs. */\nexport function oauthMethod(options: OAuthMethodOptions): ProviderAuth.OAuthMethod {\n return {\n _tag: \"oauth2\",\n authorizationServer,\n capabilities: [...options.capabilities],\n clientAuth: options.clientAuth,\n scopes: [...options.scopes],\n };\n}\n\n/** Creates the Cloudflare token and OAuth authorization manifest. */\nexport function manifest(options: OAuthMethodOptions): ProviderAuth.Manifest {\n return {\n methods: [tokenMethod(options.capabilities), oauthMethod(options)],\n providerId: \"cloudflare\",\n };\n}\n\ntype CredentialOptions = Omit<Client.Options, \"accountId\" | \"token\" | \"tokenKind\">;\n\n/** Selects an explicit Cloudflare account or discovers it from an authorized domain. */\nexport type CredentialTarget =\n | {\n readonly accountId: string;\n readonly domain?: never;\n }\n | {\n readonly accountId?: never;\n readonly domain: DomainName.DomainName;\n };\n\nexport type SubjectResolverOptions = CredentialOptions & CredentialTarget;\n\n/** Configuration for validating a Cloudflare token against an account or authorized domain. */\nexport type TokenValidatorOptions = CredentialOptions &\n (\n | {\n readonly accountId: string;\n readonly domain?: never;\n readonly tokenKind?: \"account\" | \"user\";\n }\n | {\n readonly accountId?: never;\n readonly domain: DomainName.DomainName;\n readonly tokenKind?: \"account\" | \"user\";\n }\n );\n\n/** Resolves the Cloudflare account selected by a completed OAuth grant. */\nexport function subjectResolver(\n options: SubjectResolverOptions,\n): ProviderAuth.OAuthSubjectResolver {\n return (tokens: oauth.TokenEndpointResponse, accessToken: Secret.Value) =>\n Effect.gen(function* () {\n const accountId =\n options.accountId ??\n (yield* Client.discoverAuthorizationAccount({\n ...(options.baseUrl === undefined ? {} : { baseUrl: options.baseUrl }),\n domain: options.domain,\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n token: accessToken,\n }).pipe(Effect.map((account) => account.id)));\n if (options.accountId !== undefined) {\n yield* Client.make({\n accountId: options.accountId,\n ...(options.baseUrl === undefined ? {} : { baseUrl: options.baseUrl }),\n capabilities: options.capabilities,\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n token: accessToken,\n tokenKind: \"user\",\n }).listZones();\n }\n const now = yield* Clock.currentTimeMillis;\n return {\n accountId,\n expiresAt:\n typeof tokens.expires_in === \"number\" ? new Date(now + tokens.expires_in * 1_000) : null,\n };\n });\n}\n\n/** Creates a host callback that validates a Cloudflare API token. */\nexport function tokenValidator(\n options: TokenValidatorOptions,\n): (token: Secret.Value) => ReturnType<Client.Interface[\"validateToken\"]> {\n return (token) =>\n options.accountId === undefined\n ? Client.validateDomainToken({\n ...(options.baseUrl === undefined ? {} : { baseUrl: options.baseUrl }),\n capabilities: options.capabilities,\n domain: options.domain,\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n token,\n ...(options.tokenKind === undefined ? {} : { tokenKind: options.tokenKind }),\n })\n : Client.make({\n accountId: options.accountId,\n ...(options.baseUrl === undefined ? {} : { baseUrl: options.baseUrl }),\n capabilities: options.capabilities,\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n token,\n ...(options.tokenKind === undefined ? {} : { tokenKind: options.tokenKind }),\n }).validateToken();\n}\n\nexport type TokenConnectionOptions = TokenValidatorOptions & {\n readonly token: Secret.Value;\n};\n\n/** Creates a provider-independent token connection method backed by Cloudflare validation. */\nexport function tokenConnectionMethod(\n options: TokenConnectionOptions,\n): Extract<Connection.Method, { readonly _tag: \"Token\" }> {\n const requiredCapabilities = [...options.capabilities];\n return Connection.Method.Token({\n authenticate: Effect.fn(\"CloudflareAuth.authenticateToken\")(function* (token) {\n const validated = yield* tokenValidator(options)(token);\n const observedAt = new Date(yield* Clock.currentTimeMillis);\n return {\n capabilityEvidence: validated.capabilities.map((capability) => ({\n capability,\n evidence: ProviderAuthorization.Evidence.Introspected({ observedAt }),\n })),\n credential: { accessToken: token, refreshToken: null, tokenType: \"bearer\" },\n expiresAt: validated.expiresAt,\n providerAccountId: validated.accountId,\n providerContext: yield* contextCodec.encode({ tokenKind: options.tokenKind ?? \"user\" }),\n scopes: [...validated.scopes],\n } satisfies Connection.Authentication;\n }),\n providerId: \"cloudflare\",\n requiredCapabilities,\n token: options.token,\n });\n}\n\n/** Converts a completed Cloudflare OAuth grant into the canonical connection authentication. */\nexport const oauthAuthentication = Effect.fn(\"CloudflareAuth.oauthAuthentication\")(function* (\n options: SubjectResolverOptions & {\n readonly accessToken: Secret.Value;\n readonly tokens: oauth.TokenEndpointResponse;\n },\n) {\n const resolved = yield* subjectResolver(options)(options.tokens, options.accessToken);\n const observedAt = new Date(yield* Clock.currentTimeMillis);\n return {\n capabilityEvidence: options.capabilities.map((capability) => ({\n capability,\n evidence: ProviderAuthorization.Evidence.Introspected({ observedAt }),\n })),\n credential: {\n accessToken: options.accessToken,\n refreshToken:\n options.tokens.refresh_token === undefined\n ? null\n : Secret.Value.from(options.tokens.refresh_token),\n tokenType: options.tokens.token_type,\n },\n expiresAt: resolved.expiresAt,\n providerAccountId: resolved.accountId,\n providerContext: yield* contextCodec.encode({ tokenKind: \"user\" }),\n scopes: (options.tokens.scope ?? \"\").split(\" \").filter(Boolean),\n } satisfies Connection.Authentication;\n});\n\nexport type OAuthFlowOptions = SubjectResolverOptions & {\n readonly client: ProviderAuth.OAuthClientConfiguration;\n readonly clientAuth: ProviderAuth.OAuthMethod[\"clientAuth\"];\n readonly redirectUri: string;\n readonly scopes: ReadonlyArray<string>;\n};\n\n/** Creates Cloudflare's OAuth implementation of the common interactive connection capability. */\nexport function oauthFlow(options: OAuthFlowOptions): Connection.InteractiveFlow {\n const method = oauthMethod({\n capabilities: options.capabilities,\n clientAuth: options.clientAuth,\n scopes: options.scopes,\n });\n return {\n complete: Effect.fn(\"CloudflareAuth.oauthFlow.complete\")(function* (payload, callbackUrl) {\n const tokens = yield* AuthorizationCode.complete({\n callbackUrl,\n client: options.client,\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n method,\n payload,\n providerId: \"cloudflare\",\n });\n return yield* oauthAuthentication({\n ...(options.accountId === undefined\n ? { domain: options.domain }\n : { accountId: options.accountId }),\n ...(options.baseUrl === undefined ? {} : { baseUrl: options.baseUrl }),\n capabilities: options.capabilities,\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n accessToken: Secret.make(tokens.access_token),\n tokens,\n });\n }),\n method: \"oauth2\",\n providerId: \"cloudflare\",\n requiredCapabilities: [...options.capabilities],\n start: (continuationId) =>\n AuthorizationCode.start({\n client: options.client,\n method,\n redirectUri: options.redirectUri,\n state: continuationId,\n }),\n };\n}\n"],"mappings":";;;;;;;AAeA,MAAa,QAAQ,OAAO,GAAG,yBAAyB,CAAC,CAAC,WAAW,OAKlE;CACD,MAAM,SAAS,OAAO,OAAO;CAC7B,MAAM,eAAe,UAAU,OAAO,YAAY,QAAQ,EAAE,CAAC;CAC7D,MAAM,YAAY,UAAU,OAAO,OAAO,QAAQ,YAAY,CAAC;CAC/D,MAAM,mBAAmB,IAAI,IAAI,MAAM,OAAO,oBAAoB,sBAAsB;CACxF,iBAAiB,SAAS,IAAI,gBAAgB;EAC5C,WAAW,MAAM,OAAO;EACxB,gBAAgB;EAChB,uBAAuB;EACvB,cAAc,MAAM;EACpB,eAAe;EACf,OAAO,MAAM,OAAO,OAAO,KAAK,GAAG;EACnC,OAAO,MAAM;CACf,CAAC,CAAC,CAAC,SAAS;CACZ,OAAO;EACL;EACA,SAASA,OACP,KAAK,UAAU;GAAE;GAAc,aAAa,MAAM;GAAa,OAAO,MAAM;EAAM,CAAC,CACrF;CACF;AACF,CAAC;AAED,MAAa,WAAW,OAAO,GAAG,4BAA4B,CAAC,CAAC,WAAW,OAOxE;CACD,MAAM,UAAU,OAAO,cAAc,MAAM,OAAO;CAClD,IAAI,MAAM,YAAY,aAAa,IAAI,OAAO,MAAM,QAAQ,OAC1D,OAAO,OAAOC,UAAQ,8DAA8D;CAEtF,MAAM,SAAS,MAAM,OAAO;CAC5B,MAAM,SAAuB,EAAE,WAAW,MAAM,OAAO,SAAS;CAChE,MAAM,iBAAiB,OAAO,qBAAqB,MAAM,QAAQ,MAAM,MAAM;CAC7E,OAAO,OAAO,OAAO,WAAW;EAC9B,KAAK,OAAO,WAAW;GACrB,MAAM,WAAW,MAAM,qBAAqB,QAAQ,QAAQ,MAAM,aAAa,QAAQ,KAAK;GAC5F,MAAM,WAAW,MAAM,MAAM,8BAC3B,QACA,QACA,gBACA,UACA,QAAQ,aACR,QAAQ,cACR,eAAe,MAAM,OAAO,MAAM,CACpC;GACA,OAAO,MAAM,iCAAiC,QAAQ,QAAQ,QAAQ;EACxE;EACA,QAAQ,UACN,IAAIC,QAAiB;GACnB,UAAU;GACV,SAAS,iBAAiB,WAAW,QAAQ,MAAM,OAAO;GAC1D,WAAW;GACX,OAAO;EACT,CAAC;CACL,CAAC;AACH,CAAC;AAED,MAAM,gBAAgB,OAAO,OAAO;CAClC,cAAc,OAAO;CACrB,aAAa,OAAO;CACpB,OAAO,OAAO;AAChB,CAAC;AAED,SAAS,cAAc,SAAiE;CACtF,OAAO,OAAO,oBAAoB,OAAO,eAAe,aAAa,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC,KACxF,OAAO,eAEH,IAAIA,QAAiB;EACnB,UAAU;EACV,SAAS;EACT,WAAW;EACX,OAAO;CACT,CAAC,CACL,CACF;AACF;AAEA,SAAS,qBACP,QACA,QACmD;CACnD,QAAQ,OAAO,YAAf;EACE,KAAK,QACH,OAAO,OAAO,QAAQ,MAAM,KAAK,CAAC;EACpC,KAAK,uBACH,OAAO,OAAO,iBAAiB,KAAA,IAC3BD,UAAQ,iCAAiC,IACzC,OAAO,QAAQ,MAAM,kBAAkB,OAAO,aAAa,OAAO,CAAC,CAAC;EAC1E,KAAK,sBACH,OAAO,OAAO,iBAAiB,KAAA,IAC3BA,UAAQ,iCAAiC,IACzC,OAAO,QAAQ,MAAM,iBAAiB,OAAO,aAAa,OAAO,CAAC,CAAC;CAC3E;AACF;AAEA,SAAS,eACP,qBACA,QACmC;CACnC,OAAO,wBAAwB,KAAA,IAC3B,EAAE,OAAO,IACT;EACE;GACC,MAAM,eAAe,KAAK,YACzB,oBAAoB,KAAK;GAAE,GAAG;GAAS,MAAM,QAAQ;EAAK,CAAC;CAC/D;AACN;AAEA,MAAMA,aAAW,YACf,OAAO,KACL,IAAIC,QAAiB;CACnB,UAAU;CACV;CACA,WAAW;CACX,OAAO;AACT,CAAC,CACH;AAEF,SAAS,YACP,QACA,MAC6C;CAC7C,OAAO,OAAO,YAAY,IAAI,CAAC,CAAC,KAC9B,OAAO,UACJ,UACC,IAAIA,QAAiB;EACnB,UAAU;EACV,SAAS,MAAM;EACf,WAAW;EACX,OAAO;CACT,CAAC,CACL,CACF;AACF;AAEA,SAAS,OAAO,QAAuB,OAA4D;CACjG,OAAO,OAAO,OAAO,WAAW,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,KAC/D,OAAO,UACJ,UACC,IAAIA,QAAiB;EACnB,UAAU;EACV,SAAS,MAAM;EACf,WAAW;EACX,OAAO;CACT,CAAC,CACL,CACF;AACF;AAEA,SAAS,UAAU,OAA2B;CAC5C,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,OAAO,UAAU,OAAO,aAAa,IAAI;CAC5D,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,CAAC,WAAW,KAAK,EAAE;AAClF;;;AC/KA,MAAa,cAAcC,OAAE,OAAO;CAClC,MAAMA,OAAE;CACR,SAASA,OAAE;AACb,CAAC;AAGD,MAAa,aAAaA,OAAE,OAAO;CACjC,OAAOA,OAAE,YAAYA,OAAE,MAAM;CAC7B,MAAMA,OAAE,YAAYA,OAAE,MAAM;CAC5B,UAAUA,OAAE,YAAYA,OAAE,MAAM;CAChC,aAAaA,OAAE,YAAYA,OAAE,MAAM;CACnC,aAAaA,OAAE,YAAYA,OAAE,MAAM;AACrC,CAAC;AAED,MAAM,UAAUA,OAAE,OAAO;CACvB,MAAMA,OAAE,YAAYA,OAAE,MAAM;CAC5B,SAASA,OAAE;AACb,CAAC;AAED,MAAa,eAAeA,OAAE,OAAO;CACnC,QAAQA,OAAE,MAAM,WAAW;CAC3B,UAAUA,OAAE,MAAM,OAAO;CACzB,SAASA,OAAE;AACb,CAAC;AAED,MAAa,UAAUA,OAAE,OAAO;CAC9B,IAAIA,OAAE;CACN,MAAMA,OAAE;AACV,CAAC;AAGD,MAAa,OAAOA,OAAE,OAAO;CAC3B,SAAS;CACT,IAAIA,OAAE;CACN,MAAMA,OAAE;CACR,cAAcA,OAAE,MAAMA,OAAE,MAAM;CAC9B,QAAQA,OAAE,YAAYA,OAAE,MAAM;AAChC,CAAC;AAGD,MAAa,SAASA,OAAE,OAAO;CAC7B,SAASA,OAAE,YAAYA,OAAE,MAAM;CAC/B,MAAMA,OAAE,YAAYA,OAAE,OAAO;CAC7B,IAAIA,OAAE;CACN,MAAMA,OAAE;CACR,UAAUA,OAAE,YAAYA,OAAE,MAAM;CAChC,SAASA,OAAE,YAAYA,OAAE,OAAO;CAChC,KAAKA,OAAE;CACP,MAAMA,OAAE;AACV,CAAC;AAGD,MAAa,QAAQA,OAAE,OAAO;CAC5B,YAAYA,OAAE,YAAYA,OAAE,MAAM;CAClC,IAAIA,OAAE;CACN,YAAYA,OAAE,YAAYA,OAAE,MAAM;CAClC,QAAQA,OAAE,SAAS;EAAC;EAAU;EAAY;CAAS,CAAC;AACtD,CAAC;AAGD,MAAa,mBAAmBA,OAAE,OAAO;CACvC,QAAQA,OAAE,MAAM,WAAW;CAC3B,UAAUA,OAAE,MAAM,OAAO;CACzB,QAAQA,OAAE,MAAM,IAAI;CACpB,aAAaA,OAAE,YAAY,UAAU;CACrC,SAASA,OAAE;AACb,CAAC;AACD,MAAa,qBAAqBA,OAAE,OAAO;CACzC,QAAQA,OAAE,MAAM,WAAW;CAC3B,UAAUA,OAAE,MAAM,OAAO;CACzB,QAAQA,OAAE,MAAM,MAAM;CACtB,aAAaA,OAAE,YAAY,UAAU;CACrC,SAASA,OAAE;AACb,CAAC;AACD,MAAa,iBAAiBA,OAAE,OAAO;CACrC,QAAQA,OAAE,MAAM,WAAW;CAC3B,UAAUA,OAAE,MAAM,OAAO;CACzB,QAAQ;CACR,SAASA,OAAE;AACb,CAAC;AACD,MAAa,gBAAgBA,OAAE,OAAO;CACpC,QAAQA,OAAE,MAAM,WAAW;CAC3B,UAAUA,OAAE,MAAM,OAAO;CACzB,QAAQ;CACR,SAASA,OAAE;AACb,CAAC;;;AChFD,MAAMC,SAAOC,OAAE,OAAO;CACpB,OAAOA,OAAE,YAAYA,OAAE,MAAM;CAC7B,MAAMA,OAAE,YAAYA,OAAE,MAAM;CAC5B,UAAUA,OAAE,YAAYA,OAAE,MAAM;CAChC,KAAKA,OAAE,YAAYA,OAAE,MAAM;CAC3B,QAAQA,OAAE,YAAYA,OAAE,MAAM;CAC9B,OAAOA,OAAE,YAAYA,OAAE,MAAM;CAC7B,QAAQA,OAAE,YAAYA,OAAE,MAAM;AAChC,CAAC;AAID,MAAaC,WAAS,OAAO,GAAG,0BAA0B,CAAC,EAAE,WAC3D,OAAO,IAAI,aAAa;CACtB,MAAM,OAAO,OAAOC,SAAkB,OAAO,IAAI,CAAC,CAAC,KACjD,OAAO,MAAM;EAAE,iBAAiB;EAAM,YAAY,UAAU;CAAM,CAAC,CACrE;CACA,IAAI,SAAS,MAAM,OAAO,OAAO,aAAa,MAAM;CACpD,MAAM,SAAS;EACb,UAAU;GACR,WAAW;GACX,YAAY,OAAO,YAAY,OAAO,uBAAuB;GAC7D,SAAS;EACX;EACA;EACA,QAAQ,OAAO,SAAS,UAAU,cAAc;EAChD,KAAK,OAAO,QAAQ,IAAI,OAAO,OAAO;CACxC;CACA,MAAM,gBACJ,OAAO,YAAY,KAAA,IACf,OAAO,KAAKC,UAAQ,gBAAgB,cAAc,OAAO,KAAK,uBAAuB,CAAC,IACtF,OAAO,QAAQ,OAAO,OAAO;CAEnC,QAAQ,OAAO,MAAf;EACE,KAAK;EACL,KAAK,QACH,OAAO,OAAOC,SAAiB;GAC7B,GAAG;GACH,MAAM,OAAO;GACb,SAAS,OAAO,QAAQ;EAC1B,CAAC,CAAC,CAAC,KAAK,OAAO,UAAU,UAAUD,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CAAC;EAC5E,KAAK;EACL,KAAK,MACH,OAAO,OAAOC,SAAiB;GAC7B,GAAG;GACH,MAAM,OAAO;GACb,QAAQ,OAAO,QAAQ;EACzB,CAAC,CAAC,CAAC,KAAK,OAAO,UAAU,UAAUD,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CAAC;EAC5E,KAAK,OACH,OAAO,OAAOC,SAAiB;GAC7B,GAAG;GACH,MAAM;GACN,OAAO,OAAO,QAAQ;EACxB,CAAC,CAAC,CAAC,KAAK,OAAO,UAAU,UAAUD,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CAAC;EAC5E,KAAK,MACH,OAAO,OAAOC,SAAiB;GAC7B,GAAG;GACH,MAAM;GACN,UAAU,OAAO,QAAQ;GACzB,UAAU,OAAO;EACnB,CAAC,CAAC,CAAC,KAAK,OAAO,UAAU,UAAUD,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CAAC;EAC5E,KAAK,OAAO;GACV,MAAM,OAAO,OAAO,WAAW,MAAM;GACrC,OAAO,OAAOC,SAAiB;IAAE,GAAG;IAAQ,MAAM;IAAO,GAAG;GAAK,CAAC,CAAC,CAAC,KAClE,OAAO,UAAU,UAAUD,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CACnE;EACF;EACA,KAAK,OAAO;GACV,MAAM,OAAO,OAAO,WAAW,MAAM;GACrC,OAAO,OAAOC,SAAiB;IAAE,GAAG;IAAQ,MAAM;IAAO,GAAG;GAAK,CAAC,CAAC,CAAC,KAClE,OAAO,UAAU,UAAUD,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CACnE;EACF;EACA,SACE,OAAO,OAAO,aAAa,MAAM;CACrC;AACF,CAAC,CACH;AAEA,MAAM,eAAe,OAAO,GAAG,gCAAgC,CAAC,EAAE,WAChEH,OAAE,oBAAoBK,MAAgB,CAAC,CAAC;CACtC,MAAM;CACN,MAAM,OAAO;CACb,kBAAkB,OAAO;CACzB,cAAc,OAAO;AACvB,CAAC,CAAC,CAAC,KAAK,OAAO,UAAU,UAAUF,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CAAC,CAC5E;AAEA,SAAgB,OAAO,QAAyC;CAC9D,MAAM,SAAS;EACb,MAAM,OAAO;EACb,SAAS;EACT,KAAK,OAAO,OAAO;EACnB,MAAM,OAAO;CACf;CACA,QAAQ,OAAO,MAAf;EACE,KAAK;EACL,KAAK,QACH,OAAO;GAAE,GAAG;GAAQ,SAAS,OAAO;EAAQ;EAC9C,KAAK;EACL,KAAK,MACH,OAAO;GAAE,GAAG;GAAQ,SAAS,OAAO;EAAO;EAC7C,KAAK,OACH,OAAO;GAAE,GAAG;GAAQ,SAAS,OAAO;EAAM;EAC5C,KAAK,MACH,OAAO;GAAE,GAAG;GAAQ,SAAS,OAAO;GAAU,UAAU,OAAO;EAAS;EAC1E,KAAK,OACH,OAAO;GACL,GAAG;GACH,MAAM;IAAE,OAAO,OAAO;IAAO,KAAK,OAAO;IAAK,OAAO,OAAO;GAAM;EACpE;EACF,KAAK,OACH,OAAO;GACL,GAAG;GACH,MAAM;IACJ,MAAM,OAAO;IACb,UAAU,OAAO;IACjB,QAAQ,OAAO;IACf,QAAQ,OAAO;GACjB;EACF;CACJ;AACF;AAEA,MAAM,aAAa,OAAO,GAAG,8BAA8B,CAAC,EAAE,WAC5DH,OAAE,oBAAoBD,MAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KACvC,OAAO,UAAU,UAAUI,UAAQ,gBAAgB,MAAM,OAAO,CAAC,CACnE,CACF;AAEA,SAASA,UACP,WACA,SACA,SAAqD,CAAC,GACnC;CACnB,OAAO,IAAIG,MAAkB;EAC3B;EACA;EACA,YAAY;EACZ,QAAQ,OAAO,UAAU;CAC3B,CAAC;AACH;;;;;;;;;;AClGA,SAAgB,UAAU,QAAyC;CACjE,OAAO;EACL,YAAY,SACV,OAAO,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,KACzB,OAAO,KAAK,UACV,MAAM,KAAK,UAAU;GACnB,GAAG;GACH,QAAQ,KAAK,WAAW,YAAY,KAAK,WAAW,YAAY,KAAK,SAAS;EAChF,EAAE,CACJ,CACF;EACF,UAAU;CACZ;AACF;AAcA,MAAM,iBAAiB,YAA+B;CACpD,MAAM,QAAQ,QAAQ,SAAS,WAAW;CAC1C,MAAM,WAAW,QAAQ,WAAW,uCAAA,CAAwC,QAAQ,OAAO,EAAE;CAE7F,MAAM,UAAU,OAAO,GAAG,0BAA0B,CAAC,EAClD,MAAc,WAAmB,SAChC,OAAO,IAAI,aAAa;EACtB,MAAM,WAAW,OAAO,OAAO,WAAW;GACxC,WACE,MAAM,GAAG,UAAU,QAAQ;IACzB,GAAG;IACH,SAAS;KACP,QAAQ;KACR,eAAe,UAAU,QAAQ,MAAM,OAAO;KAC9C,GAAI,MAAM,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,mBAAmB;KACzE,GAAG,MAAM;IACX;GACF,CAAC;GACH,aACE,QAAQ,WAAW,6BAA6B,EAC9C,QAAQ,YACV,CAAC;EACL,CAAC;EAkBD,OAAO;GAAE,MAAA,OAjBW,OAAO,WAAW;IACpC,WAAW,SAAS,KAAK;IACzB,aAAa;KACX,MAAM,eAAe,WAAW,SAAS,QAAQ,IAAI,aAAa,CAAC;KACnE,OAAO,QACL,WACA,SAAS,KACL,4CACA,uCAAuC,SAAS,UACpD;MACE,QAAQ,SAAS,KAAK,aAAa,OAAO,SAAS,MAAM;MACzD,GAAI,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa;MACrD,QAAQ,SAAS;KACnB,CACF;IACF;GACF,CAAC;GACc;EAAS;CAC1B,CAAC,CACL;CAEA,MAAM,gBAAgB,OAAO,GAAG,gCAAgC,CAAC,EAC9D,WAA+B,MAAyC,SACvE,OAAO,IAAI,aAAa;EACtB,MAAM,QAAQ,IAAI,gBAAgB;GAAE,MAAM,OAAO,IAAI;GAAG,UAAU;EAAK,CAAC;EACxE,MAAM,IAAI,QAAQ,iCAAiC;EACnD,IAAI,cAAc,KAAA,GAAW,MAAM,IAAI,cAAc,SAAS;EAC9D,IAAI,SAAS,KAAA,GAAW,MAAM,IAAI,QAAQ,IAAI;EAC9C,MAAM,EAAE,MAAM,aAAa,OAAO,QAAQ,UAAU,SAAS,WAAW;EACxE,OAAO,cAAc,MAAM,aAAa,QAAQ;EAChD,OAAO,OAAO,OAAOC,kBAA2B,MAAM,aAAa,QAAQ;CAC7E,CAAC,CACL;CAiDA,OAAO;EAAE,UA/CQ,OAAO,GAAG,2BAA2B,CAAC,EACpD,WAAoB,SACnB,OAAO,IAAI,aAAa;GACtB,MAAM,QAA8B,CAAC;GACrC,IAAI,OAAO;GACX,OAAO,MAAM;IACX,MAAM,WAAW,OAAO,cAAc,WAAW,MAAM,IAAI;IAC3D,MAAM,KAAK,GAAG,SAAS,MAAM;IAC7B,MAAM,aAAa,SAAS,aAAa;IACzC,IACG,eAAe,KAAA,KAAa,QAAQ,cACpC,eAAe,KAAA,KAAa,SAAS,OAAO,SAAS,IAEtD,OAAO;IAET,QAAQ;GACV;EACF,CAAC,CA8BW;EAAG,cA3BE,OAAO,GAAG,+BAA+B,CAAC,EAAE,SAC/D,OAAO,IAAI,aAAa;GACtB,MAAM,EAAE,MAAM,aAAa,OAAO,QAAQ,MAAM,eAAe;GAC/D,OAAO,cAAc,MAAM,iBAAiB,QAAQ;GACpD,MAAM,WAAW,OAAO,OAAOC,eAAwB,MAAM,iBAAiB,QAAQ;GACtF,IAAI,SAAS,OAAO,WAAW,UAC7B,OAAO,OAAO,OAAO,KACnB,QAAQ,iBAAiB,uBAAuB,SAAS,OAAO,UAAU;IACxE,QAAQ;IACR,QAAQ,SAAS;GACnB,CAAC,CACH;GAEF,MAAM,YACJ,SAAS,OAAO,eAAe,KAAA,IAAY,OAAO,IAAI,KAAK,SAAS,OAAO,UAAU;GACvF,IAAI,cAAc,QAAQ,OAAO,MAAM,UAAU,QAAQ,CAAC,GACxD,OAAO,OAAO,OAAO,KACnB,QAAQ,iBAAiB,oDAAoD;IAC3E,QAAQ;IACR,QAAQ,SAAS;GACnB,CAAC,CACH;GAEF,OAAO;EACT,CAAC,CAG2B;EAAG;CAAQ;AAC3C;AAEA,MAAM,kBAAkB,OAAO,GAAG,kCAAkC,CAAC,EAClE,YACC,OAAO,IAAI,aAAa;CACtB,MAAM,EAAE,aAAa,cAAc,OAAO;CAC1C,KAAK,MAAM,aAAaC,WAAiB,QAAQ,MAAM,GAAG;EACxD,MAAM,UAAU,OAAO,SAAS,KAAA,GAAW,SAAS;EACpD,MAAM,QAAQ,QAAQ;EACtB,IAAI,QAAQ,WAAW,GAAG;EAC1B,IAAI,QAAQ,WAAW,KAAK,UAAU,KAAA,GAAW,OAAO,MAAM;EAC9D,OAAO,OAAO,OAAO,KACnB,QACE,mBACA,uDAAuD,aACvD,EAAE,QAAQ,WAAW,CACvB,CACF;CACF;CACA,OAAO,OAAO,OAAO,KACnB,QACE,mBACA,oDAAoD,QAAQ,UAC5D,EAAE,QAAQ,YAAY,CACxB,CACF;AACF,CAAC,CACL;AAEA,MAAa,+BAA+B;AAE5C,MAAa,sBAAsB,OAAO,GAAG,sCAAsC,CAAC,EACjF,YACC,OAAO,IAAI,aAAa;CACtB,MAAM,YAAY,cAAc,OAAO;CACvC,MAAM,UAAU,QAAQ,cAAc,YAAY,OAAO,gBAAgB,OAAO,IAAI,KAAA;CACpF,MAAM,YAAY,OAAO,UAAU,aACjC,YAAY,KAAA,IACR,wBACA,aAAa,mBAAmB,QAAQ,EAAE,EAAE,eAClD;CAEA,OAAO;EACL,YAFwB,YAAY,OAAO,gBAAgB,OAAO,GAAA,CAErC;EAC7B,cAAc,QAAQ;EACtB;EACA,QAAQ,CAAC;CACX;AACF,CAAC,CACL;;AAGA,SAAgB,KAAK,SAA6B;CAChD,MAAM,EAAE,UAAU,cAAc,YAAY,cAAc,OAAO;CAEjE,MAAM,cAAc,OAAO,GAAG,8BAA8B,CAAC,EAAE,SAC7D,OAAO,IAAI,aAAa;EACtB,MAAM,UAAU,OAAO,SAAS,QAAQ,WAAW,IAAI;EACvD,MAAM,QAAQ,QAAQ;EACtB,IAAI,QAAQ,WAAW,KAAK,UAAU,KAAA,GAAW,OAAO;EACxD,OAAO,OAAO,OAAO,KACnB,QACE,eACA,QAAQ,WAAW,IACf,mBAAmB,KAAK,4BAA4B,QAAQ,cAC5D,4CAA4C,KAAK,cAAc,QAAQ,aAC3E,EAAE,QAAQ,QAAQ,WAAW,IAAI,cAAc,WAAW,CAC5D,CACF;CACF,CAAC,CACH;CAEA,MAAM,cAAc,OAAO,GAAG,8BAA8B,CAAC,EAAE,aAC7D,OAAO,IAAI,aAAa;EACtB,MAAM,OAAO,OAAO,YAAY,QAAQ;EACxC,MAAM,UAAqC,CAAC;EAC5C,IAAI,OAAO;EACX,OAAO,MAAM;GACX,MAAM,QAAQ,IAAI,gBAAgB;IAAE,MAAM,OAAO,IAAI;IAAG,UAAU;GAAM,CAAC;GACzE,MAAM,EAAE,MAAM,aAAa,OAAO,QAChC,UAAU,mBAAmB,KAAK,EAAE,EAAE,eAAe,SACrD,aACF;GACA,OAAO,cAAc,MAAM,eAAe,QAAQ;GAClD,MAAM,WAAW,OAAO,OAAOC,oBAA6B,MAAM,eAAe,QAAQ;GACzF,QAAQ,KAAK,GAAI,OAAO,OAAO,QAAQ,SAAS,QAAQC,QAAc,CAAE;GACxE,MAAM,aAAa,SAAS,aAAa;GACzC,IACG,eAAe,KAAA,KAAa,QAAQ,cACpC,eAAe,KAAA,KAAa,SAAS,OAAO,SAAS,KAEtD,OAAO;GAET,QAAQ;EACV;CACF,CAAC,CACH;CAEA,MAAM,eAAe,OAAO,GAAG,+BAA+B,CAAC,EAC5D,UAAiC,WAChC,OAAO,IAAI,aAAa;EACtB,MAAM,OAAO,OAAO,YAAY,QAAQ;EACxC,MAAM,EAAE,MAAM,aAAa,OAAO,QAChC,UAAU,mBAAmB,KAAK,EAAE,EAAE,eACtC,gBACA;GAAE,MAAM,KAAK,UAAUC,OAAe,MAAM,CAAC;GAAG,QAAQ;EAAO,CACjE;EACA,OAAO,cAAc,MAAM,gBAAgB,QAAQ;EAEnD,OAAO,EAAE,mBAAkB,OADH,OAAOC,gBAAyB,MAAM,gBAAgB,QAAQ,EAAA,CAClD,OAAO,GAAG;CAChD,CAAC,CACL;CAEA,MAAM,YAAY,OAAO,GAAG,4BAA4B,CAAC,EACtD,UAAiC,qBAChC,OAAO,IAAI,aAAa;EACtB,MAAM,OAAO,OAAO,YAAY,QAAQ;EACxC,MAAM,EAAE,MAAM,aAAa,OAAO,QAChC,UAAU,mBAAmB,KAAK,EAAE,EAAE,eAAe,mBAAmB,gBAAgB,KACxF,WACF;EACA,IAAI,SAAS,WAAW,KAAK,OAAO;EACpC,OAAO,cAAc,MAAM,aAAa,QAAQ;EAChD,MAAM,WAAW,OAAO,OAAOA,gBAAyB,MAAM,aAAa,QAAQ;EACnF,OAAO,OAAOF,SAAe,SAAS,MAAM;CAC9C,CAAC,CACL;CAgDA,OAAO;EACL,IAAI;EACJ;EACA,cAjDmB,OAAO,GAAG,+BAA+B,CAAC,EAC5D,UAAiC,qBAChC,OAAO,IAAI,aAAa;GACtB,MAAM,OAAO,OAAO,YAAY,QAAQ;GACxC,MAAM,EAAE,MAAM,aAAa,OAAO,QAChC,UAAU,mBAAmB,KAAK,EAAE,EAAE,eAAe,mBAAmB,gBAAgB,KACxF,gBACA,EAAE,QAAQ,SAAS,CACrB;GACA,OAAO,cAAc,MAAM,gBAAgB,QAAQ;EACrD,CAAC,CAuCQ;EACX;EACA,cAtCmB,OAAO,GAAG,+BAA+B,CAAC,OAC7D,SAAS,CAAC,CAAC,KACT,OAAO,KAAK,UAAU;GACpB,MAAM,2BAAW,IAAI,IAA8B;GACnD,KAAK,MAAM,QAAQ,OAAO,SAAS,IAAI,KAAK,QAAQ,IAAI,KAAK,OAAO;GACpE,OAAO,CAAC,GAAG,SAAS,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;EACzF,CAAC,CACH,CA+BW;EACX;EACA,WA9BgB,OAAO,GAAG,4BAA4B,CAAC,EAAE,QAAwB,CAAC,MAClF,SAAS,MAAM,aAAa,QAAQ,WAAW,MAAM,IAAI,CAAC,CAAC,KACzD,OAAO,SAAS,UAAU,OAAO,QAAQ,OAAO,WAAW,CAAC,CAC9D,CA2BQ;EACR,eAzBoB,OAAO,GAAG,gCAAgC,CAAC,OAC/D,OAAO,IAAI,aAAa;GACtB,MAAM,OACJ,QAAQ,cAAc,YAClB,aAAa,mBAAmB,QAAQ,SAAS,EAAE,kBACnD;GACN,MAAM,YAAY,OAAO,aAAa,IAAI;GAC1C,OAAO,SAAS,QAAQ,SAAS;GACjC,OAAO;IACL,WAAW,QAAQ;IACnB,cAAc,QAAQ;IACtB;IACA,QAAQ,CAAC;GACX;EACF,CAAC,CAWW;CACd;AACF;AAEA,MAAM,cAAc,OAAO,GAAG,8BAA8B,CAAC,EAAE,SAC7D,OAAO,IAAI,aAAa;CACtB,MAAM,OAAO,OAAOG,SAAkB,KAAK,IAAI,CAAC,CAAC,KAC/C,OAAO,UAAU,UAAU,QAAQ,aAAa,MAAM,SAAS,EAAE,QAAQ,WAAW,CAAC,CAAC,CACxF;CACA,MAAM,cAAc,OAAO,OAAO,QAAQ,KAAK,eAAe,eAC5DA,SAAkB,UAAU,CAAC,CAAC,KAC5B,OAAO,UAAU,UAAU,QAAQ,aAAa,MAAM,SAAS,EAAE,QAAQ,WAAW,CAAC,CAAC,CACxF,CACF;CACA,OAAO;EACL,WAAW,KAAK,QAAQ;EACxB,IAAI,KAAK;EACT;EACA;EACA,QAAQ,KAAK,UAAU;CACzB;AACF,CAAC,CACH;AAEA,SAAS,OACP,QACA,OACA,WACA,UACqC;CACrC,OAAOC,OAAE,oBAAoB,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAC1C,OAAO,UAAU,UACf,QAAQ,WAAW,uDAAuD,MAAM,WAAW;EACzF,QAAQ;EACR,QAAQ,SAAS;CACnB,CAAC,CACH,CACF;AACF;AAEA,SAAS,cACP,OACA,WACA,UACwC;CACxC,OAAOA,OAAE,oBAAoBC,YAAqB,CAAC,CAAC,KAAK,CAAC,CAAC,KACzD,OAAO,eACL,QAAQ,WAAW,4DAA4D;EAC7E,QAAQ;EACR,QAAQ,SAAS;CACnB,CAAC,CACH,GACA,OAAO,SAAS,aAAa;EAC3B,IAAI,SAAS,MAAM,SAAS,SAAS,OAAO,OAAO;EACnD,MAAM,SAAS,SAAS,OAAO;EAC/B,MAAM,eAAe,WAAW,SAAS,QAAQ,IAAI,aAAa,CAAC;EACnE,OAAO,OAAO,KACZ,QACE,WACA,QAAQ,WAAW,uCAAuC,SAAS,UACnE;GACE,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK;GACpD,QAAQ,OAAO,SAAS,QAAQ,QAAQ,IAAI;GAC5C,GAAI,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa;GACrD,QAAQ,SAAS;EACnB,CACF,CACF;CACF,CAAC,CACH;AACF;AAEA,SAAS,OAAO,QAAgB,MAAwC;CACtE,IAAI,WAAW,KAAK,OAAO;CAC3B,IAAI,WAAW,KAAK,OAAO;CAC3B,IAAI,WAAW,KAAK,OAAO;CAC3B,IAAI,WAAW,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS,OAAO,OAAO;CACjF,IAAI,WAAW,KAAK,OAAO;CAC3B,IAAI,UAAU,KAAK,OAAO;CAC1B,OAAO;AACT;AAEA,SAAS,WAAW,OAA0C;CAC5D,IAAI,UAAU,MAAM,OAAO,KAAA;CAC3B,MAAM,UAAU,OAAO,KAAK;CAC5B,IAAI,OAAO,SAAS,OAAO,GAAG,OAAO,KAAK,IAAI,GAAG,UAAU,GAAK;CAChE,MAAM,OAAO,KAAK,MAAM,KAAK;CAC7B,OAAO,OAAO,MAAM,IAAI,IAAI,KAAA,IAAY,KAAK,IAAI,GAAG,OAAO,KAAK,IAAI,CAAC;AACvE;AAEA,SAAS,QACP,WACA,SACA,SAA0F,CAAC,GACxE;CACnB,OAAO,IAAIC,MAAkB;EAC3B,GAAG;EACH;EACA;EACA,YAAY;CACd,CAAC;AACH;;;;;;;;;;;;;;ACrcA,MAAM,sBAAsB;CAC1B,wBAAwB;CACxB,QAAQ;CACR,qBAAqB;CACrB,gBAAgB;AAClB;AAEA,MAAMC,YAAU,OAAO,OAAO,EAAE,WAAW,OAAO,SAAS,CAAC,WAAW,MAAM,CAAC,EAAE,CAAC;AAEjF,MAAa,eAAeC,MAAsB,iBAAiBD,SAAO;;AAG1E,SAAgB,YACd,cAC+E;CAC/E,OAAO;EACL,MAAM;EACN,cAAc,CAAC,GAAG,YAAY;EAC9B,iBAAiB;CACnB;AACF;;AAWA,SAAgB,YAAY,SAAuD;CACjF,OAAO;EACL,MAAM;EACN;EACA,cAAc,CAAC,GAAG,QAAQ,YAAY;EACtC,YAAY,QAAQ;EACpB,QAAQ,CAAC,GAAG,QAAQ,MAAM;CAC5B;AACF;;AAGA,SAAgB,SAAS,SAAoD;CAC3E,OAAO;EACL,SAAS,CAAC,YAAY,QAAQ,YAAY,GAAG,YAAY,OAAO,CAAC;EACjE,YAAY;CACd;AACF;;AAiCA,SAAgB,gBACd,SACmC;CACnC,QAAQ,QAAqC,gBAC3C,OAAO,IAAI,aAAa;EACtB,MAAM,YACJ,QAAQ,cACP,OAAOE,6BAAoC;GAC1C,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;GACpE,QAAQ,QAAQ;GAChB,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;GAC9D,OAAO;EACT,CAAC,CAAC,CAAC,KAAK,OAAO,KAAK,YAAY,QAAQ,EAAE,CAAC;EAC7C,IAAI,QAAQ,cAAc,KAAA,GACxB,OAAOC,KAAY;GACjB,WAAW,QAAQ;GACnB,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;GACpE,cAAc,QAAQ;GACtB,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;GAC9D,OAAO;GACP,WAAW;EACb,CAAC,CAAC,CAAC,UAAU;EAEf,MAAM,MAAM,OAAO,MAAM;EACzB,OAAO;GACL;GACA,WACE,OAAO,OAAO,eAAe,WAAW,IAAI,KAAK,MAAM,OAAO,aAAa,GAAK,IAAI;EACxF;CACF,CAAC;AACL;;AAGA,SAAgB,eACd,SACwE;CACxE,QAAQ,UACN,QAAQ,cAAc,KAAA,IAClBC,oBAA2B;EACzB,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;EACpE,cAAc,QAAQ;EACtB,QAAQ,QAAQ;EAChB,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;EAC9D;EACA,GAAI,QAAQ,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;CAC5E,CAAC,IACDD,KAAY;EACV,WAAW,QAAQ;EACnB,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;EACpE,cAAc,QAAQ;EACtB,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;EAC9D;EACA,GAAI,QAAQ,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;CAC5E,CAAC,CAAC,CAAC,cAAc;AACzB;;AAOA,SAAgB,sBACd,SACwD;CACxD,MAAM,uBAAuB,CAAC,GAAG,QAAQ,YAAY;CACrD,OAAA,OAAyB,MAAM;EAC7B,cAAc,OAAO,GAAG,kCAAkC,CAAC,CAAC,WAAW,OAAO;GAC5E,MAAM,YAAY,OAAO,eAAe,OAAO,CAAC,CAAC,KAAK;GACtD,MAAM,aAAa,IAAI,KAAK,OAAO,MAAM,iBAAiB;GAC1D,OAAO;IACL,oBAAoB,UAAU,aAAa,KAAK,gBAAgB;KAC9D;KACA,UAAA,SAAyC,aAAa,EAAE,WAAW,CAAC;IACtE,EAAE;IACF,YAAY;KAAE,aAAa;KAAO,cAAc;KAAM,WAAW;IAAS;IAC1E,WAAW,UAAU;IACrB,mBAAmB,UAAU;IAC7B,iBAAiB,OAAO,aAAa,OAAO,EAAE,WAAW,QAAQ,aAAa,OAAO,CAAC;IACtF,QAAQ,CAAC,GAAG,UAAU,MAAM;GAC9B;EACF,CAAC;EACD,YAAY;EACZ;EACA,OAAO,QAAQ;CACjB,CAAC;AACH;;AAGA,MAAa,sBAAsB,OAAO,GAAG,oCAAoC,CAAC,CAAC,WACjF,SAIA;CACA,MAAM,WAAW,OAAO,gBAAgB,OAAO,CAAC,CAAC,QAAQ,QAAQ,QAAQ,WAAW;CACpF,MAAM,aAAa,IAAI,KAAK,OAAO,MAAM,iBAAiB;CAC1D,OAAO;EACL,oBAAoB,QAAQ,aAAa,KAAK,gBAAgB;GAC5D;GACA,UAAA,SAAyC,aAAa,EAAE,WAAW,CAAC;EACtE,EAAE;EACF,YAAY;GACV,aAAa,QAAQ;GACrB,cACE,QAAQ,OAAO,kBAAkB,KAAA,IAC7B,OAAA,MACa,KAAK,QAAQ,OAAO,aAAa;GACpD,WAAW,QAAQ,OAAO;EAC5B;EACA,WAAW,SAAS;EACpB,mBAAmB,SAAS;EAC5B,iBAAiB,OAAO,aAAa,OAAO,EAAE,WAAW,OAAO,CAAC;EACjE,SAAS,QAAQ,OAAO,SAAS,GAAA,CAAI,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;CAChE;AACF,CAAC;;AAUD,SAAgB,UAAU,SAAuD;CAC/E,MAAM,SAAS,YAAY;EACzB,cAAc,QAAQ;EACtB,YAAY,QAAQ;EACpB,QAAQ,QAAQ;CAClB,CAAC;CACD,OAAO;EACL,UAAU,OAAO,GAAG,mCAAmC,CAAC,CAAC,WAAW,SAAS,aAAa;GACxF,MAAM,SAAS,OAAOE,SAA2B;IAC/C;IACA,QAAQ,QAAQ;IAChB,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;IAC9D;IACA;IACA,YAAY;GACd,CAAC;GACD,OAAO,OAAO,oBAAoB;IAChC,GAAI,QAAQ,cAAc,KAAA,IACtB,EAAE,QAAQ,QAAQ,OAAO,IACzB,EAAE,WAAW,QAAQ,UAAU;IACnC,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;IACpE,cAAc,QAAQ;IACtB,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;IAC9D,aAAaC,OAAY,OAAO,YAAY;IAC5C;GACF,CAAC;EACH,CAAC;EACD,QAAQ;EACR,YAAY;EACZ,sBAAsB,CAAC,GAAG,QAAQ,YAAY;EAC9C,QAAQ,mBACNC,MAAwB;GACtB,QAAQ,QAAQ;GAChB;GACA,aAAa,QAAQ;GACrB,OAAO;EACT,CAAC;CACL;AACF"}
|
|
@@ -1,33 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
var secret_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
-
Value: () => Value,
|
|
7
|
-
make: () => make$1
|
|
8
|
-
});
|
|
9
|
-
/** A deliberately non-serializable credential value. */
|
|
10
|
-
var Value = class Value {
|
|
11
|
-
#value;
|
|
12
|
-
constructor(value) {
|
|
13
|
-
this.#value = value;
|
|
14
|
-
}
|
|
15
|
-
static from(value) {
|
|
16
|
-
if (value.length === 0) throw new Error("Secret values cannot be empty");
|
|
17
|
-
return new Value(value);
|
|
18
|
-
}
|
|
19
|
-
expose() {
|
|
20
|
-
return this.#value;
|
|
21
|
-
}
|
|
22
|
-
toJSON() {
|
|
23
|
-
return "[REDACTED]";
|
|
24
|
-
}
|
|
25
|
-
toString() {
|
|
26
|
-
return "[REDACTED]";
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
const make$1 = Value.from;
|
|
30
|
-
//#endregion
|
|
2
|
+
import { E as decode$2, c as Opaque, h as decode$3, y as Error } from "./dns-record-BLeqo56C.mjs";
|
|
3
|
+
import { g as Method, h as Error$1, p as make$1, r as Evidence, u as codec } from "./authorization-DOg2Re1D.mjs";
|
|
4
|
+
import { Clock, Effect, Schema } from "effect";
|
|
31
5
|
//#region src/providers/vercel/protocol.ts
|
|
32
6
|
const Pagination = Schema.Struct({
|
|
33
7
|
count: Schema.Number,
|
|
@@ -113,88 +87,6 @@ const IntegrationToken = Schema.Struct({
|
|
|
113
87
|
user_id: Schema.String
|
|
114
88
|
});
|
|
115
89
|
//#endregion
|
|
116
|
-
//#region src/providers/vercel/auth.ts
|
|
117
|
-
var auth_exports = /* @__PURE__ */ __exportAll({
|
|
118
|
-
exchangeCode: () => exchangeCode,
|
|
119
|
-
integrationMethod: () => integrationMethod,
|
|
120
|
-
manifest: () => manifest,
|
|
121
|
-
tokenMethod: () => tokenMethod
|
|
122
|
-
});
|
|
123
|
-
/** Describes Vercel's caller-created personal access-token method. */
|
|
124
|
-
function tokenMethod(capabilities) {
|
|
125
|
-
return {
|
|
126
|
-
_tag: "token",
|
|
127
|
-
capabilities: [...capabilities],
|
|
128
|
-
instructionsUrl: "https://vercel.com/account/settings/tokens"
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
/** Describes Vercel's provider-specific integration installation flow. */
|
|
132
|
-
function integrationMethod(options) {
|
|
133
|
-
return {
|
|
134
|
-
_tag: "integration",
|
|
135
|
-
capabilities: [...options.capabilities],
|
|
136
|
-
installUrl: `https://vercel.com/integrations/${encodeURIComponent(options.slug)}/new`,
|
|
137
|
-
tokenEndpoint: "https://api.vercel.com/oauth/access_token"
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
/** Creates the Vercel token and integration authorization manifest. */
|
|
141
|
-
function manifest(options) {
|
|
142
|
-
return {
|
|
143
|
-
methods: [tokenMethod(options.capabilities), integrationMethod(options)],
|
|
144
|
-
providerId: "vercel"
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
/** Exchanges Vercel's one-time integration code and preserves its account context. */
|
|
148
|
-
const exchangeCode = Effect.fn("VercelAuth.exchangeCode")((options) => Effect.gen(function* () {
|
|
149
|
-
const fetch = options.fetch ?? globalThis.fetch;
|
|
150
|
-
const baseUrl = (options.baseUrl ?? "https://api.vercel.com").replace(/\/$/, "");
|
|
151
|
-
const body = new URLSearchParams({
|
|
152
|
-
client_id: options.clientId,
|
|
153
|
-
client_secret: options.clientSecret.expose(),
|
|
154
|
-
code: options.code.expose(),
|
|
155
|
-
redirect_uri: options.redirectUri
|
|
156
|
-
});
|
|
157
|
-
const response = yield* Effect.tryPromise({
|
|
158
|
-
try: () => fetch(`${baseUrl}/oauth/access_token`, {
|
|
159
|
-
body,
|
|
160
|
-
headers: {
|
|
161
|
-
Accept: "application/json",
|
|
162
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
163
|
-
},
|
|
164
|
-
method: "POST"
|
|
165
|
-
}),
|
|
166
|
-
catch: () => failure$2("exchangeCode", "Vercel token exchange failed", "transport")
|
|
167
|
-
});
|
|
168
|
-
const input = yield* Effect.tryPromise({
|
|
169
|
-
try: () => response.json(),
|
|
170
|
-
catch: () => failure$2("exchangeCode", response.ok ? "Vercel returned a non-JSON token response" : `Vercel token exchange failed with HTTP ${response.status}`, response.ok ? "response" : response.status === 401 ? "authentication" : "request", response.status)
|
|
171
|
-
});
|
|
172
|
-
if (!response.ok) {
|
|
173
|
-
const detail = Schema.decodeUnknownOption(ErrorEnvelope)(input);
|
|
174
|
-
return yield* Effect.fail(failure$2("exchangeCode", detail._tag === "Some" ? detail.value.error.message : `Vercel token exchange failed with HTTP ${response.status}`, response.status === 401 ? "authentication" : "request", response.status, detail._tag === "Some" ? detail.value.error.code : void 0));
|
|
175
|
-
}
|
|
176
|
-
const token = yield* Schema.decodeUnknownEffect(IntegrationToken)(input).pipe(Effect.mapError((cause) => failure$2("exchangeCode", `Vercel token response did not match its API contract: ${cause.message}`, "response", response.status)));
|
|
177
|
-
return {
|
|
178
|
-
accessToken: make$1(token.access_token),
|
|
179
|
-
context: token.team_id === null ? { _tag: "personal" } : {
|
|
180
|
-
_tag: "team",
|
|
181
|
-
teamId: token.team_id
|
|
182
|
-
},
|
|
183
|
-
installationId: token.installation_id ?? null,
|
|
184
|
-
userId: token.user_id
|
|
185
|
-
};
|
|
186
|
-
}));
|
|
187
|
-
function failure$2(operation, message, reason, status, code) {
|
|
188
|
-
return new Error$1({
|
|
189
|
-
...code === void 0 ? {} : { code },
|
|
190
|
-
message,
|
|
191
|
-
operation,
|
|
192
|
-
providerId: "vercel",
|
|
193
|
-
reason,
|
|
194
|
-
...status === void 0 ? {} : { status }
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
//#endregion
|
|
198
90
|
//#region src/providers/vercel/records.ts
|
|
199
91
|
const decode$1 = Effect.fn("VercelRecords.decode")((zone, record) => Effect.gen(function* () {
|
|
200
92
|
const absolute = absoluteNameCandidate(zone, record.name);
|
|
@@ -213,7 +105,7 @@ const decode$1 = Effect.fn("VercelRecords.decode")((zone, record) => Effect.gen(
|
|
|
213
105
|
policy: record.type === "CNAME" ? "exclusive" : "append",
|
|
214
106
|
ttl: record.ttl ?? 60
|
|
215
107
|
};
|
|
216
|
-
const fromRecord = (input) => decode$3(input).pipe(Effect.mapError((cause) => failure$
|
|
108
|
+
const fromRecord = (input) => decode$3(input).pipe(Effect.mapError((cause) => failure$2("decodeRecord", cause.message)));
|
|
217
109
|
switch (record.type) {
|
|
218
110
|
case "A":
|
|
219
111
|
case "AAAA": return yield* fromRecord({
|
|
@@ -240,7 +132,7 @@ const decode$1 = Effect.fn("VercelRecords.decode")((zone, record) => Effect.gen(
|
|
|
240
132
|
});
|
|
241
133
|
case "CAA": {
|
|
242
134
|
const match = record.value.match(/^(\d{1,3})\s+(issue|issuewild|iodef)\s+(?:"((?:\\.|[^"])*)"|(\S.*))$/);
|
|
243
|
-
if (match === null) return yield* Effect.fail(failure$
|
|
135
|
+
if (match === null) return yield* Effect.fail(failure$2("decodeRecord", "Vercel CAA record has an invalid value"));
|
|
244
136
|
return yield* fromRecord({
|
|
245
137
|
...common,
|
|
246
138
|
_tag: "CAA",
|
|
@@ -274,7 +166,7 @@ const decodeOpaque = Effect.fn("VercelRecords.decodeOpaque")((record, name) => S
|
|
|
274
166
|
name,
|
|
275
167
|
providerRecordId: record.id,
|
|
276
168
|
providerType: record.type
|
|
277
|
-
}).pipe(Effect.mapError((cause) => failure$
|
|
169
|
+
}).pipe(Effect.mapError((cause) => failure$2("decodeRecord", cause.message))));
|
|
278
170
|
function encode(zone, record) {
|
|
279
171
|
const common = {
|
|
280
172
|
name: relativeName(zone, record.name),
|
|
@@ -322,7 +214,7 @@ function absoluteNameCandidate(zone, name) {
|
|
|
322
214
|
function relativeName(zone, name) {
|
|
323
215
|
if (name === zone) return "";
|
|
324
216
|
const suffix = `.${zone}`;
|
|
325
|
-
if (!name.endsWith(suffix)) throw failure$
|
|
217
|
+
if (!name.endsWith(suffix)) throw failure$2("encodeRecord", `DNS record ${name} is outside Vercel zone ${zone}`, { reason: "request" });
|
|
326
218
|
return name.slice(0, -suffix.length);
|
|
327
219
|
}
|
|
328
220
|
function escapeQuoted(value) {
|
|
@@ -331,8 +223,8 @@ function escapeQuoted(value) {
|
|
|
331
223
|
function unescapeQuoted(value) {
|
|
332
224
|
return value.replace(/\\([\\"])/g, "$1");
|
|
333
225
|
}
|
|
334
|
-
function failure$
|
|
335
|
-
return new Error
|
|
226
|
+
function failure$2(operation, message, fields = {}) {
|
|
227
|
+
return new Error({
|
|
336
228
|
message,
|
|
337
229
|
operation,
|
|
338
230
|
providerId: "vercel",
|
|
@@ -341,7 +233,17 @@ function failure$1(operation, message, fields = {}) {
|
|
|
341
233
|
}
|
|
342
234
|
//#endregion
|
|
343
235
|
//#region src/providers/vercel/client.ts
|
|
344
|
-
var client_exports = /* @__PURE__ */ __exportAll({
|
|
236
|
+
var client_exports = /* @__PURE__ */ __exportAll({
|
|
237
|
+
discovery: () => discovery,
|
|
238
|
+
make: () => make
|
|
239
|
+
});
|
|
240
|
+
/** Exposes Vercel zone lookup as the optional provider discovery capability. */
|
|
241
|
+
function discovery(client) {
|
|
242
|
+
return {
|
|
243
|
+
listZones: (name) => client.listZones({ name }),
|
|
244
|
+
provider: client
|
|
245
|
+
};
|
|
246
|
+
}
|
|
345
247
|
/** Creates an Effect-native Vercel client without owning the credential lifecycle. */
|
|
346
248
|
function make(options) {
|
|
347
249
|
const fetch = options.fetch ?? globalThis.fetch;
|
|
@@ -363,11 +265,11 @@ function make(options) {
|
|
|
363
265
|
...init?.headers
|
|
364
266
|
}
|
|
365
267
|
}),
|
|
366
|
-
catch: () => failure(operation, "Vercel request failed", { reason: "transport" })
|
|
268
|
+
catch: () => failure$1(operation, "Vercel request failed", { reason: "transport" })
|
|
367
269
|
});
|
|
368
270
|
const body = yield* Effect.tryPromise({
|
|
369
271
|
try: () => response.json(),
|
|
370
|
-
catch: () => failure(operation, response.ok ? "Vercel returned a non-JSON response" : `Vercel request failed with HTTP ${response.status}`, {
|
|
272
|
+
catch: () => failure$1(operation, response.ok ? "Vercel returned a non-JSON response" : `Vercel request failed with HTTP ${response.status}`, {
|
|
371
273
|
reason: response.ok ? "response" : reason(response.status),
|
|
372
274
|
...rateLimit(response),
|
|
373
275
|
status: response.status
|
|
@@ -416,8 +318,8 @@ function make(options) {
|
|
|
416
318
|
}).pipe(Effect.catchTag("ProviderError", (cause) => cause.reason === "not_found" ? Effect.succeed(null) : Effect.fail(cause))));
|
|
417
319
|
const resolveZone = Effect.fn("VercelClient.resolveZone")((name) => Effect.gen(function* () {
|
|
418
320
|
const domain = yield* discoverZone(name);
|
|
419
|
-
if (domain === null) return yield* Effect.fail(failure("resolveZone", `Vercel zone ${name} is not configured for authoritative DNS in the selected account`, { reason: "not_found" }));
|
|
420
|
-
return yield* decode$2(domain.name).pipe(Effect.mapError((cause) => failure("resolveZone", `Vercel returned an invalid storage zone: ${cause.message}`)));
|
|
321
|
+
if (domain === null) return yield* Effect.fail(failure$1("resolveZone", `Vercel zone ${name} is not configured for authoritative DNS in the selected account`, { reason: "not_found" }));
|
|
322
|
+
return yield* decode$2(domain.name).pipe(Effect.mapError((cause) => failure$1("resolveZone", `Vercel returned an invalid storage zone: ${cause.message}`)));
|
|
421
323
|
}));
|
|
422
324
|
const listRecords = Effect.fn("VercelClient.listRecords")((zoneName) => Effect.gen(function* () {
|
|
423
325
|
const storageZone = yield* resolveZone(zoneName);
|
|
@@ -438,7 +340,7 @@ function make(options) {
|
|
|
438
340
|
const storageZone = yield* resolveZone(zoneName);
|
|
439
341
|
const body = yield* Effect.try({
|
|
440
342
|
try: () => encode(storageZone, record),
|
|
441
|
-
catch: (cause) => cause instanceof Error
|
|
343
|
+
catch: (cause) => cause instanceof Error ? cause : failure$1("createRecord", "Vercel record could not be encoded", { reason: "request" })
|
|
442
344
|
});
|
|
443
345
|
const result = yield* request(withContext(`/v2/domains/${encodeURIComponent(storageZone)}/records`), "createRecord", {
|
|
444
346
|
body: JSON.stringify(body),
|
|
@@ -513,8 +415,8 @@ function hasDnsStorage(domain, configuredServiceType = domain.serviceType) {
|
|
|
513
415
|
return configuredServiceType === "zeit.world" || domain.zone === true || domain.intendedNameservers.length > 0;
|
|
514
416
|
}
|
|
515
417
|
const projectZone = Effect.fn("VercelClient.projectZone")((domain) => Effect.gen(function* () {
|
|
516
|
-
const name = yield* decode$2(domain.name).pipe(Effect.mapError((cause) => failure("listZones", cause.message, { reason: "response" })));
|
|
517
|
-
const nameservers = yield* Effect.forEach(domain.intendedNameservers, (nameserver) => decode$2(nameserver).pipe(Effect.mapError((cause) => failure("listZones", cause.message, { reason: "response" }))));
|
|
418
|
+
const name = yield* decode$2(domain.name).pipe(Effect.mapError((cause) => failure$1("listZones", cause.message, { reason: "response" })));
|
|
419
|
+
const nameservers = yield* Effect.forEach(domain.intendedNameservers, (nameserver) => decode$2(nameserver).pipe(Effect.mapError((cause) => failure$1("listZones", cause.message, { reason: "response" }))));
|
|
518
420
|
return {
|
|
519
421
|
accountId: domain.teamId ?? domain.userId,
|
|
520
422
|
id: domain.id,
|
|
@@ -524,14 +426,14 @@ const projectZone = Effect.fn("VercelClient.projectZone")((domain) => Effect.gen
|
|
|
524
426
|
};
|
|
525
427
|
}));
|
|
526
428
|
function decode(schema, input, operation, response) {
|
|
527
|
-
return Schema.decodeUnknownEffect(schema)(input).pipe(Effect.mapError((cause) => failure(operation, `Vercel response did not match its API contract: ${cause.message}`, {
|
|
429
|
+
return Schema.decodeUnknownEffect(schema)(input).pipe(Effect.mapError((cause) => failure$1(operation, `Vercel response did not match its API contract: ${cause.message}`, {
|
|
528
430
|
reason: "response",
|
|
529
431
|
status: response.status
|
|
530
432
|
})));
|
|
531
433
|
}
|
|
532
434
|
function apiFailure(input, operation, response) {
|
|
533
435
|
const detail = Schema.decodeUnknownOption(ErrorEnvelope)(input);
|
|
534
|
-
return failure(operation, detail._tag === "Some" ? detail.value.error.message : `Vercel request failed with HTTP ${response.status}`, {
|
|
436
|
+
return failure$1(operation, detail._tag === "Some" ? detail.value.error.message : `Vercel request failed with HTTP ${response.status}`, {
|
|
535
437
|
...detail._tag === "Some" ? { code: detail.value.error.code } : {},
|
|
536
438
|
reason: reason(response.status, detail._tag === "Some" ? detail.value.error.code : void 0),
|
|
537
439
|
...rateLimit(response, detail._tag === "Some" ? detail.value.error : void 0),
|
|
@@ -553,8 +455,8 @@ function rateLimit(response, detail) {
|
|
|
553
455
|
const reset = resetMs ?? (header === null ? void 0 : Number(header) * 1e3);
|
|
554
456
|
return reset === void 0 || !Number.isFinite(reset) ? {} : { retryAfterMs: Math.max(0, reset - Date.now()) };
|
|
555
457
|
}
|
|
556
|
-
function failure(operation, message, fields = {}) {
|
|
557
|
-
return new Error
|
|
458
|
+
function failure$1(operation, message, fields = {}) {
|
|
459
|
+
return new Error({
|
|
558
460
|
...fields,
|
|
559
461
|
message,
|
|
560
462
|
operation,
|
|
@@ -562,6 +464,208 @@ function failure(operation, message, fields = {}) {
|
|
|
562
464
|
});
|
|
563
465
|
}
|
|
564
466
|
//#endregion
|
|
565
|
-
|
|
467
|
+
//#region src/providers/vercel/auth.ts
|
|
468
|
+
var auth_exports = /* @__PURE__ */ __exportAll({
|
|
469
|
+
contextCodec: () => contextCodec,
|
|
470
|
+
exchangeCode: () => exchangeCode,
|
|
471
|
+
integrationAuthentication: () => integrationAuthentication,
|
|
472
|
+
integrationFlow: () => integrationFlow,
|
|
473
|
+
integrationMethod: () => integrationMethod,
|
|
474
|
+
manifest: () => manifest,
|
|
475
|
+
tokenConnectionMethod: () => tokenConnectionMethod,
|
|
476
|
+
tokenMethod: () => tokenMethod
|
|
477
|
+
});
|
|
478
|
+
const Context$1 = Schema.TaggedUnion({
|
|
479
|
+
personal: { installationId: Schema.NullOr(Schema.String) },
|
|
480
|
+
team: {
|
|
481
|
+
installationId: Schema.NullOr(Schema.String),
|
|
482
|
+
teamId: Schema.String
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
const contextCodec = codec("vercel.v1", Context$1);
|
|
486
|
+
/** Describes Vercel's caller-created personal access-token method. */
|
|
487
|
+
function tokenMethod(capabilities) {
|
|
488
|
+
return {
|
|
489
|
+
_tag: "token",
|
|
490
|
+
capabilities: [...capabilities],
|
|
491
|
+
instructionsUrl: "https://vercel.com/account/settings/tokens"
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
/** Describes Vercel's provider-specific integration installation flow. */
|
|
495
|
+
function integrationMethod(options) {
|
|
496
|
+
return {
|
|
497
|
+
_tag: "integration",
|
|
498
|
+
capabilities: [...options.capabilities],
|
|
499
|
+
installUrl: `https://vercel.com/integrations/${encodeURIComponent(options.slug)}/new`,
|
|
500
|
+
tokenEndpoint: "https://api.vercel.com/oauth/access_token"
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/** Creates the Vercel token and integration authorization manifest. */
|
|
504
|
+
function manifest(options) {
|
|
505
|
+
return {
|
|
506
|
+
methods: [tokenMethod(options.capabilities), integrationMethod(options)],
|
|
507
|
+
providerId: "vercel"
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
/** Exchanges Vercel's one-time integration code and preserves its account context. */
|
|
511
|
+
const exchangeCode = Effect.fn("VercelAuth.exchangeCode")((options) => Effect.gen(function* () {
|
|
512
|
+
const fetch = options.fetch ?? globalThis.fetch;
|
|
513
|
+
const baseUrl = (options.baseUrl ?? "https://api.vercel.com").replace(/\/$/, "");
|
|
514
|
+
const body = new URLSearchParams({
|
|
515
|
+
client_id: options.clientId,
|
|
516
|
+
client_secret: options.clientSecret.expose(),
|
|
517
|
+
code: options.code.expose(),
|
|
518
|
+
redirect_uri: options.redirectUri
|
|
519
|
+
});
|
|
520
|
+
const response = yield* Effect.tryPromise({
|
|
521
|
+
try: () => fetch(`${baseUrl}/oauth/access_token`, {
|
|
522
|
+
body,
|
|
523
|
+
headers: {
|
|
524
|
+
Accept: "application/json",
|
|
525
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
526
|
+
},
|
|
527
|
+
method: "POST"
|
|
528
|
+
}),
|
|
529
|
+
catch: () => failure("exchangeCode", "Vercel token exchange failed", "transport")
|
|
530
|
+
});
|
|
531
|
+
const input = yield* Effect.tryPromise({
|
|
532
|
+
try: () => response.json(),
|
|
533
|
+
catch: () => failure("exchangeCode", response.ok ? "Vercel returned a non-JSON token response" : `Vercel token exchange failed with HTTP ${response.status}`, response.ok ? "response" : response.status === 401 ? "authentication" : "request", response.status)
|
|
534
|
+
});
|
|
535
|
+
if (!response.ok) {
|
|
536
|
+
const detail = Schema.decodeUnknownOption(ErrorEnvelope)(input);
|
|
537
|
+
return yield* Effect.fail(failure("exchangeCode", detail._tag === "Some" ? detail.value.error.message : `Vercel token exchange failed with HTTP ${response.status}`, response.status === 401 ? "authentication" : "request", response.status, detail._tag === "Some" ? detail.value.error.code : void 0));
|
|
538
|
+
}
|
|
539
|
+
const token = yield* Schema.decodeUnknownEffect(IntegrationToken)(input).pipe(Effect.mapError((cause) => failure("exchangeCode", `Vercel token response did not match its API contract: ${cause.message}`, "response", response.status)));
|
|
540
|
+
return {
|
|
541
|
+
accessToken: make$1(token.access_token),
|
|
542
|
+
context: token.team_id === null ? { _tag: "personal" } : {
|
|
543
|
+
_tag: "team",
|
|
544
|
+
teamId: token.team_id
|
|
545
|
+
},
|
|
546
|
+
installationId: token.installation_id ?? null,
|
|
547
|
+
userId: token.user_id
|
|
548
|
+
};
|
|
549
|
+
}));
|
|
550
|
+
/** Creates a provider-independent token connection method backed by Vercel validation. */
|
|
551
|
+
function tokenConnectionMethod(options) {
|
|
552
|
+
const requiredCapabilities = [...options.capabilities];
|
|
553
|
+
return Method.Token({
|
|
554
|
+
authenticate: Effect.fn("VercelAuth.authenticateToken")(function* (token) {
|
|
555
|
+
const validated = yield* make({
|
|
556
|
+
...options,
|
|
557
|
+
token
|
|
558
|
+
}).validateToken();
|
|
559
|
+
const observedAt = new Date(yield* Clock.currentTimeMillis);
|
|
560
|
+
return {
|
|
561
|
+
capabilityEvidence: validated.capabilities.map((capability) => ({
|
|
562
|
+
capability,
|
|
563
|
+
evidence: Evidence.Introspected({ observedAt })
|
|
564
|
+
})),
|
|
565
|
+
credential: {
|
|
566
|
+
accessToken: token,
|
|
567
|
+
refreshToken: null,
|
|
568
|
+
tokenType: "bearer"
|
|
569
|
+
},
|
|
570
|
+
expiresAt: validated.expiresAt,
|
|
571
|
+
providerAccountId: validated.accountId,
|
|
572
|
+
providerContext: yield* contextCodec.encode(options.context._tag === "team" ? {
|
|
573
|
+
_tag: "team",
|
|
574
|
+
installationId: null,
|
|
575
|
+
teamId: options.context.teamId
|
|
576
|
+
} : {
|
|
577
|
+
_tag: "personal",
|
|
578
|
+
installationId: null
|
|
579
|
+
}),
|
|
580
|
+
scopes: [...validated.scopes]
|
|
581
|
+
};
|
|
582
|
+
}),
|
|
583
|
+
providerId: "vercel",
|
|
584
|
+
requiredCapabilities,
|
|
585
|
+
token: options.token
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
/** Converts a completed Vercel Integration exchange into canonical connection authentication. */
|
|
589
|
+
const integrationAuthentication = Effect.fn("VercelAuth.integrationAuthentication")(function* (options) {
|
|
590
|
+
const exchanged = yield* exchangeCode(options);
|
|
591
|
+
const observedAt = new Date(yield* Clock.currentTimeMillis);
|
|
592
|
+
return {
|
|
593
|
+
capabilityEvidence: options.capabilities.map((capability) => ({
|
|
594
|
+
capability,
|
|
595
|
+
evidence: Evidence.Introspected({ observedAt })
|
|
596
|
+
})),
|
|
597
|
+
credential: {
|
|
598
|
+
accessToken: exchanged.accessToken,
|
|
599
|
+
refreshToken: null,
|
|
600
|
+
tokenType: "bearer"
|
|
601
|
+
},
|
|
602
|
+
expiresAt: null,
|
|
603
|
+
providerAccountId: exchanged.context._tag === "team" ? exchanged.context.teamId : exchanged.userId,
|
|
604
|
+
providerContext: yield* contextCodec.encode(exchanged.context._tag === "team" ? {
|
|
605
|
+
_tag: "team",
|
|
606
|
+
installationId: exchanged.installationId,
|
|
607
|
+
teamId: exchanged.context.teamId
|
|
608
|
+
} : {
|
|
609
|
+
_tag: "personal",
|
|
610
|
+
installationId: exchanged.installationId
|
|
611
|
+
}),
|
|
612
|
+
scopes: []
|
|
613
|
+
};
|
|
614
|
+
});
|
|
615
|
+
/** Creates Vercel Integration's implementation of the common interactive connection capability. */
|
|
616
|
+
function integrationFlow(options) {
|
|
617
|
+
const method = integrationMethod(options);
|
|
618
|
+
const Payload = Schema.fromJsonString(Schema.Struct({ state: Schema.String }));
|
|
619
|
+
return {
|
|
620
|
+
complete: Effect.fn("VercelAuth.integrationFlow.complete")(function* (payload, callbackUrl) {
|
|
621
|
+
const continuation = yield* Schema.decodeUnknownEffect(Payload)(payload.expose()).pipe(Effect.mapError(() => new Error$1({
|
|
622
|
+
category: "authorization",
|
|
623
|
+
message: "Vercel Integration continuation payload is invalid",
|
|
624
|
+
operation: "VercelAuth.integrationFlow.complete",
|
|
625
|
+
retry: "after-user-action"
|
|
626
|
+
})));
|
|
627
|
+
const code = callbackUrl.searchParams.get("code");
|
|
628
|
+
if (callbackUrl.searchParams.get("state") !== continuation.state || code === null) return yield* new Error$1({
|
|
629
|
+
category: "authorization",
|
|
630
|
+
message: "Vercel Integration callback does not match its continuation",
|
|
631
|
+
operation: "VercelAuth.integrationFlow.complete",
|
|
632
|
+
retry: "after-user-action"
|
|
633
|
+
});
|
|
634
|
+
return yield* integrationAuthentication({
|
|
635
|
+
...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
|
|
636
|
+
capabilities: options.capabilities,
|
|
637
|
+
clientId: options.clientId,
|
|
638
|
+
clientSecret: options.clientSecret,
|
|
639
|
+
code: make$1(code),
|
|
640
|
+
...options.fetch === void 0 ? {} : { fetch: options.fetch },
|
|
641
|
+
redirectUri: options.redirectUri
|
|
642
|
+
});
|
|
643
|
+
}),
|
|
644
|
+
method: "integration",
|
|
645
|
+
providerId: "vercel",
|
|
646
|
+
requiredCapabilities: [...options.capabilities],
|
|
647
|
+
start: (continuationId) => {
|
|
648
|
+
const authorizationUrl = new URL(method.installUrl);
|
|
649
|
+
authorizationUrl.searchParams.set("source", "external");
|
|
650
|
+
authorizationUrl.searchParams.set("state", continuationId);
|
|
651
|
+
return Effect.succeed({
|
|
652
|
+
authorizationUrl,
|
|
653
|
+
payload: make$1(JSON.stringify({ state: continuationId }))
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function failure(operation, message, reason, status, code) {
|
|
659
|
+
return new Error({
|
|
660
|
+
...code === void 0 ? {} : { code },
|
|
661
|
+
message,
|
|
662
|
+
operation,
|
|
663
|
+
providerId: "vercel",
|
|
664
|
+
reason,
|
|
665
|
+
...status === void 0 ? {} : { status }
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
//#endregion
|
|
669
|
+
export { manifest as a, client_exports as c, integrationMethod as i, discovery as l, exchangeCode as n, tokenConnectionMethod as o, integrationFlow as r, tokenMethod as s, auth_exports as t, make as u };
|
|
566
670
|
|
|
567
|
-
//# sourceMappingURL=
|
|
671
|
+
//# sourceMappingURL=auth-CzhZ3Cuc.mjs.map
|