mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
fix(integrations): resolve OAuth connect UI by service id instead of display name (#5001)
* fix(integrations): resolve OAuth connect UI by service id instead of display name * test(integrations): pin OAuth service resolution for all catalog integrations; fix credential branding reverse lookup * fix(docs-gen): blank string literals and comments before brace scanning in extractOAuthServiceId
This commit is contained in:
@@ -222,6 +222,7 @@ interface IntegrationEntry {
|
||||
triggers: TriggerInfo[]
|
||||
triggerCount: number
|
||||
authType: 'oauth' | 'api-key' | 'none'
|
||||
oauthServiceId?: string
|
||||
category: BlockCategory
|
||||
integrationType: IntegrationType
|
||||
tags?: string[]
|
||||
@@ -570,6 +571,52 @@ function extractAuthType(blockContent: string): 'oauth' | 'api-key' | 'none' {
|
||||
return 'none'
|
||||
}
|
||||
|
||||
/**
|
||||
* Length-preserving copy of `content` with string-literal and comment
|
||||
* interiors blanked out, so delimiter scans cannot be tripped by braces or
|
||||
* quotes inside them. Indices into the result line up with indices into
|
||||
* `content`.
|
||||
*/
|
||||
function blankStringsAndComments(content: string): string {
|
||||
return content.replace(
|
||||
/(['"`])(?:\\[\s\S]|(?!\1)[^\\])*\1|\/\/[^\n]*|\/\*[\s\S]*?\*\//g,
|
||||
(match) => match[0] + match.slice(1, -1).replace(/[^\n]/g, ' ') + match[match.length - 1]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the OAuth service id from the block's `oauth-input` credential
|
||||
* subBlock. Scoped to that subBlock's object literal so `serviceId` fields on
|
||||
* other subBlocks (e.g. file selectors) are never picked up. Brace matching
|
||||
* runs on a blanked copy of the content so string literals and comments
|
||||
* containing braces cannot skew it.
|
||||
*/
|
||||
function extractOAuthServiceId(blockContent: string): string | undefined {
|
||||
const typeMatch = /type\s*:\s*['"]oauth-input['"]/.exec(blockContent)
|
||||
if (!typeMatch) return undefined
|
||||
|
||||
const scannable = blankStringsAndComments(blockContent)
|
||||
let depth = 0
|
||||
let objectStart = -1
|
||||
for (let i = typeMatch.index; i >= 0; i--) {
|
||||
const char = scannable[i]
|
||||
if (char === '}') depth++
|
||||
else if (char === '{') {
|
||||
if (depth === 0) {
|
||||
objectStart = i
|
||||
break
|
||||
}
|
||||
depth--
|
||||
}
|
||||
}
|
||||
if (objectStart === -1) return undefined
|
||||
|
||||
const objectEnd = findMatchingClose(scannable, objectStart)
|
||||
if (objectEnd === -1) return undefined
|
||||
const subBlockContent = blockContent.substring(objectStart, objectEnd)
|
||||
return /serviceId\s*:\s*['"]([^'"]+)['"]/.exec(subBlockContent)?.[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the list of trigger IDs from the block's `triggers.available` array.
|
||||
* Handles blocks that declare `triggers: { enabled: true, available: [...] }`.
|
||||
@@ -820,6 +867,16 @@ async function writeIntegrationsJson(iconMapping: Record<string, string>): Promi
|
||||
.replace(/^-|-$/g, '')
|
||||
|
||||
const authType = extractAuthType(fileContent)
|
||||
const oauthServiceId = authType === 'oauth' ? extractOAuthServiceId(fileContent) : undefined
|
||||
// OAuth integrations resolve their connect UI through the service id
|
||||
// (see `resolveOAuthServiceForIntegration`), so fail loudly rather than
|
||||
// shipping a catalog entry that silently falls back to the API-key path.
|
||||
if (authType === 'oauth' && !oauthServiceId) {
|
||||
throw new Error(
|
||||
`Block "${blockType}" is an OAuth integration but no \`serviceId\` could be ` +
|
||||
`extracted from its \`oauth-input\` subBlock.`
|
||||
)
|
||||
}
|
||||
|
||||
integrations.push({
|
||||
type: blockType,
|
||||
@@ -835,6 +892,7 @@ async function writeIntegrationsJson(iconMapping: Record<string, string>): Promi
|
||||
triggers,
|
||||
triggerCount: triggers.length,
|
||||
authType,
|
||||
...(oauthServiceId ? { oauthServiceId } : {}),
|
||||
category: 'tools',
|
||||
integrationType,
|
||||
...(config.tags ? { tags: config.tags } : {}),
|
||||
|
||||
Reference in New Issue
Block a user