Skip to content

Commit fa81c4c

Browse files
committed
Fix refresh connection not working, address feedback
1 parent 298bc24 commit fa81c4c

File tree

12 files changed

+139
-147
lines changed

12 files changed

+139
-147
lines changed

apps/web/public/_assets/logo-greenhouse2.svg

Lines changed: 10 additions & 0 deletions
Loading

connectors/all-connectors/connectors.meta.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -728,9 +728,7 @@ export default {
728728
displayName: 'Greenhouse 2',
729729
stage: 'alpha',
730730
verticals: ['ats'],
731-
// TODO: Review why this is not working, asset exists in _assets folder
732-
// Is this used? connector is trying to get _assets/logo-greenhouse2.svg
733-
logoUrl: '/_assets/logo-greenhouse.svg',
731+
logoUrl: '/_assets/logo-greenhouse2.svg',
734732
authType: 'API_KEY',
735733
},
736734
},
Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type {ConnectorDef} from '@openint/cdk'
12
import type {Z} from '@openint/util/zod-utils'
23
import type {JsonConnectorDef} from '../schema'
34

@@ -9,51 +10,59 @@ export function createApiKeyConnectorDef<
910
T extends JsonConnectorDef,
1011
>(name: N, def: T) {
1112
const connectorConfig = () => {
12-
let schema = apiKeySchemas.connector_config
13+
let schema = apiKeySchemas.connector_config.unwrap().unwrap()
1314
if (Object.keys(def.auth?.connector_config ?? {}).length > 0) {
1415
// TODO: test this merge with other api key connectors
1516
schema = z.object({
1617
...schema.shape,
17-
...(def.auth.connector_config.shape as Record<string, Z.ZodTypeAny>),
18+
...(def?.auth?.connector_config?.shape as Record<string, Z.ZodTypeAny>),
1819
})
1920
}
2021

2122
return z.object({
22-
...(def.auth.connector_config?.shape as Record<string, Z.ZodTypeAny>),
23+
...(def?.auth?.connector_config?.shape as Record<string, Z.ZodTypeAny>),
2324
})
2425
}
2526

2627
const connectionSettings = () => {
2728
const schema = apiKeySchemas.connection_settings
28-
if (def.auth.connection_settings) {
29+
if (schema) {
2930
return z
3031
.object({
31-
...(def.auth.connection_settings.shape as Record<
32+
...schema.shape,
33+
...(def.auth.connection_settings?.shape as Record<
3234
string,
3335
Z.ZodTypeAny
3436
>),
3537
})
3638
.openapi({effectType: 'input'})
3739
}
38-
return schema
40+
return z
41+
.object({
42+
...(def.auth.connection_settings?.shape as Record<
43+
string,
44+
Z.ZodTypeAny
45+
>),
46+
})
47+
.openapi({effectType: 'input'})
3948
}
4049

4150
return {
4251
name,
4352
schemas: {
4453
...apiKeySchemas,
4554
name: z.literal(name),
46-
connector_config: connectorConfig(),
47-
connection_settings: connectionSettings(),
55+
connector_config: connectorConfig() as any,
56+
connection_settings: connectionSettings() as any,
4857
},
4958
metadata: {
5059
displayName: def.display_name,
5160
stage: def.stage,
5261
verticals: def.verticals,
5362
// TODO: We should get this from the connector def/meta
5463
logoUrl: `/_assets/logo-${name}.svg`,
55-
authType: def.auth.type,
64+
authType: def?.auth?.type,
5665
jsonDef: def,
5766
},
58-
}
67+
} satisfies ConnectorDef<typeof apiKeySchemas & {name: Z.ZodLiteral<N>}>
5968
}
Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,68 @@
11
import type {ConnectorDef, ConnectorServer} from '@openint/cdk'
22
import type {Z} from '@openint/util/zod-utils'
3-
import type {apiKeySchemas, zApiKeyConfig} from './schemas'
4-
5-
import {getClient} from './utils'
3+
import type {apiKeySchemas} from './schemas'
64

75
export function createAPIKeyConnectorServer<
86
TName extends string,
97
T extends typeof apiKeySchemas & {name: Z.ZodLiteral<TName>},
10-
>(
11-
connectorDef: ConnectorDef<T>,
12-
oauthConfigTemplate: Z.infer<typeof zApiKeyConfig>,
13-
): ConnectorServer<T, ReturnType<typeof getClient>> {
8+
>(connectorDef: ConnectorDef<T>): ConnectorServer<T> {
149
if (connectorDef.metadata?.authType !== 'API_KEY') {
1510
throw new Error('This server can only be used with API Key connectors')
1611
}
1712

1813
const baseServer = {
19-
newInstance: ({config, settings, context}) => {
20-
return getClient({
21-
connectorName: connectorDef.name,
22-
oauthConfigTemplate,
23-
connectorConfig: config,
24-
connectionSettings: settings,
25-
fetch: context.fetch,
26-
baseURLs: context.baseURLs,
27-
})
28-
},
14+
async checkConnection({settings}) {
15+
const auth = connectorDef.metadata?.jsonDef?.auth
16+
17+
if (!auth || auth.type !== 'API_KEY') {
18+
throw new Error('Invalid connector definition')
19+
}
20+
21+
const url = `${auth?.base_url}${auth?.verification.endpoint}`
22+
23+
const apiKey = settings?.api_key
24+
if (!apiKey) {
25+
throw new Error('Credentials are not configured')
26+
}
27+
28+
// Handle Basic auth by base64 encoding the API key
29+
const authHeader =
30+
auth?.verification.header_mode === 'Basic'
31+
? `Basic ${Buffer.from(`${apiKey}:`).toString('base64').trim()}`
32+
: `${auth?.verification.header_mode} ${apiKey}`
2933

30-
// TODO: Review why we get a type error here but this param works fine
31-
// in the oauth2 connector
32-
async checkConnection({instance}) {
33-
const {client} = instance
3434
try {
35-
await client.GET('/v1/jobs')
36-
return {status: 'healthy'}
37-
} catch (err) {
38-
console.warn('Greenhouse checkConnection error', err)
35+
const response = await fetch(url, {
36+
method: auth?.verification.method,
37+
headers: {
38+
Authorization: authHeader,
39+
},
40+
})
41+
42+
if (!response.ok) {
43+
const errorText = await response
44+
.text()
45+
.catch(() => 'No error details available')
46+
throw new Error(
47+
`Connection check failed with status ${response.status} (${response.statusText}): ${errorText}`,
48+
)
49+
}
50+
51+
return {
52+
status: 'healthy',
53+
status_message: null,
54+
settings,
55+
}
56+
} catch (error) {
3957
return {
4058
status: 'disconnected',
41-
status_message: `Failed to connect to Greenhouse: ${err}`,
59+
status_message:
60+
error instanceof Error ? error.message : String(error),
61+
settings,
4262
}
4363
}
4464
},
45-
} satisfies ConnectorServer<T, ReturnType<typeof getClient>>
65+
} satisfies ConnectorServer<typeof apiKeySchemas & {name: T['name']}>
4666

47-
return baseServer as unknown as ConnectorServer<
48-
ConnectorDef<T>['schemas'],
49-
ReturnType<typeof getClient>
50-
>
67+
return baseServer as unknown as ConnectorServer<ConnectorDef<T>['schemas']>
5168
}

connectors/cnext/auth-apikey/def.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ export const zAPIKeyConnectorDef = z.object({
44
type: z
55
.literal('API_KEY')
66
.describe('The authentication type for API Key-based providers'),
7-
api_key_field: z
8-
.string()
9-
.describe('Field name where the API key should be passed'),
10-
api_key_location: z
11-
.enum(['header', 'query'])
12-
.describe(
13-
'Specifies whether the API key is passed in headers or query parameters',
14-
),
7+
base_url: z.string().url().describe('The base URL of the API'),
8+
verification: z.object({
9+
method: z
10+
.enum(['GET', 'POST'])
11+
.describe('The method to verify the API key'),
12+
header_mode: z
13+
.enum(['Basic', 'Bearer'])
14+
.describe('The header to verify the API key'),
15+
endpoint: z.string().describe('The endpoint to verify the API key'),
16+
}),
1517
connector_config: z
1618
.object({})
1719
.optional()
@@ -20,7 +22,6 @@ export const zAPIKeyConnectorDef = z.object({
2022
connection_settings: z
2123
.object({})
2224
.optional()
23-
.default({})
2425
.describe('Additional configuration for api key connection settings'),
2526
overrides: z
2627
.object({

connectors/cnext/auth-apikey/schemas.ts

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,17 @@ import {z} from '@openint/util/zod-utils'
55

66
const zApiKeyConnectorConfig = z
77
.object({})
8-
.describe('Base oauth configuration for api key connector')
8+
.describe('Base api key configuration for api key connector')
99

1010
const zApiKeyConnectionSettings = z.object({
11-
credentials: z
12-
.object({
13-
api_key: z.string(),
14-
})
15-
.optional()
16-
.describe('Output of the postConnect hook for oauth2 connectors'),
11+
api_key: z.string(),
1712
})
1813

1914
export type ApiKeyConnectorConfig = Z.infer<typeof zApiKeyConnectorConfig>
2015

2116
export const apiKeySchemas = {
22-
connector_config: z.object({
23-
oauth: zApiKeyConnectorConfig.nullish(),
24-
}),
25-
connection_settings: z
26-
.object({
27-
oauth: zApiKeyConnectionSettings,
28-
})
29-
.openapi({effectType: 'input'}),
17+
connector_config: zApiKeyConnectorConfig.nullish(),
18+
connection_settings: zApiKeyConnectionSettings.openapi({effectType: 'input'}),
3019
pre_connect_input: z.object({}),
3120
connect_input: z.object({}),
3221
connect_output: z.object({

connectors/cnext/auth-apikey/utils.ts

Lines changed: 0 additions & 41 deletions
This file was deleted.

connectors/cnext/auth-oauth2/createOAuth2ConnectorDef.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function createOAuth2ConnectorDef<
2222
// TODO: does this need to do a deep merge of connectorConfig.oauth keys?
2323
schema = z.object({
2424
...schema.shape,
25-
...(def.auth.connector_config.shape as Record<string, Z.ZodTypeAny>),
25+
...(def.auth?.connector_config?.shape as Record<string, Z.ZodTypeAny>),
2626
})
2727
}
2828

@@ -33,8 +33,9 @@ export function createOAuth2ConnectorDef<
3333
if (defaultCredentialsConfigured) {
3434
// Only use default_scopes if they exist, otherwise use an empty array
3535
const openintDefaultCredentialsScopes =
36-
def.auth.type === 'OAUTH2'
37-
? (def.auth.openint_allowed_scopes ?? def.auth.openint_default_scopes)
36+
def.auth?.type === 'OAUTH2'
37+
? (def.auth?.openint_allowed_scopes ??
38+
def.auth?.openint_default_scopes)
3839
: []
3940
const zOpenIntDefaultScopes = z.array(
4041
z.enum(openintDefaultCredentialsScopes as [string, ...string[]]),
@@ -70,18 +71,18 @@ export function createOAuth2ConnectorDef<
7071
return z.object({
7172
oauth: schema.shape.oauth,
7273
// make sure to merge in any additional connector config fields
73-
...(def.auth.connector_config?.shape as Record<string, Z.ZodTypeAny>),
74+
...(def.auth?.connector_config?.shape as Record<string, Z.ZodTypeAny>),
7475
})
7576
}
7677

7778
const connectionSettings = () => {
7879
const schema = oauth2Schemas.connection_settings
79-
if (def.auth.connection_settings) {
80+
if (def.auth?.connection_settings) {
8081
return (
8182
z
8283
.object({
8384
...schema.innerType().shape,
84-
...(def.auth.connection_settings.shape as Record<
85+
...(def.auth?.connection_settings?.shape as Record<
8586
string,
8687
Z.ZodTypeAny
8788
>),
@@ -112,7 +113,7 @@ export function createOAuth2ConnectorDef<
112113
stage: def.stage,
113114
verticals: def.verticals,
114115
logoUrl: `/_assets/logo-${name}.svg`,
115-
authType: def.auth.type,
116+
authType: def.auth?.type,
116117
jsonDef: def,
117118
},
118119
} satisfies ConnectorDef<typeof oauth2Schemas & {name: Z.ZodLiteral<N>}>

connectors/cnext/connectors.def.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const getConnectorDefFnByAuthMode = (
1414
case 'API_KEY':
1515
return createApiKeyConnectorDef
1616
default:
17-
return createOAuth2ConnectorDef
17+
throw new Error('Unsupported connector auth type')
1818
}
1919
}
2020

0 commit comments

Comments
 (0)