d25d482dc2
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
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
188 lines
5.2 KiB
TypeScript
188 lines
5.2 KiB
TypeScript
import type { SubBlockType } from '@sim/workflow-types/blocks'
|
|
|
|
export const WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS = {
|
|
type: 'subflowType',
|
|
iterations: 'subflowIterations',
|
|
items: 'subflowItems',
|
|
condition: 'subflowCondition',
|
|
batchSize: 'subflowBatchSize',
|
|
} as const
|
|
|
|
export type WorkflowSearchSubflowFieldId =
|
|
(typeof WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS)[keyof typeof WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS]
|
|
|
|
export type WorkflowSearchSubflowEditableValue = string | number
|
|
|
|
interface WorkflowSearchSubflowBlock {
|
|
type: string
|
|
data?: {
|
|
loopType?: string
|
|
parallelType?: string
|
|
count?: unknown
|
|
batchSize?: unknown
|
|
collection?: unknown
|
|
whileCondition?: unknown
|
|
doWhileCondition?: unknown
|
|
}
|
|
}
|
|
|
|
export interface WorkflowSearchSubflowField {
|
|
id: WorkflowSearchSubflowFieldId
|
|
title: string
|
|
type: SubBlockType
|
|
value: string
|
|
editable: boolean
|
|
valueKind: 'number' | 'text' | 'enum'
|
|
reason?: string
|
|
}
|
|
|
|
export function getWorkflowSearchSubflowFields(
|
|
block: WorkflowSearchSubflowBlock
|
|
): WorkflowSearchSubflowField[] {
|
|
if (block.type === 'loop') {
|
|
const loopType = block.data?.loopType ?? 'for'
|
|
const fields: WorkflowSearchSubflowField[] = [
|
|
{
|
|
id: WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.type,
|
|
title: 'Loop Type',
|
|
type: 'combobox',
|
|
value: String(loopType),
|
|
editable: false,
|
|
valueKind: 'enum',
|
|
reason: 'Subflow type is changed from the block sidebar',
|
|
},
|
|
]
|
|
|
|
if (loopType === 'for') {
|
|
fields.push({
|
|
id: WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.iterations,
|
|
title: 'Loop Iterations',
|
|
type: 'short-input',
|
|
value: String(block.data?.count ?? 5),
|
|
editable: true,
|
|
valueKind: 'number',
|
|
})
|
|
} else if (loopType === 'forEach') {
|
|
fields.push({
|
|
id: WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.items,
|
|
title: 'Collection Items',
|
|
type: 'code',
|
|
value: String(block.data?.collection ?? ''),
|
|
editable: true,
|
|
valueKind: 'text',
|
|
})
|
|
} else {
|
|
fields.push({
|
|
id: WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.condition,
|
|
title: 'While Condition',
|
|
type: 'code',
|
|
value: String(
|
|
loopType === 'doWhile'
|
|
? (block.data?.doWhileCondition ?? '')
|
|
: (block.data?.whileCondition ?? '')
|
|
),
|
|
editable: true,
|
|
valueKind: 'text',
|
|
})
|
|
}
|
|
|
|
return fields
|
|
}
|
|
|
|
if (block.type === 'parallel') {
|
|
const parallelType = block.data?.parallelType ?? 'count'
|
|
return [
|
|
{
|
|
id: WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.type,
|
|
title: 'Parallel Type',
|
|
type: 'combobox',
|
|
value: String(parallelType),
|
|
editable: false,
|
|
valueKind: 'enum',
|
|
reason: 'Subflow type is changed from the block sidebar',
|
|
},
|
|
{
|
|
id:
|
|
parallelType === 'count'
|
|
? WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.iterations
|
|
: WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.items,
|
|
title: parallelType === 'count' ? 'Parallel Iterations' : 'Parallel Items',
|
|
type: parallelType === 'count' ? 'short-input' : 'code',
|
|
value:
|
|
parallelType === 'count'
|
|
? String(block.data?.count ?? 5)
|
|
: String(block.data?.collection ?? ''),
|
|
editable: true,
|
|
valueKind: parallelType === 'count' ? 'number' : 'text',
|
|
},
|
|
{
|
|
id: WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.batchSize,
|
|
title: 'Parallel Batch Size',
|
|
type: 'short-input',
|
|
value: String(block.data?.batchSize ?? 20),
|
|
editable: true,
|
|
valueKind: 'number',
|
|
},
|
|
]
|
|
}
|
|
|
|
return []
|
|
}
|
|
|
|
export function getWorkflowSearchSubflowField(
|
|
block: WorkflowSearchSubflowBlock,
|
|
fieldId: WorkflowSearchSubflowFieldId
|
|
) {
|
|
return getWorkflowSearchSubflowFields(block).find((field) => field.id === fieldId)
|
|
}
|
|
|
|
export function workflowSearchSubflowFieldMatchesExpected(
|
|
block: WorkflowSearchSubflowBlock,
|
|
fieldId: WorkflowSearchSubflowFieldId,
|
|
expectedValue: unknown
|
|
): boolean {
|
|
const field = getWorkflowSearchSubflowField(block, fieldId)
|
|
return Boolean(field && String(field.value) === String(expectedValue))
|
|
}
|
|
|
|
export function parseWorkflowSearchSubflowReplacement({
|
|
blockType,
|
|
fieldId,
|
|
replacement,
|
|
}: {
|
|
blockType: 'loop' | 'parallel'
|
|
fieldId: WorkflowSearchSubflowFieldId
|
|
replacement: string
|
|
}):
|
|
| { success: true; value: WorkflowSearchSubflowEditableValue }
|
|
| { success: false; reason: string } {
|
|
if (
|
|
fieldId !== WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.iterations &&
|
|
fieldId !== WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.batchSize
|
|
) {
|
|
return { success: true, value: replacement }
|
|
}
|
|
|
|
const trimmed = replacement.trim()
|
|
if (!/^\d+$/.test(trimmed)) {
|
|
return { success: false, reason: 'Subflow iteration count must be a whole number' }
|
|
}
|
|
|
|
const count = Number.parseInt(trimmed, 10)
|
|
const maxBatchSize = 20
|
|
if (
|
|
count < 1 ||
|
|
(fieldId === WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.batchSize && count > maxBatchSize)
|
|
) {
|
|
return {
|
|
success: false,
|
|
reason:
|
|
fieldId === WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.batchSize
|
|
? `Parallel batch size must be between 1 and ${maxBatchSize}`
|
|
: 'Subflow iteration count must be greater than 0',
|
|
}
|
|
}
|
|
|
|
return { success: true, value: count }
|
|
}
|