improvement(serializer): canonical subblock, serialization cleanups, schedules/webhooks are deployment version friendly (#2848)

* hide form deployment tab from docs

* progress

* fix resolution

* cleanup code

* fix positioning

* cleanup dead sockets adv mode ops

* address greptile comments

* fix tests plus more simplification

* fix cleanup

* bring back advanced mode with specific definition

* revert feature flags

* improvement(subblock): ui

* resolver change to make all var references optional chaining

* fix(webhooks/schedules): deployment version friendly

* fix tests

* fix credential sets with new lifecycle

* prep merge

* add back migration

* fix display check for adv fields

* fix trigger vs block scoping

---------

Co-authored-by: Emir Karabeg <emirkarabeg@berkeley.edu>
This commit is contained in:
Vikhyath Mondreti
2026-01-16 15:23:43 -08:00
committed by GitHub
parent ce3ddb6ba0
commit 78e4ca9d45
70 changed files with 12806 additions and 1011 deletions

View File

@@ -126,16 +126,14 @@ describe('BlockResolver', () => {
expect(resolver.resolve('<source.items.1.id>', ctx)).toBe(2)
})
it.concurrent('should throw error for non-existent path', () => {
it.concurrent('should return undefined for non-existent path', () => {
const workflow = createTestWorkflow([{ id: 'source' }])
const resolver = new BlockResolver(workflow)
const ctx = createTestContext('current', {
source: { existing: 'value' },
})
expect(() => resolver.resolve('<source.nonexistent>', ctx)).toThrow(
/No value found at path "nonexistent" in block "source"/
)
expect(resolver.resolve('<source.nonexistent>', ctx)).toBeUndefined()
})
it.concurrent('should return undefined for non-existent block', () => {
@@ -971,19 +969,17 @@ describe('BlockResolver', () => {
source: { value: undefined, other: 'exists' },
})
expect(() => resolver.resolve('<source.value>', ctx)).toThrow()
expect(resolver.resolve('<source.value>', ctx)).toBeUndefined()
})
it.concurrent('should handle deeply nested path errors', () => {
it.concurrent('should return undefined for deeply nested non-existent path', () => {
const workflow = createTestWorkflow([{ id: 'source' }])
const resolver = new BlockResolver(workflow)
const ctx = createTestContext('current', {
source: { level1: { level2: {} } },
})
expect(() => resolver.resolve('<source.level1.level2.level3>', ctx)).toThrow(
/No value found at path "level1.level2.level3"/
)
expect(resolver.resolve('<source.level1.level2.level3>', ctx)).toBeUndefined()
})
})
})

View File

@@ -108,11 +108,7 @@ export class BlockResolver implements Resolver {
}
}
// If still undefined, throw error with original path
const availableKeys = output && typeof output === 'object' ? Object.keys(output) : []
throw new Error(
`No value found at path "${pathParts.join('.')}" in block "${blockName}". Available fields: ${availableKeys.join(', ')}`
)
return undefined
}
private getBlockOutput(blockId: string, context: ResolutionContext): any {