chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,202 @@
import { createLogger } from '@sim/logger'
import { WebflowIcon } from '@/components/icons'
import { requestJson } from '@/lib/api/client/request'
import {
webflowCollectionsSelectorContract,
webflowSitesSelectorContract,
} from '@/lib/api/contracts/selectors/webflow'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import type { TriggerConfig } from '../types'
const logger = createLogger('webflow-collection-item-changed-trigger')
export const webflowCollectionItemChangedTrigger: TriggerConfig = {
id: 'webflow_collection_item_changed',
name: 'Collection Item Changed',
provider: 'webflow',
description:
'Trigger workflow when an item is updated in a Webflow CMS collection (requires Webflow credentials)',
version: '1.0.0',
icon: WebflowIcon,
subBlocks: [
{
id: 'triggerCredentials',
title: 'Credentials',
type: 'oauth-input',
description: 'This trigger requires webflow credentials to access your account.',
serviceId: 'webflow',
requiredScopes: [],
required: true,
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_changed',
},
},
{
id: 'triggerSiteId',
title: 'Site',
type: 'dropdown',
placeholder: 'Select a site',
description: 'The Webflow site to monitor',
required: true,
options: [],
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_changed',
},
fetchOptions: async (blockId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) {
throw new Error('No Webflow credential selected')
}
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId },
})
return (data.sites ?? []).map((site) => ({
id: site.id,
label: site.name,
}))
} catch (error) {
logger.error('Error fetching Webflow sites:', error)
throw error
}
},
fetchOptionById: async (blockId: string, optionId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) return null
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId, siteId: optionId },
})
const site = data.sites?.find((s) => s.id === optionId)
if (site) {
return { id: site.id, label: site.name }
}
return null
} catch {
return null
}
},
dependsOn: ['triggerCredentials'],
},
{
id: 'triggerCollectionId',
title: 'Collection',
type: 'dropdown',
placeholder: 'Select a collection (optional)',
description: 'Optionally filter to monitor only a specific collection',
required: false,
options: [],
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_changed',
},
fetchOptions: async (blockId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
const siteId = useSubBlockStore.getState().getValue(blockId, 'triggerSiteId') as
| string
| null
if (!credentialId || !siteId) {
return []
}
try {
const data = await requestJson(webflowCollectionsSelectorContract, {
body: { credential: credentialId, siteId },
})
return (data.collections ?? []).map((collection) => ({
id: collection.id,
label: collection.name,
}))
} catch (error) {
logger.error('Error fetching Webflow collections:', error)
throw error
}
},
fetchOptionById: async (blockId: string, optionId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
const siteId = useSubBlockStore.getState().getValue(blockId, 'triggerSiteId') as
| string
| null
if (!credentialId || !siteId) return null
try {
const data = await requestJson(webflowCollectionsSelectorContract, {
body: { credential: credentialId, siteId },
})
const collection = data.collections?.find((c) => c.id === optionId)
if (collection) {
return { id: collection.id, label: collection.name }
}
return null
} catch {
return null
}
},
dependsOn: ['triggerCredentials', 'triggerSiteId'],
},
{
id: 'triggerInstructions',
title: 'Setup Instructions',
hideFromPreview: true,
type: 'text',
defaultValue: [
'Connect your Webflow account using the "Select Webflow credential" button above.',
'Select your Webflow site from the dropdown.',
'Optionally select a collection to monitor only specific collections.',
'If no collection is selected, the trigger will fire for items changed in any collection on the site.',
'The webhook will trigger whenever an existing item is updated in the specified collection(s).',
'Make sure your Webflow account has appropriate permissions for the specified site.',
]
.map(
(instruction, index) =>
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
)
.join(''),
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_changed',
},
},
],
outputs: {
siteId: {
type: 'string',
description: 'The site ID where the event occurred',
},
collectionId: {
type: 'string',
description: 'The collection ID where the item was changed',
},
payload: {
id: { type: 'string', description: 'The ID of the changed item' },
cmsLocaleId: { type: 'string', description: 'CMS locale ID' },
lastPublished: { type: 'string', description: 'Last published timestamp' },
lastUpdated: { type: 'string', description: 'Last updated timestamp' },
createdOn: { type: 'string', description: 'Timestamp when the item was created' },
isArchived: { type: 'boolean', description: 'Whether the item is archived' },
isDraft: { type: 'boolean', description: 'Whether the item is a draft' },
fieldData: { type: 'object', description: 'The updated field data of the item' },
},
},
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
@@ -0,0 +1,216 @@
import { createLogger } from '@sim/logger'
import { WebflowIcon } from '@/components/icons'
import { requestJson } from '@/lib/api/client/request'
import {
webflowCollectionsSelectorContract,
webflowSitesSelectorContract,
} from '@/lib/api/contracts/selectors/webflow'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import type { TriggerConfig } from '../types'
const logger = createLogger('webflow-collection-item-created-trigger')
export const webflowCollectionItemCreatedTrigger: TriggerConfig = {
id: 'webflow_collection_item_created',
name: 'Collection Item Created',
provider: 'webflow',
description:
'Trigger workflow when a new item is created in a Webflow CMS collection (requires Webflow credentials)',
version: '1.0.0',
icon: WebflowIcon,
subBlocks: [
{
id: 'selectedTriggerId',
title: 'Trigger Type',
type: 'dropdown',
mode: 'trigger',
options: [
{ label: 'Collection Item Created', id: 'webflow_collection_item_created' },
{ label: 'Collection Item Changed', id: 'webflow_collection_item_changed' },
{ label: 'Collection Item Deleted', id: 'webflow_collection_item_deleted' },
{ label: 'Form Submission', id: 'webflow_form_submission' },
],
value: () => 'webflow_collection_item_created',
required: true,
},
{
id: 'triggerCredentials',
title: 'Credentials',
type: 'oauth-input',
description: 'This trigger requires webflow credentials to access your account.',
serviceId: 'webflow',
requiredScopes: [],
required: true,
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_created',
},
},
{
id: 'triggerSiteId',
title: 'Site',
type: 'dropdown',
placeholder: 'Select a site',
description: 'The Webflow site to monitor',
required: true,
options: [],
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_created',
},
fetchOptions: async (blockId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) {
throw new Error('No Webflow credential selected')
}
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId },
})
return (data.sites ?? []).map((site) => ({
id: site.id,
label: site.name,
}))
} catch (error) {
logger.error('Error fetching Webflow sites:', error)
throw error
}
},
fetchOptionById: async (blockId: string, optionId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) return null
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId, siteId: optionId },
})
const site = data.sites?.find((s) => s.id === optionId)
if (site) {
return { id: site.id, label: site.name }
}
return null
} catch {
return null
}
},
dependsOn: ['triggerCredentials'],
},
{
id: 'triggerCollectionId',
title: 'Collection',
type: 'dropdown',
placeholder: 'Select a collection (optional)',
description: 'Optionally filter to monitor only a specific collection',
required: false,
options: [],
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_created',
},
fetchOptions: async (blockId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
const siteId = useSubBlockStore.getState().getValue(blockId, 'triggerSiteId') as
| string
| null
if (!credentialId || !siteId) {
return []
}
try {
const data = await requestJson(webflowCollectionsSelectorContract, {
body: { credential: credentialId, siteId },
})
return (data.collections ?? []).map((collection) => ({
id: collection.id,
label: collection.name,
}))
} catch (error) {
logger.error('Error fetching Webflow collections:', error)
throw error
}
},
fetchOptionById: async (blockId: string, optionId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
const siteId = useSubBlockStore.getState().getValue(blockId, 'triggerSiteId') as
| string
| null
if (!credentialId || !siteId) return null
try {
const data = await requestJson(webflowCollectionsSelectorContract, {
body: { credential: credentialId, siteId },
})
const collection = data.collections?.find((c) => c.id === optionId)
if (collection) {
return { id: collection.id, label: collection.name }
}
return null
} catch {
return null
}
},
dependsOn: ['triggerCredentials', 'triggerSiteId'],
},
{
id: 'triggerInstructions',
title: 'Setup Instructions',
hideFromPreview: true,
type: 'text',
defaultValue: [
'Connect your Webflow account using the "Select Webflow credential" button above.',
'Select your Webflow site from the dropdown.',
'Optionally select a collection to monitor only specific collections.',
'If no collection is selected, the trigger will fire for items created in any collection on the site.',
'The webhook will trigger whenever a new item is created in the specified collection(s).',
'Make sure your Webflow account has appropriate permissions for the specified site.',
]
.map(
(instruction, index) =>
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
)
.join(''),
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_created',
},
},
],
outputs: {
siteId: {
type: 'string',
description: 'The site ID where the event occurred',
},
collectionId: {
type: 'string',
description: 'The collection ID where the item was created',
},
payload: {
id: { type: 'string', description: 'The ID of the created item' },
cmsLocaleId: { type: 'string', description: 'CMS locale ID' },
lastPublished: { type: 'string', description: 'Last published timestamp' },
lastUpdated: { type: 'string', description: 'Last updated timestamp' },
createdOn: { type: 'string', description: 'Timestamp when the item was created' },
isArchived: { type: 'boolean', description: 'Whether the item is archived' },
isDraft: { type: 'boolean', description: 'Whether the item is a draft' },
fieldData: { type: 'object', description: 'The field data of the item' },
},
},
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
@@ -0,0 +1,197 @@
import { createLogger } from '@sim/logger'
import { WebflowIcon } from '@/components/icons'
import { requestJson } from '@/lib/api/client/request'
import {
webflowCollectionsSelectorContract,
webflowSitesSelectorContract,
} from '@/lib/api/contracts/selectors/webflow'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import type { TriggerConfig } from '../types'
const logger = createLogger('webflow-collection-item-deleted-trigger')
export const webflowCollectionItemDeletedTrigger: TriggerConfig = {
id: 'webflow_collection_item_deleted',
name: 'Collection Item Deleted',
provider: 'webflow',
description:
'Trigger workflow when an item is deleted from a Webflow CMS collection (requires Webflow credentials)',
version: '1.0.0',
icon: WebflowIcon,
subBlocks: [
{
id: 'triggerCredentials',
title: 'Credentials',
type: 'oauth-input',
description: 'This trigger requires webflow credentials to access your account.',
serviceId: 'webflow',
requiredScopes: [],
required: true,
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_deleted',
},
},
{
id: 'triggerSiteId',
title: 'Site',
type: 'dropdown',
placeholder: 'Select a site',
description: 'The Webflow site to monitor',
required: true,
options: [],
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_deleted',
},
fetchOptions: async (blockId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) {
throw new Error('No Webflow credential selected')
}
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId },
})
return (data.sites ?? []).map((site) => ({
id: site.id,
label: site.name,
}))
} catch (error) {
logger.error('Error fetching Webflow sites:', error)
throw error
}
},
fetchOptionById: async (blockId: string, optionId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) return null
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId, siteId: optionId },
})
const site = data.sites?.find((s) => s.id === optionId)
if (site) {
return { id: site.id, label: site.name }
}
return null
} catch {
return null
}
},
dependsOn: ['triggerCredentials'],
},
{
id: 'triggerCollectionId',
title: 'Collection',
type: 'dropdown',
placeholder: 'Select a collection (optional)',
description: 'Optionally filter to monitor only a specific collection',
required: false,
options: [],
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_deleted',
},
fetchOptions: async (blockId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
const siteId = useSubBlockStore.getState().getValue(blockId, 'triggerSiteId') as
| string
| null
if (!credentialId || !siteId) {
return []
}
try {
const data = await requestJson(webflowCollectionsSelectorContract, {
body: { credential: credentialId, siteId },
})
return (data.collections ?? []).map((collection) => ({
id: collection.id,
label: collection.name,
}))
} catch (error) {
logger.error('Error fetching Webflow collections:', error)
throw error
}
},
fetchOptionById: async (blockId: string, optionId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
const siteId = useSubBlockStore.getState().getValue(blockId, 'triggerSiteId') as
| string
| null
if (!credentialId || !siteId) return null
try {
const data = await requestJson(webflowCollectionsSelectorContract, {
body: { credential: credentialId, siteId },
})
const collection = data.collections?.find((c) => c.id === optionId)
if (collection) {
return { id: collection.id, label: collection.name }
}
return null
} catch {
return null
}
},
dependsOn: ['triggerCredentials', 'triggerSiteId'],
},
{
id: 'triggerInstructions',
title: 'Setup Instructions',
hideFromPreview: true,
type: 'text',
defaultValue: [
'Connect your Webflow account using the "Select Webflow credential" button above.',
'Select your Webflow site from the dropdown.',
'Optionally select a collection to monitor only specific collections.',
'If no collection is selected, the trigger will fire for items deleted in any collection on the site.',
'The webhook will trigger whenever an item is deleted from the specified collection(s).',
'Note: Once an item is deleted, only minimal information (ID, collection, site) is available.',
'Make sure your Webflow account has appropriate permissions for the specified site.',
]
.map(
(instruction, index) =>
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
)
.join(''),
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_collection_item_deleted',
},
},
],
outputs: {
siteId: {
type: 'string',
description: 'The site ID where the event occurred',
},
collectionId: {
type: 'string',
description: 'The collection ID where the item was deleted',
},
payload: {
id: { type: 'string', description: 'The ID of the deleted item' },
deletedOn: { type: 'string', description: 'Timestamp when the item was deleted' },
},
},
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
@@ -0,0 +1,184 @@
import { createLogger } from '@sim/logger'
import { WebflowIcon } from '@/components/icons'
import { requestJson } from '@/lib/api/client/request'
import { webflowSitesSelectorContract } from '@/lib/api/contracts/selectors/webflow'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import type { TriggerConfig } from '../types'
const logger = createLogger('webflow-form-submission-trigger')
export const webflowFormSubmissionTrigger: TriggerConfig = {
id: 'webflow_form_submission',
name: 'Form Submission',
provider: 'webflow',
description:
'Trigger workflow when a form is submitted on a Webflow site (requires Webflow credentials)',
version: '1.0.0',
icon: WebflowIcon,
subBlocks: [
{
id: 'triggerCredentials',
title: 'Credentials',
type: 'oauth-input',
description: 'This trigger requires webflow credentials to access your account.',
serviceId: 'webflow',
requiredScopes: ['forms:read'],
required: true,
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_form_submission',
},
},
{
id: 'triggerSiteId',
title: 'Site',
type: 'dropdown',
placeholder: 'Select a site',
description: 'The Webflow site to monitor',
required: true,
options: [],
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_form_submission',
},
fetchOptions: async (blockId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) {
throw new Error('No Webflow credential selected')
}
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId },
})
return (data.sites ?? []).map((site) => ({
id: site.id,
label: site.name,
}))
} catch (error) {
logger.error('Error fetching Webflow sites:', error)
throw error
}
},
fetchOptionById: async (blockId: string, optionId: string) => {
const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as
| string
| null
if (!credentialId) return null
try {
const data = await requestJson(webflowSitesSelectorContract, {
body: { credential: credentialId, siteId: optionId },
})
const site = data.sites?.find((s) => s.id === optionId)
if (site) {
return { id: site.id, label: site.name }
}
return null
} catch {
return null
}
},
dependsOn: ['triggerCredentials'],
},
{
id: 'formName',
title: 'Form Name',
type: 'short-input',
placeholder: 'Contact Form (optional)',
description:
'The name of the specific form to monitor (optional - leave empty for all forms)',
required: false,
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_form_submission',
},
},
{
id: 'triggerInstructions',
title: 'Setup Instructions',
hideFromPreview: true,
type: 'text',
defaultValue: [
'Connect your Webflow account using the "Select Webflow credential" button above.',
'Select your Webflow site from the dropdown.',
'Optionally enter the Form Name to monitor only a specific form.',
'If no Form Name is provided, the trigger will fire for any form submission on the site.',
'The webhook will trigger whenever a form is submitted on the specified site.',
'Form data will be included in the payload with all submitted field values.',
'Make sure your Webflow account has appropriate permissions for the specified site.',
]
.map(
(instruction, index) =>
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
)
.join(''),
mode: 'trigger',
condition: {
field: 'selectedTriggerId',
value: 'webflow_form_submission',
},
},
],
outputs: {
siteId: {
type: 'string',
description: 'The site ID where the form was submitted',
},
formId: {
type: 'string',
description: 'The form ID',
},
name: {
type: 'string',
description: 'The name of the form',
},
id: {
type: 'string',
description: 'The unique ID of the form submission',
},
submittedAt: {
type: 'string',
description: 'Timestamp when the form was submitted',
},
data: {
type: 'object',
description:
'The form submission field data (keys are field names, values are submitted data)',
},
schema: {
type: 'array',
description: 'Form schema describing each field',
items: {
type: 'object',
properties: {
fieldName: { type: 'string', description: 'Name of the form field' },
fieldType: {
type: 'string',
description: 'Type of input (e.g., FormTextInput, FormEmail)',
},
fieldElementId: {
type: 'string',
description: 'Unique identifier for the form element (UUID)',
},
},
},
},
formElementId: {
type: 'string',
description: 'The form element ID',
},
},
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
+4
View File
@@ -0,0 +1,4 @@
export { webflowCollectionItemChangedTrigger } from './collection_item_changed'
export { webflowCollectionItemCreatedTrigger } from './collection_item_created'
export { webflowCollectionItemDeletedTrigger } from './collection_item_deleted'
export { webflowFormSubmissionTrigger } from './form_submission'