import { defineAction } from "../../../automation/actions" import type { Webflow } from "webflow-api" import * as serializers from "webflow-api/serialization" import * as z from "zod" import { getWebflowApi, webflowAction, webflowActionSchemas, webflowInputSchema, webflowObjectSchema, webflowRequest, webflowVoidSchema, type WebflowInputValue, } from "../lib" type CollectionInput = WebflowInputValue & { collectionId: string } type ItemInput = CollectionInput & { itemId: string } type CreateItemRequest = Omit & { fieldData?: Webflow.CollectionItemPostSingle["fieldData"] items?: Webflow.CollectionItemPostSingle[] skipInvalidFiles?: boolean } type CreateItemLiveRequest = Omit & { fieldData?: Webflow.CollectionItem["fieldData"] items?: Webflow.CollectionItem[] skipInvalidFiles?: boolean } type UpdateItemRequest = Webflow.CollectionItemPatchSingle & { skipInvalidFiles?: boolean } type PublishItemsInput = CollectionInput<{ itemIds?: string[] items?: Array<{ cmsLocaleIds?: string[]; id: string }> }> /** Lists staged CMS items with locale, name, slug, sort, and pagination filters. */ export const listWebflowCollectionItems = webflowAction< CollectionInput, Webflow.CollectionItemList >( defineAction("List Webflow collection items") .describe("Lists staged CMS items with filtering and pagination.") .account("webflow", "cms:read") .input( webflowInputSchema< CollectionInput >( webflowActionSchemas.parameters(["collectionId"], { cmsLocaleId: z.string().trim().min(1).optional(), lastPublished: z .object({ gte: z.string().datetime().optional(), lte: z.string().datetime().optional(), }) .optional(), limit: z.number().int().min(1).max(100).optional(), name: z.string().optional(), offset: z.number().int().nonnegative().optional(), slug: z.string().optional(), sortBy: z.enum(["lastPublished", "name", "slug"]).optional(), sortOrder: z.enum(["asc", "desc"]).optional(), }), ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "safe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.listItems( input.collectionId, webflowItemsListRequest(input, "collectionId"), ), ), ) /** Lists the currently published version of CMS items. */ export const listLiveWebflowCollectionItems = webflowAction< CollectionInput, Webflow.CollectionItemList >( defineAction("List live Webflow collection items") .describe("Lists published CMS items with filtering and pagination.") .account("webflow", "cms:read") .input( webflowInputSchema< CollectionInput >( webflowActionSchemas.parameters(["collectionId"], { cmsLocaleId: z.string().trim().min(1).optional(), lastPublished: z .object({ gte: z.string().datetime().optional(), lte: z.string().datetime().optional(), }) .optional(), limit: z.number().int().min(1).max(100).optional(), name: z.string().optional(), offset: z.number().int().nonnegative().optional(), slug: z.string().optional(), sortBy: z.enum(["lastPublished", "name", "slug"]).optional(), sortOrder: z.enum(["asc", "desc"]).optional(), }), ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "safe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.listItemsLive( input.collectionId, webflowItemsListRequest(input, "collectionId"), ), ), ) /** Retrieves one staged Webflow CMS item. */ export const getWebflowCollectionItem = webflowAction< ItemInput, Webflow.CollectionItem >( defineAction("Get Webflow collection item") .describe("Retrieves one staged CMS item in a selected locale.") .account("webflow", "cms:read") .input( webflowInputSchema>( webflowActionSchemas.parameters(["collectionId", "itemId"], { cmsLocaleId: z.string().trim().min(1).optional(), }), ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "safe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.getItem( input.collectionId, input.itemId, webflowRequest(input, "collectionId", "itemId"), ), ), ) /** Retrieves the currently published version of one Webflow CMS item. */ export const getLiveWebflowCollectionItem = webflowAction< ItemInput, Webflow.CollectionItem >( defineAction("Get live Webflow collection item") .describe("Retrieves one published CMS item in a selected locale.") .account("webflow", "cms:read") .input( webflowInputSchema< ItemInput >( webflowActionSchemas.parameters(["collectionId", "itemId"], { cmsLocaleId: z.string().trim().min(1).optional(), }), ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "safe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.getItemLive( input.collectionId, input.itemId, webflowRequest(input, "collectionId", "itemId"), ), ), ) /** Creates one or more staged Webflow CMS items. */ export const createWebflowCollectionItem = webflowAction< CollectionInput, Webflow.CollectionItem >( defineAction("Create Webflow collection item") .describe("Creates one or more staged CMS items in a collection.") .account("webflow", "cms:write") .input( webflowInputSchema>( webflowActionSchemas.parameters(["collectionId"], { skipInvalidFiles: z.boolean().optional(), }), serializers.collections.ItemsCreateItemRequestBody, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.createItem( input.collectionId, webflowRequest(input, "collectionId"), ), ), ) /** Creates and immediately publishes one or more Webflow CMS items. */ export const createLiveWebflowCollectionItem = webflowAction< CollectionInput, Webflow.CollectionItem >( defineAction("Create live Webflow collection item") .describe("Creates and publishes one or more CMS items.") .account("webflow", "cms:write") .input( webflowInputSchema>( webflowActionSchemas.parameters(["collectionId"], { skipInvalidFiles: z.boolean().optional(), }), serializers.collections.ItemsCreateItemLiveRequestBody, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.createItemLive( input.collectionId, webflowRequest(input, "collectionId"), ), ), ) /** Creates localized variants for multiple Webflow CMS items. */ export const createLocalizedWebflowCollectionItems = webflowAction< CollectionInput, Webflow.BulkCollectionItem >( defineAction("Create localized Webflow collection items") .describe("Creates CMS item variants across multiple locales in bulk.") .account("webflow", "cms:write") .input( webflowInputSchema< CollectionInput >( webflowActionSchemas.parameters(["collectionId"], { skipInvalidFiles: z.boolean().optional(), }), serializers.collections.CreateBulkCollectionItemRequestBody, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.createItems( input.collectionId, webflowRequest(input, "collectionId"), ), ), ) /** Updates one staged Webflow CMS item. */ export const updateWebflowCollectionItem = webflowAction< ItemInput, Webflow.CollectionItem >( defineAction("Update Webflow collection item") .describe("Updates fields, draft state, or archive state for one CMS item.") .account("webflow", "cms:write") .input( webflowInputSchema>( webflowActionSchemas.parameters(["collectionId", "itemId"], { skipInvalidFiles: z.boolean().optional(), }), serializers.CollectionItemPatchSingle, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.updateItem( input.collectionId, input.itemId, webflowRequest(input, "collectionId", "itemId"), ), ), ) /** Updates one published Webflow CMS item immediately. */ export const updateLiveWebflowCollectionItem = webflowAction< ItemInput, Webflow.CollectionItem >( defineAction("Update live Webflow collection item") .describe("Updates and publishes one CMS item immediately.") .account("webflow", "cms:write") .input( webflowInputSchema>( webflowActionSchemas.parameters(["collectionId", "itemId"], { skipInvalidFiles: z.boolean().optional(), }), serializers.CollectionItemPatchSingle, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.updateItemLive( input.collectionId, input.itemId, webflowRequest(input, "collectionId", "itemId"), ), ), ) /** Updates up to 100 staged Webflow CMS items. */ export const updateWebflowCollectionItems = webflowAction< CollectionInput, Webflow.collections.ItemsUpdateItemsResponse >( defineAction("Update Webflow collection items") .describe("Updates up to 100 staged CMS items across selected locales.") .account("webflow", "cms:write") .input( webflowInputSchema< CollectionInput >( webflowActionSchemas.parameters(["collectionId"], { skipInvalidFiles: z.boolean().optional(), }), serializers.collections.ItemsUpdateItemsRequest, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.updateItems( input.collectionId, webflowRequest(input, "collectionId"), ), ), ) /** Updates and publishes multiple Webflow CMS items. */ export const updateLiveWebflowCollectionItems = webflowAction< CollectionInput, Webflow.CollectionItemListNoPagination >( defineAction("Update live Webflow collection items") .describe("Updates and publishes multiple CMS items immediately.") .account("webflow", "cms:write") .input( webflowInputSchema< CollectionInput >( webflowActionSchemas.parameters(["collectionId"], { skipInvalidFiles: z.boolean().optional(), }), serializers.collections.ItemsUpdateItemsLiveRequest, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.updateItemsLive( input.collectionId, webflowRequest(input, "collectionId"), ), ), ) /** Publishes or unpublishes selected staged Webflow CMS items. */ export const publishWebflowCollectionItems = webflowAction< PublishItemsInput, Webflow.collections.ItemsPublishItemResponse >( defineAction("Publish Webflow collection items") .describe("Publishes or unpublishes selected staged CMS items.") .account("webflow", "cms:write") .input( webflowInputSchema( webflowActionSchemas.id("collectionId"), serializers.collections.ItemsPublishItemRequest, ), ) .output(webflowObjectSchema()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input }) => await getWebflowApi(account).collections.items.publishItem( input.collectionId, webflowRequest(input, "collectionId"), ), ), ) /** Deletes one staged Webflow CMS item. */ export const deleteWebflowCollectionItem = webflowAction< ItemInput, void >( defineAction("Delete Webflow collection item") .describe("Deletes one staged CMS item in a selected locale.") .account("webflow", "cms:write") .input( webflowInputSchema>( webflowActionSchemas.parameters(["collectionId", "itemId"], { cmsLocaleId: z.string().trim().min(1).optional(), }), ), ) .output(webflowVoidSchema()) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { await getWebflowApi(account).collections.items.deleteItem( input.collectionId, input.itemId, webflowRequest(input, "collectionId", "itemId"), ) }), ) /** Deletes one published Webflow CMS item immediately. */ export const deleteLiveWebflowCollectionItem = webflowAction< ItemInput, void >( defineAction("Delete live Webflow collection item") .describe("Deletes one published CMS item in a selected locale.") .account("webflow", "cms:write") .input( webflowInputSchema< ItemInput >( webflowActionSchemas.parameters(["collectionId", "itemId"], { cmsLocaleId: z.string().trim().min(1).optional(), }), ), ) .output(webflowVoidSchema()) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { await getWebflowApi(account).collections.items.deleteItemLive( input.collectionId, input.itemId, webflowRequest(input, "collectionId", "itemId"), ) }), ) /** Deletes multiple staged Webflow CMS items. */ export const deleteWebflowCollectionItems = webflowAction< CollectionInput, void >( defineAction("Delete Webflow collection items") .describe("Deletes multiple staged CMS items from a collection.") .account("webflow", "cms:write") .input( webflowInputSchema< CollectionInput >( webflowActionSchemas.id("collectionId"), serializers.collections.ItemsDeleteItemsRequest, ), ) .output(webflowVoidSchema()) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { await getWebflowApi(account).collections.items.deleteItems( input.collectionId, webflowRequest(input, "collectionId"), ) }), ) /** Deletes multiple published Webflow CMS items immediately. */ export const deleteLiveWebflowCollectionItems = webflowAction< CollectionInput, void >( defineAction("Delete live Webflow collection items") .describe("Deletes multiple published CMS items immediately.") .account("webflow", "cms:write") .input( webflowInputSchema< CollectionInput >( webflowActionSchemas.id("collectionId"), serializers.collections.ItemsDeleteItemsLiveRequest, ), ) .output(webflowVoidSchema()) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { await getWebflowApi(account).collections.items.deleteItemsLive( input.collectionId, webflowRequest(input, "collectionId"), ) }), ) /** * Restores Webflow SDK date objects after portable input validation. * * @param input - Portable collection-item list parameters. * @param keys - Route identifier keys to omit. */ function webflowItemsListRequest( input: Record, ...keys: string[] ): Webflow.collections.ItemsListItemsRequest { const request = webflowRequest< WebflowInputValue >(input, ...keys) return { ...request, lastPublished: request.lastPublished === undefined ? undefined : { gte: request.lastPublished.gte === undefined ? undefined : new Date(request.lastPublished.gte), lte: request.lastPublished.lte === undefined ? undefined : new Date(request.lastPublished.lte), }, } }