import {z} from 'zod' export type GetApi30AutomationsArgs = {count?: number | undefined, offset?: number | undefined, fields?: Array | undefined, exclude_fields?: Array | undefined, before_create_time?: string | undefined, since_create_time?: string | undefined, before_start_time?: string | undefined, since_start_time?: string | undefined, status?: ('save' | 'paused' | 'sending') | undefined}; export type GetApi30AutomationsOptions = {baseUrl?: string | undefined, bearerToken?: string | undefined, fetch?: typeof fetch | undefined}; export const getApi30AutomationsResponse = z.object({_links: z.array(z.object({href: z.string().optional(), method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]).optional(), rel: z.string().optional(), schema: z.string().optional(), targetSchema: z.string().optional()})).optional(), automations: z.array(z.object({_links: z.array(z.object({href: z.string().optional(), method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]).optional(), rel: z.string().optional(), schema: z.string().optional(), targetSchema: z.string().optional()})).optional(), create_time: z.string().optional(), emails_sent: z.number().int().optional(), id: z.string().optional(), recipients: z.object({list_id: z.string().optional(), list_is_active: z.boolean().optional(), list_name: z.string().optional(), segment_opts: z.array(z.union([z.object({condition_type: z.literal("Aim").optional(), field: z.literal("aim").optional(), op: z.enum(["open", "click", "sent", "noopen", "noclick", "nosent"]).optional(), value: z.string().optional()}), z.object({condition_type: z.literal("Automation").optional(), field: z.literal("automation"), op: z.enum(["started", "completed", "not_started", "not_completed"]), value: z.string()}), z.object({condition_type: z.literal("CampaignPoll").optional(), field: z.literal("poll"), op: z.enum(["member", "notmember"]), value: z.number()}), z.object({condition_type: z.literal("Conversation").optional(), field: z.literal("conversation"), op: z.enum(["member", "notmember"]), value: z.string()}), z.object({condition_type: z.literal("Date").optional(), extra: z.string().optional(), field: z.enum(["timestamp_opt", "info_changed", "ecomm_date"]), op: z.enum(["greater", "less", "is", "not", "blank", "blank_not", "within", "notwithin"]), value: z.string()}), z.object({condition_type: z.literal("EmailClient").optional(), field: z.literal("email_client"), op: z.enum(["client_is", "client_not"]), value: z.string()}), z.object({condition_type: z.literal("Language").optional(), field: z.literal("language"), op: z.enum(["is", "not"]), value: z.string()}), z.object({condition_type: z.literal("MemberRating").optional(), field: z.literal("rating"), op: z.enum(["is", "not", "greater", "less"]), value: z.union([z.number(), z.string()])}), z.object({condition_type: z.literal("SignupSource"), field: z.literal("source"), op: z.enum(["source_is", "source_not"]), value: z.string().optional()}), z.object({condition_type: z.literal("SurveyMonkey").optional(), field: z.literal("survey_monkey"), op: z.enum(["started", "completed", "not_started", "not_completed"]), value: z.string()}), z.object({condition_type: z.literal("VIP").optional(), field: z.literal("gmonkey"), op: z.enum(["member", "notmember"])}), z.object({condition_type: z.literal("Interests").optional(), field: z.string().optional(), op: z.enum(["interestcontains", "interestcontainsall", "interestnotcontains"]).optional(), value: z.array(z.string()).optional()}), z.object({condition_type: z.literal("EcommCategory").optional(), field: z.enum(["ecomm_cat", "ecomm_prod"]).optional(), op: z.enum(["is", "not", "contains", "notcontain", "starts", "ends"]).optional(), value: z.string().optional()}), z.object({condition_type: z.literal("EcommNumber").optional(), field: z.enum(["ecomm_spent_avg", "ecomm_orders", "ecomm_prod_all", "ecomm_avg_ord"]), op: z.enum(["is", "not", "greater", "less"]), value: z.union([z.number(), z.string()])}), z.object({condition_type: z.literal("EcommPurchased").optional(), field: z.literal("ecomm_purchased").optional(), op: z.enum(["member", "notmember"]).optional()}), z.object({condition_type: z.literal("EcommSpent").optional(), field: z.enum(["ecomm_spent_one", "ecomm_spent_all"]).optional(), op: z.enum(["greater", "less"]).optional(), value: z.union([z.number(), z.string()]).optional()}), z.object({condition_type: z.literal("EcommStore").optional(), field: z.literal("ecomm_store").optional(), op: z.enum(["is", "not"]).optional(), value: z.string().optional()}), z.object({condition_type: z.literal("GoalActivity").optional(), field: z.literal("goal"), op: z.enum(["is", "goal_not", "contains", "goal_notcontain", "starts", "ends"]), value: z.string()}), z.object({condition_type: z.literal("GoalTimestamp").optional(), field: z.literal("goal_last_visited"), op: z.enum(["greater", "less", "is"]), value: z.string()}), z.object({condition_type: z.literal("FuzzySegment").optional(), field: z.literal("fuzzy_segment"), op: z.enum(["fuzzy_is", "fuzzy_not"]), value: z.union([z.number(), z.string()])}), z.object({condition_type: z.literal("StaticSegment").optional(), field: z.literal("static_segment"), op: z.enum(["static_is", "static_not"]), value: z.union([z.number(), z.string()])}), z.object({condition_type: z.literal("IPGeoCountryState").optional(), field: z.literal("ipgeo"), op: z.enum(["ipgeocountry", "ipgeonotcountry", "ipgeostate", "ipgeonotstate"]), value: z.string()}), z.object({addr: z.string(), condition_type: z.literal("IPGeoIn").optional(), field: z.literal("ipgeo"), lat: z.string(), lng: z.string(), op: z.enum(["ipgeoin", "ipgeonotin"]), value: z.number().int()}), z.object({condition_type: z.literal("IPGeoInZip").optional(), extra: z.number().int(), field: z.literal("ipgeo"), op: z.literal("ipgeoinzip"), value: z.number().int()}), z.object({condition_type: z.literal("IPGeoUnknown").optional(), field: z.literal("ipgeo"), op: z.literal("ipgeounknown")}), z.object({condition_type: z.literal("IPGeoZip").optional(), field: z.literal("ipgeo"), op: z.enum(["ipgeoiszip", "ipgeonotzip"]), value: z.number().int()}), z.object({condition_type: z.literal("SocialAge").optional(), field: z.literal("social_age"), op: z.enum(["is", "not"]), value: z.enum(["18-24", "25-34", "35-54", "55+"])}), z.object({condition_type: z.literal("SocialGender").optional(), field: z.literal("social_gender"), op: z.enum(["is", "not"]), value: z.enum(["male", "female"])}), z.object({condition_type: z.literal("SocialInfluence").optional(), field: z.literal("social_influence"), op: z.enum(["is", "not", "greater", "less"]), value: z.number()}), z.object({condition_type: z.literal("SocialNetworkMember").optional(), field: z.literal("social_network"), op: z.enum(["member", "notmember"]), value: z.enum(["twitter", "facebook", "linkedin", "flickr", "foursquare", "lastfm", "myspace", "quora", "vimeo", "yelp", "youtube"])}), z.object({condition_type: z.literal("SocialNetworkFollow").optional(), field: z.literal("social_network"), op: z.enum(["follow", "notfollow"]), value: z.literal("twitter_follow")}), z.object({condition_type: z.literal("AddressMerge").optional(), field: z.string(), op: z.enum(["contains", "notcontain", "blank", "blank_not"]), value: z.string().optional()}), z.object({condition_type: z.literal("ZipMerge").optional(), extra: z.string(), field: z.string(), op: z.literal("geoin"), value: z.string()}), z.object({condition_type: z.literal("BirthdayMerge").optional(), field: z.string(), op: z.enum(["is", "not", "blank", "blank_not"]), value: z.string().optional()}), z.object({condition_type: z.literal("DateMerge").optional(), field: z.string(), op: z.enum(["is", "not", "less", "blank", "blank_not", "greater"]), value: z.string().optional()}), z.object({condition_type: z.literal("SelectMerge").optional(), field: z.string(), op: z.enum(["is", "not", "blank", "blank_not", "notcontain", "contains"]), value: z.string().optional()}), z.object({condition_type: z.literal("TextMerge").optional(), field: z.string(), op: z.enum(["is", "not", "contains", "notcontain", "starts", "ends", "greater", "less", "blank", "blank_not"]), value: z.string().optional()}), z.object({condition_type: z.literal("EmailAddress").optional(), field: z.enum(["merge0", "EMAIL"]), op: z.enum(["is", "not", "contains", "notcontain", "starts", "ends", "greater", "less"]), value: z.string().optional()}), z.object({condition_type: z.literal("PredictedGender").optional(), field: z.literal("predicted_gender"), op: z.enum(["is", "not"]), value: z.enum(["male", "female"])}), z.object({condition_type: z.literal("PredictedAge").optional(), field: z.literal("predicted_age_range"), op: z.literal("is"), value: z.enum(["18-24", "25-34", "35-44", "45-54", "55-64", "65+"])}), z.object({condition_type: z.literal("NewSubscribers").optional(), field: z.literal("timestamp_opt").optional(), op: z.literal("date_within").optional(), value: z.string().optional()})])).optional(), store_id: z.string().optional()}).optional(), report_summary: z.object({click_rate: z.number().optional(), clicks: z.number().int().optional(), open_rate: z.number().optional(), opens: z.number().int().optional(), subscriber_clicks: z.number().int().optional(), unique_opens: z.number().int().optional()}).optional(), settings: z.object({authenticate: z.boolean().optional(), auto_footer: z.boolean().optional(), from_name: z.string().optional(), inline_css: z.boolean().optional(), reply_to: z.string().optional(), title: z.string().optional(), to_name: z.string().optional(), use_conversation: z.boolean().optional()}).optional(), start_time: z.string().optional(), status: z.enum(["save", "paused", "sending"]).optional(), tracking: z.object({capsule: z.object({notes: z.boolean().optional()}).optional(), clicktale: z.string().optional(), ecomm360: z.boolean().optional(), goal_tracking: z.boolean().optional(), google_analytics: z.string().optional(), html_clicks: z.boolean().optional(), opens: z.boolean().optional(), salesforce: z.object({campaign: z.boolean().optional(), notes: z.boolean().optional()}).optional(), text_clicks: z.boolean().optional()}).optional(), trigger_settings: z.object({runtime: z.object({days: z.array(z.enum(["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"])).optional(), hours: z.object({type: z.enum(["send_asap", "send_between", "send_at"])}).optional()}).optional(), workflow_emails_count: z.number().int().optional(), workflow_title: z.string().optional(), workflow_type: z.enum(["abandonedBrowse", "abandonedCart", "api", "bestCustomers", "categoryFollowup", "dateAdded", "emailFollowup", "emailSeries", "groupAdd", "groupRemove", "mandrill", "productFollowup", "purchaseFollowup", "recurringEvent", "specialEvent", "visitUrl", "welcomeSeries"])}).optional()})).optional(), total_items: z.number().int().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * List automations * * GET /3.0/automations * * Also accepts auth: oauth2 */ export const getApi30Automations = async (args: GetApi30AutomationsArgs, options?: GetApi30AutomationsOptions) => { const {baseUrl = "https://api.mailchimp.com", fetch: fetchFn = fetch, bearerToken} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.count != null) query.append("count", String(args.count)) if (args.offset != null) query.append("offset", String(args.offset)) if (args.fields != null) query.append("fields", args.fields.join(',')) if (args.exclude_fields != null) query.append("exclude_fields", args.exclude_fields.join(',')) if (args.before_create_time != null) query.append("before_create_time", String(args.before_create_time)) if (args.since_create_time != null) query.append("since_create_time", String(args.since_create_time)) if (args.before_start_time != null) query.append("before_start_time", String(args.before_start_time)) if (args.since_start_time != null) query.append("since_start_time", String(args.since_start_time)) if (args.status != null) query.append("status", String(args.status)) if (bearerToken !== undefined) headers.set('authorization', `Bearer ${bearerToken}`) const url = `${baseUrl.replace(/\/+$/, '')}/3.0/automations${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApi30AutomationsResponse, await res.json()) };