import * as z from "zod" import { defineAction } from "../../automation/actions" import { encodableSchema } from "@automate.ax/codec" import { CLOUDFLARE_ACCOUNT_SCHEMA, CLOUDFLARE_ALERT_TYPE_SCHEMA, CLOUDFLARE_AVAILABLE_ALERT_SCHEMA, CLOUDFLARE_DELETE_RESULT_SCHEMA, CLOUDFLARE_DNS_RECORD_SCHEMA, CLOUDFLARE_DNS_RECORD_TYPE_SCHEMA, CLOUDFLARE_HEALTH_CHECK_REGION_SCHEMA, CLOUDFLARE_HEALTH_CHECK_SCHEMA, CLOUDFLARE_HTTP_HEALTH_CHECK_SCHEMA, CLOUDFLARE_NOTIFICATION_FILTERS_SCHEMA, CLOUDFLARE_NOTIFICATION_HISTORY_SCHEMA, CLOUDFLARE_NOTIFICATION_MECHANISMS_SCHEMA, CLOUDFLARE_NOTIFICATION_POLICY_SCHEMA, CLOUDFLARE_NOTIFICATION_WEBHOOK_SCHEMA, CLOUDFLARE_TCP_HEALTH_CHECK_SCHEMA, CLOUDFLARE_ZONE_SCHEMA, getCloudflareApi, } from "@automate.ax/integration-contracts/cloudflare" import { CLOUDFLARE_ACCOUNT_SETTINGS_READ_SCOPE, CLOUDFLARE_CACHE_PURGE_SCOPE, CLOUDFLARE_DNS_READ_SCOPE, CLOUDFLARE_DNS_WRITE_SCOPE, CLOUDFLARE_HEALTH_CHECK_READ_SCOPE, CLOUDFLARE_HEALTH_CHECK_WRITE_SCOPE, CLOUDFLARE_ID_SCHEMA, CLOUDFLARE_NOTIFICATIONS_READ_SCOPE, CLOUDFLARE_NOTIFICATIONS_WRITE_SCOPE, CLOUDFLARE_PAGE_INPUT_SCHEMA, CLOUDFLARE_ZONE_READ_SCOPE, CLOUDFLARE_ZONE_WRITE_SCOPE, cloudflareAccountRequirement, cloudflarePageSchema, toCloudflarePage, } from "./lib" const ACCOUNT = "cloudflare" const DIRECTION_SCHEMA = z.enum(["asc", "desc"]) const ZONE_ID = { zoneId: CLOUDFLARE_ID_SCHEMA } const ACCOUNT_ID = { accountId: CLOUDFLARE_ID_SCHEMA } /** * Resolves the shared API client from one action account. * * @param account - Resolved Cloudflare action account. * @param account.connectionMethodId - OAuth or API-token method ID. * @param account.secret - Resolved provider credential. * @param account.serviceId - Cloudflare service discriminator. */ function api(account: { connectionMethodId: string secret: Record serviceId: "cloudflare" }) { return getCloudflareApi(account) } /** Lists Cloudflare accounts visible to the connection. */ export const listCloudflareAccounts = defineAction("List Cloudflare accounts") .describe("Lists Cloudflare accounts visible to the connected identity.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ACCOUNT_SETTINGS_READ_SCOPE), ) .input( z.object({ name: z.string().optional(), ...CLOUDFLARE_PAGE_INPUT_SCHEMA }), ) .output(cloudflarePageSchema(CLOUDFLARE_ACCOUNT_SCHEMA)) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => toCloudflarePage( await api(account).requestPage("accounts", { query: input, responseSchema: CLOUDFLARE_ACCOUNT_SCHEMA.array(), }), ), ) /** Retrieves one Cloudflare account. */ export const getCloudflareAccount = defineAction("Get Cloudflare account") .describe("Retrieves one Cloudflare account by ID.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ACCOUNT_SETTINGS_READ_SCOPE), ) .input(z.object(ACCOUNT_ID)) .output(CLOUDFLARE_ACCOUNT_SCHEMA) .retry({ replaySafety: "safe" }) .handler(({ account, input }) => api(account).request(`accounts/${encodeURIComponent(input.accountId)}`, { responseSchema: CLOUDFLARE_ACCOUNT_SCHEMA, }), ) const LIST_ZONES_INPUT = z.object({ accountId: CLOUDFLARE_ID_SCHEMA.optional(), direction: DIRECTION_SCHEMA.prefault("asc"), match: z.enum(["all", "any"]).prefault("all"), name: z.string().optional(), order: z .enum(["account.id", "account.name", "name", "status"]) .prefault("name"), ...CLOUDFLARE_PAGE_INPUT_SCHEMA, status: z.enum(["active", "initializing", "moved", "pending"]).optional(), }) /** Lists Cloudflare zones. */ export const listCloudflareZones = defineAction("List Cloudflare zones") .describe("Lists zones with account, name, status, and pagination filters.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ZONE_READ_SCOPE)) .input(LIST_ZONES_INPUT) .output(cloudflarePageSchema(CLOUDFLARE_ZONE_SCHEMA)) .retry({ replaySafety: "safe" }) .handler(async ({ account, input: { accountId, ...query } }) => toCloudflarePage( await api(account).requestPage("zones", { query: { ...(accountId && { "account.id": accountId }), ...query }, responseSchema: CLOUDFLARE_ZONE_SCHEMA.array(), }), ), ) /** Retrieves one Cloudflare zone. */ export const getCloudflareZone = defineAction("Get Cloudflare zone") .describe("Retrieves one Cloudflare zone by ID.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ZONE_READ_SCOPE)) .input(z.object(ZONE_ID)) .output(CLOUDFLARE_ZONE_SCHEMA) .retry({ replaySafety: "safe" }) .handler(({ account, input }) => api(account).request(`zones/${encodeURIComponent(input.zoneId)}`, { responseSchema: CLOUDFLARE_ZONE_SCHEMA, }), ) /** Creates a Cloudflare zone. */ export const createCloudflareZone = defineAction("Create Cloudflare zone") .describe("Creates a zone in a Cloudflare account.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ZONE_WRITE_SCOPE)) .input( z.object({ ...ACCOUNT_ID, name: z.string().trim().min(1).max(253), type: z.enum(["full", "partial", "secondary"]).prefault("full"), }), ) .output(CLOUDFLARE_ZONE_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input }) => api(account).request("zones", { body: { account: { id: input.accountId }, name: input.name, type: input.type, }, method: "POST", responseSchema: CLOUDFLARE_ZONE_SCHEMA, }), ) /** Updates mutable Cloudflare zone settings. */ export const updateCloudflareZone = defineAction("Update Cloudflare zone") .describe("Updates a zone's paused state, type, or vanity name servers.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ZONE_WRITE_SCOPE)) .input( z .object({ ...ZONE_ID, paused: z.boolean().optional(), type: z.enum(["full", "partial", "secondary"]).optional(), vanityNameServers: z.string().array().optional(), }) .refine( ({ paused, type, vanityNameServers }) => paused !== undefined || type !== undefined || vanityNameServers !== undefined, "Provide at least one zone change.", ), ) .output(CLOUDFLARE_ZONE_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { zoneId, ...body } }) => api(account).request(`zones/${encodeURIComponent(zoneId)}`, { body, method: "PATCH", responseSchema: CLOUDFLARE_ZONE_SCHEMA, }), ) /** Deletes a Cloudflare zone. */ export const deleteCloudflareZone = defineAction("Delete Cloudflare zone") .describe("Deletes a Cloudflare zone.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ZONE_WRITE_SCOPE)) .input(z.object(ZONE_ID)) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input }) => api(account).request(`zones/${encodeURIComponent(input.zoneId)}`, { method: "DELETE", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA, }), ) /** Requests another activation check for a pending zone. */ export const rerunCloudflareZoneActivationCheck = defineAction( "Rerun Cloudflare zone activation check", ) .describe("Requests another Cloudflare activation check for a pending zone.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_ZONE_WRITE_SCOPE)) .input(z.object(ZONE_ID)) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input }) => api(account).request( `zones/${encodeURIComponent(input.zoneId)}/activation_check`, { method: "PUT", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA }, ), ) const DNS_LIST_INPUT = z.object({ ...ZONE_ID, comment: z.string().optional(), content: z.string().optional(), direction: DIRECTION_SCHEMA.prefault("asc"), match: z.enum(["all", "any"]).prefault("all"), name: z.string().optional(), order: z .enum(["comment", "content", "name", "proxied", "ttl", "type"]) .prefault("type"), ...CLOUDFLARE_PAGE_INPUT_SCHEMA, proxied: z.boolean().optional(), search: z.string().optional(), tag: z.string().optional(), tagMatch: z.enum(["all", "any"]).optional(), type: CLOUDFLARE_DNS_RECORD_TYPE_SCHEMA.optional(), }) const DNS_BODY = { comment: z.string().max(100).optional(), content: z.string().optional(), data: z.record(z.string(), encodableSchema).optional(), name: z.string().trim().min(1).max(255), priority: z.number().int().min(0).max(65_535).optional(), proxied: z.boolean().optional(), settings: z.record(z.string(), encodableSchema).optional(), tags: z.string().max(100).array().max(100).optional(), ttl: z.number().int().min(1).max(86_400).prefault(1), type: CLOUDFLARE_DNS_RECORD_TYPE_SCHEMA, } /** Lists DNS records in a Cloudflare zone. */ export const listCloudflareDnsRecords = defineAction( "List Cloudflare DNS records", ) .describe( "Lists DNS records in a zone with Cloudflare filters and pagination.", ) .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_DNS_READ_SCOPE)) .input(DNS_LIST_INPUT) .output(cloudflarePageSchema(CLOUDFLARE_DNS_RECORD_SCHEMA)) .retry({ replaySafety: "safe" }) .handler(async ({ account, input: { zoneId, ...query } }) => toCloudflarePage( await api(account).requestPage( `zones/${encodeURIComponent(zoneId)}/dns_records`, { query, responseSchema: CLOUDFLARE_DNS_RECORD_SCHEMA.array() }, ), ), ) /** Retrieves one Cloudflare DNS record. */ export const getCloudflareDnsRecord = defineAction("Get Cloudflare DNS record") .describe("Retrieves one DNS record by zone and record ID.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_DNS_READ_SCOPE)) .input(z.object({ ...ZONE_ID, recordId: CLOUDFLARE_ID_SCHEMA })) .output(CLOUDFLARE_DNS_RECORD_SCHEMA) .retry({ replaySafety: "safe" }) .handler(({ account, input }) => api(account).request( `zones/${encodeURIComponent(input.zoneId)}/dns_records/${encodeURIComponent(input.recordId)}`, { responseSchema: CLOUDFLARE_DNS_RECORD_SCHEMA }, ), ) /** Creates a Cloudflare DNS record. */ export const createCloudflareDnsRecord = defineAction( "Create Cloudflare DNS record", ) .describe("Creates a DNS record in a Cloudflare zone.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_DNS_WRITE_SCOPE)) .input( z .object({ ...ZONE_ID, ...DNS_BODY }) .refine( (value) => value.content !== undefined || value.data !== undefined, "Provide content or structured record data.", ), ) .output(CLOUDFLARE_DNS_RECORD_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { zoneId, ...body } }) => api(account).request(`zones/${encodeURIComponent(zoneId)}/dns_records`, { body, method: "POST", responseSchema: CLOUDFLARE_DNS_RECORD_SCHEMA, }), ) /** Updates a Cloudflare DNS record. */ export const updateCloudflareDnsRecord = defineAction( "Update Cloudflare DNS record", ) .describe("Overwrites one Cloudflare DNS record.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_DNS_WRITE_SCOPE)) .input( z .object({ ...ZONE_ID, recordId: CLOUDFLARE_ID_SCHEMA, ...DNS_BODY }) .refine( (value) => value.content !== undefined || value.data !== undefined, "Provide content or structured record data.", ), ) .output(CLOUDFLARE_DNS_RECORD_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { zoneId, recordId, ...body } }) => api(account).request( `zones/${encodeURIComponent(zoneId)}/dns_records/${encodeURIComponent(recordId)}`, { body, method: "PUT", responseSchema: CLOUDFLARE_DNS_RECORD_SCHEMA }, ), ) /** Deletes a Cloudflare DNS record. */ export const deleteCloudflareDnsRecord = defineAction( "Delete Cloudflare DNS record", ) .describe("Deletes one DNS record from a Cloudflare zone.") .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_DNS_WRITE_SCOPE)) .input(z.object({ ...ZONE_ID, recordId: CLOUDFLARE_ID_SCHEMA })) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input }) => api(account).request( `zones/${encodeURIComponent(input.zoneId)}/dns_records/${encodeURIComponent(input.recordId)}`, { method: "DELETE", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA }, ), ) const PURGE_FILE_SCHEMA = z.union([ z.url(), z.object({ headers: z.record(z.string(), z.string()), url: z.url() }), ]) /** Purges selected Cloudflare cache entries or the entire zone cache. */ export const purgeCloudflareCache = defineAction("Purge Cloudflare cache") .describe( "Purges a zone cache by everything, files, hosts, prefixes, or cache tags.", ) .account(ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_CACHE_PURGE_SCOPE)) .input( z .object({ ...ZONE_ID, files: PURGE_FILE_SCHEMA.array().min(1).max(30).optional(), hosts: z.string().array().min(1).max(30).optional(), prefixes: z.string().array().min(1).max(30).optional(), purgeEverything: z.literal(true).optional(), tags: z.string().array().min(1).max(30).optional(), }) .refine( ({ files, hosts, prefixes, purgeEverything, tags }) => Number(files !== undefined) + Number(hosts !== undefined) + Number(prefixes !== undefined) + Number(purgeEverything !== undefined) + Number(tags !== undefined) === 1, "Choose exactly one cache purge mode.", ), ) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { zoneId, ...body } }) => api(account).request(`zones/${encodeURIComponent(zoneId)}/purge_cache`, { body, method: "POST", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA, }), ) const HEALTH_BODY = { address: z.string().min(1), checkRegions: CLOUDFLARE_HEALTH_CHECK_REGION_SCHEMA.array() .nullable() .optional(), consecutiveFails: z.number().int().min(0).max(5).optional(), consecutiveSuccesses: z.number().int().min(0).max(5).optional(), description: z.string().max(500).optional(), httpConfig: CLOUDFLARE_HTTP_HEALTH_CHECK_SCHEMA.extend({ expectedCodes: z.string().array().optional(), header: z.record(z.string(), z.string().array()).optional(), port: z.number().int().min(1).max(65_535).optional(), }).optional(), interval: z.number().int().min(10).max(86_400).optional(), name: z.string().regex(/^[A-Za-z0-9_-]+$/), retries: z.number().int().min(0).max(3).optional(), suspended: z.boolean().optional(), tcpConfig: CLOUDFLARE_TCP_HEALTH_CHECK_SCHEMA.extend({ port: z.number().int().min(1).max(65_535).optional(), }).optional(), timeout: z.number().int().min(1).max(10).optional(), type: z.enum(["HTTP", "HTTPS", "TCP"]).optional(), } /** Lists health checks in a Cloudflare zone. */ export const listCloudflareHealthChecks = defineAction( "List Cloudflare health checks", ) .describe("Lists health checks in a Cloudflare zone.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_HEALTH_CHECK_READ_SCOPE), ) .input(z.object({ ...ZONE_ID, ...CLOUDFLARE_PAGE_INPUT_SCHEMA })) .output(cloudflarePageSchema(CLOUDFLARE_HEALTH_CHECK_SCHEMA)) .retry({ replaySafety: "safe" }) .handler(async ({ account, input: { zoneId, ...query } }) => toCloudflarePage( await api(account).requestPage( `zones/${encodeURIComponent(zoneId)}/healthchecks`, { query, responseSchema: CLOUDFLARE_HEALTH_CHECK_SCHEMA.array() }, ), ), ) /** Retrieves one Cloudflare health check. */ export const getCloudflareHealthCheck = defineAction( "Get Cloudflare health check", ) .describe("Retrieves one Cloudflare health check.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_HEALTH_CHECK_READ_SCOPE), ) .input(z.object({ ...ZONE_ID, healthCheckId: CLOUDFLARE_ID_SCHEMA })) .output(CLOUDFLARE_HEALTH_CHECK_SCHEMA) .retry({ replaySafety: "safe" }) .handler(({ account, input }) => api(account).request( `zones/${encodeURIComponent(input.zoneId)}/healthchecks/${encodeURIComponent(input.healthCheckId)}`, { responseSchema: CLOUDFLARE_HEALTH_CHECK_SCHEMA }, ), ) /** Creates a Cloudflare health check. */ export const createCloudflareHealthCheck = defineAction( "Create Cloudflare health check", ) .describe("Creates an HTTP, HTTPS, or TCP health check.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_HEALTH_CHECK_WRITE_SCOPE), ) .input(z.object({ ...ZONE_ID, ...HEALTH_BODY })) .output(CLOUDFLARE_HEALTH_CHECK_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { zoneId, ...body } }) => api(account).request(`zones/${encodeURIComponent(zoneId)}/healthchecks`, { body, method: "POST", responseSchema: CLOUDFLARE_HEALTH_CHECK_SCHEMA, }), ) /** Updates a Cloudflare health check. */ export const updateCloudflareHealthCheck = defineAction( "Update Cloudflare health check", ) .describe("Overwrites one Cloudflare health check configuration.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_HEALTH_CHECK_WRITE_SCOPE), ) .input( z.object({ ...ZONE_ID, healthCheckId: CLOUDFLARE_ID_SCHEMA, ...HEALTH_BODY, }), ) .output(CLOUDFLARE_HEALTH_CHECK_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { zoneId, healthCheckId, ...body } }) => api(account).request( `zones/${encodeURIComponent(zoneId)}/healthchecks/${encodeURIComponent(healthCheckId)}`, { body, method: "PUT", responseSchema: CLOUDFLARE_HEALTH_CHECK_SCHEMA }, ), ) /** Deletes a Cloudflare health check. */ export const deleteCloudflareHealthCheck = defineAction( "Delete Cloudflare health check", ) .describe("Deletes one Cloudflare health check.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_HEALTH_CHECK_WRITE_SCOPE), ) .input(z.object({ ...ZONE_ID, healthCheckId: CLOUDFLARE_ID_SCHEMA })) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input }) => api(account).request( `zones/${encodeURIComponent(input.zoneId)}/healthchecks/${encodeURIComponent(input.healthCheckId)}`, { method: "DELETE", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA }, ), ) const POLICY_BODY = { alertInterval: z.string().optional(), alertType: CLOUDFLARE_ALERT_TYPE_SCHEMA, description: z.string().optional(), enabled: z.boolean().prefault(true), filters: CLOUDFLARE_NOTIFICATION_FILTERS_SCHEMA.optional(), mechanisms: CLOUDFLARE_NOTIFICATION_MECHANISMS_SCHEMA, name: z.string().trim().min(1), } /** Lists Cloudflare notification alert types available to an account. */ export const listCloudflareAvailableAlertTypes = defineAction( "List Cloudflare available alert types", ) .describe( "Lists notification alert types and filter options available to an account.", ) .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_READ_SCOPE), ) .input(z.object(ACCOUNT_ID)) .output(CLOUDFLARE_AVAILABLE_ALERT_SCHEMA.array()) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => Object.values( await api(account).request( `accounts/${encodeURIComponent(input.accountId)}/alerting/v3/available_alerts`, { responseSchema: z.record( z.string(), CLOUDFLARE_AVAILABLE_ALERT_SCHEMA.array(), ), }, ), ).flat(), ) /** Lists configured Cloudflare notification webhook destinations. */ export const listCloudflareNotificationWebhooks = defineAction( "List Cloudflare notification webhooks", ) .describe( "Lists configured notification webhook destinations for an account.", ) .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_READ_SCOPE), ) .input(z.object(ACCOUNT_ID)) .output(CLOUDFLARE_NOTIFICATION_WEBHOOK_SCHEMA.array()) .retry({ replaySafety: "safe" }) .handler(({ account, input }) => api(account).request( `accounts/${encodeURIComponent(input.accountId)}/alerting/v3/destinations/webhooks`, { responseSchema: CLOUDFLARE_NOTIFICATION_WEBHOOK_SCHEMA.array() }, ), ) /** Lists Cloudflare notification history. */ export const listCloudflareNotificationHistory = defineAction( "List Cloudflare notification history", ) .describe("Lists notification deliveries for a Cloudflare account.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_READ_SCOPE), ) .input( z.object({ ...ACCOUNT_ID, before: z.iso.datetime({ offset: true }).optional(), page: z.number().int().positive().prefault(1), perPage: z.number().int().min(5).max(1000).prefault(20), since: z.iso.datetime({ offset: true }).optional(), }), ) .output(cloudflarePageSchema(CLOUDFLARE_NOTIFICATION_HISTORY_SCHEMA)) .retry({ replaySafety: "safe" }) .handler(async ({ account, input: { accountId, ...query } }) => toCloudflarePage( await api(account).requestPage( `accounts/${encodeURIComponent(accountId)}/alerting/v3/history`, { query, responseSchema: CLOUDFLARE_NOTIFICATION_HISTORY_SCHEMA.array() .nullable() .transform((items) => items ?? []), }, ), ), ) /** Lists Cloudflare notification policies. */ export const listCloudflareNotificationPolicies = defineAction( "List Cloudflare notification policies", ) .describe("Lists notification policies for a Cloudflare account.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_READ_SCOPE), ) .input(z.object(ACCOUNT_ID)) .output(CLOUDFLARE_NOTIFICATION_POLICY_SCHEMA.array()) .retry({ replaySafety: "safe" }) .handler(({ account, input }) => api(account).request( `accounts/${encodeURIComponent(input.accountId)}/alerting/v3/policies`, { responseSchema: CLOUDFLARE_NOTIFICATION_POLICY_SCHEMA.array() }, ), ) /** Retrieves one Cloudflare notification policy. */ export const getCloudflareNotificationPolicy = defineAction( "Get Cloudflare notification policy", ) .describe("Retrieves one Cloudflare notification policy.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_READ_SCOPE), ) .input(z.object({ ...ACCOUNT_ID, policyId: CLOUDFLARE_ID_SCHEMA })) .output(CLOUDFLARE_NOTIFICATION_POLICY_SCHEMA) .retry({ replaySafety: "safe" }) .handler(({ account, input }) => api(account).request( `accounts/${encodeURIComponent(input.accountId)}/alerting/v3/policies/${encodeURIComponent(input.policyId)}`, { responseSchema: CLOUDFLARE_NOTIFICATION_POLICY_SCHEMA }, ), ) /** Creates a Cloudflare notification policy. */ export const createCloudflareNotificationPolicy = defineAction( "Create Cloudflare notification policy", ) .describe("Creates a Cloudflare notification policy.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_WRITE_SCOPE), ) .input(z.object({ ...ACCOUNT_ID, ...POLICY_BODY })) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { accountId, ...body } }) => api(account).request( `accounts/${encodeURIComponent(accountId)}/alerting/v3/policies`, { body, method: "POST", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA, }, ), ) /** Updates a Cloudflare notification policy. */ export const updateCloudflareNotificationPolicy = defineAction( "Update Cloudflare notification policy", ) .describe("Overwrites one Cloudflare notification policy.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_WRITE_SCOPE), ) .input( z.object({ ...ACCOUNT_ID, policyId: CLOUDFLARE_ID_SCHEMA, ...POLICY_BODY }), ) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input: { accountId, policyId, ...body } }) => api(account).request( `accounts/${encodeURIComponent(accountId)}/alerting/v3/policies/${encodeURIComponent(policyId)}`, { body, method: "PUT", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA, }, ), ) /** Deletes a Cloudflare notification policy. */ export const deleteCloudflareNotificationPolicy = defineAction( "Delete Cloudflare notification policy", ) .describe("Deletes one Cloudflare notification policy.") .account( ACCOUNT, cloudflareAccountRequirement(CLOUDFLARE_NOTIFICATIONS_WRITE_SCOPE), ) .input(z.object({ ...ACCOUNT_ID, policyId: CLOUDFLARE_ID_SCHEMA })) .output(CLOUDFLARE_DELETE_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(({ account, input }) => api(account).request( `accounts/${encodeURIComponent(input.accountId)}/alerting/v3/policies/${encodeURIComponent(input.policyId)}`, { method: "DELETE", responseSchema: CLOUDFLARE_DELETE_RESULT_SCHEMA }, ), )