diff --git a/apps/web/app/(admin)/(authenticated)/resources/ResourcesPage.tsx b/apps/web/app/(admin)/(authenticated)/resources/ResourcesPage.tsx
index 35ab0589..65c8ee86 100644
--- a/apps/web/app/(admin)/(authenticated)/resources/ResourcesPage.tsx
+++ b/apps/web/app/(admin)/(authenticated)/resources/ResourcesPage.tsx
@@ -5,7 +5,9 @@ import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
+import {env} from '@usevenice/app-config/env'
import {clientIntegrations} from '@usevenice/app-config/integrations/integrations.client'
+import {defIntegrations} from '@usevenice/app-config/integrations/integrations.def'
import {extractProviderName, zRaw} from '@usevenice/cdk-core'
import type {RouterOutput} from '@usevenice/engine-backend'
import {_trpcReact, VeniceConnectButton} from '@usevenice/engine-frontend'
@@ -54,7 +56,11 @@ export default function ResourcesPage() {
Resources
-
+
Resources are created based on integration configurations
+ return (
+
+ )
}
diff --git a/packages/cdk-core/integration.types.ts b/packages/cdk-core/integration.types.ts
index 3aa2b461..8f46148f 100644
--- a/packages/cdk-core/integration.types.ts
+++ b/packages/cdk-core/integration.types.ts
@@ -1,7 +1,7 @@
import type {MaybePromise, z} from '@usevenice/util'
import {R} from '@usevenice/util'
-import type {EndUserId} from './id.types'
+import type {EndUserId, Id} from './id.types'
import {makeId} from './id.types'
import type {ZStandard} from './meta.types'
import type {
@@ -100,7 +100,10 @@ export interface IntegrationClient<
openDialog: OpenDialogFn
}) => (
connectInput: T['_types']['connectInput'],
- context: ConnectOptions,
+ context: ConnectOptions & {
+ // TODO: Does this belong here?
+ integrationId: Id['int']
+ },
) => Promise
}
diff --git a/packages/cdk-core/nango.ts b/packages/cdk-core/nango.ts
index dd198975..74454f56 100644
--- a/packages/cdk-core/nango.ts
+++ b/packages/cdk-core/nango.ts
@@ -154,7 +154,9 @@ export const zIntegration = zIntegrationShort.extend({
client_secret: z.string(),
scopes: z.string(),
app_link: z.string().nullish(),
- auth_mode: z.enum(['OAUTH2', 'OAUTH1', 'BASIC']),
+ // In practice we only use nango for oauth integrations
+ // but in theory we could use it for a generic secret store as well
+ auth_mode: z.enum(['OAUTH2', 'OAUTH1', 'BASIC', 'API_KEY']),
})
export const zUpsertIntegration = zIntegration
diff --git a/packages/cdk-core/providers.types.ts b/packages/cdk-core/providers.types.ts
index 350afe17..d768d55c 100644
--- a/packages/cdk-core/providers.types.ts
+++ b/packages/cdk-core/providers.types.ts
@@ -7,7 +7,7 @@ import {
zodToJsonSchema,
} from '@usevenice/util'
-import type {EndUserId, ExtEndUserId, ExternalId} from './id.types'
+import type {EndUserId, ExtEndUserId, ExternalId, Id} from './id.types'
import {zExternalId} from './id.types'
import type {
AnyIntegrationImpl,
@@ -102,7 +102,10 @@ export type UseConnectHook = (scope: {
openDialog: OpenDialogFn
}) => (
connectInput: T['_types']['connectInput'],
- context: ConnectOptions,
+ context: ConnectOptions & {
+ // TODO: Does this belong here?
+ integrationId: Id['int']
+ },
) => Promise
// MARK: - Server side connect types
diff --git a/packages/engine-frontend/VeniceConnect.tsx b/packages/engine-frontend/VeniceConnect.tsx
index a80e9ebb..48b5042b 100644
--- a/packages/engine-frontend/VeniceConnect.tsx
+++ b/packages/engine-frontend/VeniceConnect.tsx
@@ -1,5 +1,6 @@
'use client'
+import Nango from '@nangohq/frontend'
import {useMutation} from '@tanstack/react-query'
import {Link2, Loader2, RefreshCw, Trash2} from 'lucide-react'
import React from 'react'
@@ -7,6 +8,7 @@ import React from 'react'
import type {
Id,
IntegrationClient,
+ IntegrationDef,
OpenDialogFn,
UseConnectHook,
} from '@usevenice/cdk-core'
@@ -47,9 +49,12 @@ import {_trpcReact} from './TRPCProvider'
type ConnectEventType = 'open' | 'close' | 'error'
export interface VeniceConnectProps extends UIPropsNoChildren {
+ /** Does this belong here? */
+ nangoPublicKey: string
/** Whether to display the existing connections */
showExisting?: boolean
clientIntegrations: Record
+ defIntegrations: Record
onEvent?: (event: {type: ConnectEventType; intId: Id['int']}) => void
}
@@ -132,15 +137,22 @@ type ProviderMeta = Catalog[string]
export function _VeniceConnect({
catalog,
clientIntegrations,
+ defIntegrations,
onEvent,
showExisting,
className,
integrationIds,
+ nangoPublicKey,
...uiProps
}: VeniceConnectProps & {
integrationIds: Array
catalog: Catalog
}) {
+ const nango = React.useMemo(
+ () => new Nango({publicKey: nangoPublicKey}),
+ [nangoPublicKey],
+ )
+
// VeniceConnect should be fetching its own integrationIds as well as resources
// this way it can esure those are refreshed as operations take place
// This is esp true when we are operating in client envs (js embed)
@@ -194,10 +206,21 @@ export function _VeniceConnect({
integrationIds,
R.map(extractProviderName),
R.uniq,
- R.mapToObj((name: string) => [
- name,
- clientIntegrations[name]?.useConnectHook?.({openDialog}),
- ]),
+ R.mapToObj((name: string) => {
+ let fn = clientIntegrations[name]?.useConnectHook?.({openDialog})
+ const nangoProvider = defIntegrations[name]?.metadata?.nangoProvider
+ if (!fn && nangoProvider) {
+ console.log('adding nnango provider for', nangoProvider)
+
+ fn = async (_, {integrationId}) => {
+ console.log('inputs', integrationId)
+ await nango.auth(integrationId, 'conn_test').then((r) => {
+ console.log('auth', r)
+ })
+ }
+ }
+ return [name, fn]
+ }),
)
const categories = zIntegrationCategory.options
@@ -359,7 +382,7 @@ export const WithProviderConnect = ({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const connOutput = connectFn
- ? await connectFn?.(connInput, {})
+ ? await connectFn?.(connInput, {integrationId: int.id})
: connInput
console.log(`[VeniceConnect] ${int.id} connOutput`, connOutput)
diff --git a/packages/engine-frontend/package.json b/packages/engine-frontend/package.json
index 6b5f84a0..2e522986 100644
--- a/packages/engine-frontend/package.json
+++ b/packages/engine-frontend/package.json
@@ -5,6 +5,7 @@
"sideEffects": false,
"module": "./index.ts",
"dependencies": {
+ "@nangohq/frontend": "0.33.8",
"@tanstack/react-query": "*",
"@trpc/client": "10.21.1",
"@trpc/react-query": "10.21.1",
diff --git a/packages/util/zod-jsonschema-utils.ts b/packages/util/zod-jsonschema-utils.ts
index ac2b7afd..6d451502 100644
--- a/packages/util/zod-jsonschema-utils.ts
+++ b/packages/util/zod-jsonschema-utils.ts
@@ -15,7 +15,7 @@ export function defaultTitleAsJsonPath(jsonSchema: T) {
.filter((n) => !!n) // Filter out nesting from things like anyOf
.join('.')
- if (node.title) {
+ if (node.title && jsonPath) {
// @see https://share.cleanshot.com/16sDgL6D
node.title = `${jsonPath}: ${node.title}`
} else if (jsonPath && !jsonPath.endsWith('.')) {
diff --git a/packages/util/zod-jsonschema.spec.ts b/packages/util/zod-jsonschema.spec.ts
index 019b6acd..2c2c0d81 100644
--- a/packages/util/zod-jsonschema.spec.ts
+++ b/packages/util/zod-jsonschema.spec.ts
@@ -140,11 +140,11 @@ test('enum description to title 2', () => {
"clientId",
"clientSecret",
],
- "title": "Enable",
+ "title": "oauth: Enable",
"type": "object",
},
{
- "title": "Disable",
+ "title": "oauth: Disable",
"type": "null",
},
],
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ae454471..fdeb4230 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1316,6 +1316,9 @@ importers:
packages/engine-frontend:
dependencies:
+ '@nangohq/frontend':
+ specifier: 0.33.8
+ version: 0.33.8
'@tanstack/react-query':
specifier: 4.28.0
version: 4.28.0(react-dom@18.2.0)(react@18.2.0)
@@ -3880,6 +3883,10 @@ packages:
engines: {node: '>=12'}
dev: false
+ /@nangohq/frontend@0.33.8:
+ resolution: {integrity: sha512-iKTo4BDEXaKG6FbZzT9iACr07lGDBhmaS90+tsd92XrFpO8Gk7JGMp13lUS66mfwTcCXqPBXFVSkBvE0QyJi8Q==}
+ dev: false
+
/@next/env@13.4.3:
resolution: {integrity: sha512-pa1ErjyFensznttAk3EIv77vFbfSYT6cLzVRK5jx4uiRuCQo+m2wCFAREaHKIy63dlgvOyMlzh6R8Inu8H3KrQ==}
dev: false