chore: import upstream snapshot with attribution
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

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,164 @@
/**
* @vitest-environment node
*/
import { describe, expect, it } from 'vitest'
import { clearCredentialInValue } from '@/lib/credentials/deletion'
const TARGET = 'cred_target123'
const OTHER = 'cred_other999'
describe('clearCredentialInValue', () => {
it('clears matching subBlock value with id="credential"', () => {
const input = { id: 'credential', type: 'oauth-input', value: TARGET }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
expect(result.value).toEqual({ id: 'credential', type: 'oauth-input', value: '' })
})
it('clears matching subBlock value with id="manualCredential"', () => {
const input = { id: 'manualCredential', type: 'short-input', value: TARGET }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
expect(result.value).toEqual({ id: 'manualCredential', type: 'short-input', value: '' })
})
it('clears matching subBlock value with id="triggerCredentials"', () => {
const input = { id: 'triggerCredentials', value: TARGET }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
expect((result.value as { value: string }).value).toBe('')
})
it('leaves unrelated subBlock value untouched', () => {
const input = { id: 'someOtherField', value: TARGET }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(false)
expect(result.value).toBe(input)
})
it('leaves matching subBlock with non-matching value untouched', () => {
const input = { id: 'credential', value: OTHER }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(false)
expect(result.value).toBe(input)
})
it('clears nested tools[].params.credential', () => {
const input = {
id: 'tools',
value: [
{ type: 'gmail_send', params: { credential: TARGET, to: 'a@b.com' } },
{ type: 'slack_message', params: { credential: OTHER, channel: '#x' } },
],
}
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
const value = result.value as { value: Array<{ params: { credential: string } }> }
expect(value.value[0].params.credential).toBe('')
expect(value.value[1].params.credential).toBe(OTHER)
})
it('walks workflow_blocks-style keyed subBlocks structure', () => {
const input = {
credential: { id: 'credential', value: TARGET },
messages: { id: 'messages', value: 'hello' },
tools: {
id: 'tools',
value: [{ type: 'x', params: { credential: TARGET } }],
},
}
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
const value = result.value as typeof input
expect(value.credential.value).toBe('')
expect(value.messages.value).toBe('hello')
expect(value.tools.value[0].params.credential).toBe('')
})
it('walks deployment-style nested blocks structure', () => {
const input = {
blocks: {
block1: {
subBlocks: {
credential: { id: 'credential', value: TARGET },
},
},
block2: {
subBlocks: {
other: { id: 'other', value: 'unrelated' },
},
},
},
}
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
const value = result.value as typeof input
expect(value.blocks.block1.subBlocks.credential.value).toBe('')
expect(value.blocks.block2.subBlocks.other.value).toBe('unrelated')
})
it('returns same reference when no changes are made', () => {
const input = {
blocks: {
block1: {
subBlocks: { credential: { id: 'credential', value: OTHER } },
},
},
}
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(false)
expect(result.value).toBe(input)
})
it('does not match outer "credential" key whose value is an object wrapper', () => {
const input = { credential: { id: 'credential', value: TARGET } }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
const value = result.value as { credential: { id: string; value: string } }
expect(value.credential).toEqual({ id: 'credential', value: '' })
})
it('clears params.credential string directly even when not nested in tools', () => {
const input = { params: { credential: TARGET, channel: '#x' } }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
expect((result.value as typeof input).params).toEqual({ credential: '', channel: '#x' })
})
it('does not match "credential" key when value is a different string', () => {
const input = { credential: 'cred_unrelated' }
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(false)
expect(result.value).toBe(input)
})
it('handles primitives and null', () => {
expect(clearCredentialInValue(null, TARGET)).toEqual({ value: null, changed: false })
expect(clearCredentialInValue('string', TARGET)).toEqual({ value: 'string', changed: false })
expect(clearCredentialInValue(42, TARGET)).toEqual({ value: 42, changed: false })
})
it('clears multiple references in a single pass', () => {
const input = {
blocks: {
a: { subBlocks: { credential: { id: 'credential', value: TARGET } } },
b: { subBlocks: { triggerCredentials: { id: 'triggerCredentials', value: TARGET } } },
c: {
subBlocks: {
tools: {
id: 'tools',
value: [{ params: { credential: TARGET } }, { params: { credential: TARGET } }],
},
},
},
},
}
const result = clearCredentialInValue(input, TARGET)
expect(result.changed).toBe(true)
const value = result.value as typeof input
expect(value.blocks.a.subBlocks.credential.value).toBe('')
expect(value.blocks.b.subBlocks.triggerCredentials.value).toBe('')
expect(value.blocks.c.subBlocks.tools.value[0].params.credential).toBe('')
expect(value.blocks.c.subBlocks.tools.value[1].params.credential).toBe('')
})
})