@elevasis/core 0.23.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4343 -2690
- package/dist/index.js +1101 -156
- package/dist/knowledge/index.d.ts +574 -210
- package/dist/knowledge/index.js +104 -1
- package/dist/organization-model/index.d.ts +4343 -2690
- package/dist/organization-model/index.js +1101 -156
- package/dist/test-utils/index.d.ts +483 -109
- package/dist/test-utils/index.js +904 -144
- package/package.json +3 -3
- package/src/README.md +14 -14
- package/src/__tests__/publish.test.ts +24 -24
- package/src/__tests__/template-core-compatibility.test.ts +9 -12
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2137 -2093
- package/src/_gen/__tests__/scaffold-contracts.test.ts +30 -30
- package/src/auth/multi-tenancy/credentials/__tests__/encryption.test.ts +217 -217
- package/src/auth/multi-tenancy/credentials/server/encryption.ts +69 -69
- package/src/auth/multi-tenancy/credentials/server/kek-loader.ts +37 -37
- package/src/auth/multi-tenancy/index.ts +26 -26
- package/src/auth/multi-tenancy/invitations/api-schemas.ts +104 -104
- package/src/auth/multi-tenancy/memberships/api-schemas.ts +143 -143
- package/src/auth/multi-tenancy/memberships/index.ts +26 -26
- package/src/auth/multi-tenancy/memberships/membership.ts +130 -130
- package/src/auth/multi-tenancy/organizations/__tests__/api-schemas.test.ts +194 -194
- package/src/auth/multi-tenancy/organizations/api-schemas.ts +136 -136
- package/src/auth/multi-tenancy/permissions.test.ts +42 -42
- package/src/auth/multi-tenancy/permissions.ts +123 -123
- package/src/auth/multi-tenancy/role-management/api-schemas.ts +78 -78
- package/src/auth/multi-tenancy/role-management/index.ts +16 -16
- package/src/auth/multi-tenancy/theme-presets.ts +45 -45
- package/src/auth/multi-tenancy/types.ts +57 -57
- package/src/auth/multi-tenancy/users/api-schemas.ts +165 -165
- package/src/business/README.md +2 -2
- package/src/business/acquisition/activity-events.test.ts +250 -250
- package/src/business/acquisition/activity-events.ts +93 -93
- package/src/business/acquisition/api-schemas.test.ts +1883 -1843
- package/src/business/acquisition/api-schemas.ts +1492 -1497
- package/src/business/acquisition/build-templates.test.ts +240 -240
- package/src/business/acquisition/build-templates.ts +98 -98
- package/src/business/acquisition/crm-next-action.test.ts +262 -262
- package/src/business/acquisition/crm-next-action.ts +220 -220
- package/src/business/acquisition/crm-priority.test.ts +216 -216
- package/src/business/acquisition/crm-priority.ts +349 -349
- package/src/business/acquisition/crm-state-actions.test.ts +153 -153
- package/src/business/acquisition/deal-ownership.test.ts +351 -351
- package/src/business/acquisition/deal-ownership.ts +120 -120
- package/src/business/acquisition/derive-actions.test.ts +129 -104
- package/src/business/acquisition/derive-actions.ts +74 -84
- package/src/business/acquisition/index.ts +171 -170
- package/src/business/acquisition/ontology-validation.ts +309 -0
- package/src/business/acquisition/stateful.ts +30 -30
- package/src/business/acquisition/types.ts +396 -396
- package/src/business/clients/api-schemas.test.ts +115 -115
- package/src/business/clients/api-schemas.ts +158 -158
- package/src/business/clients/index.ts +1 -1
- package/src/business/crm/api-schemas.ts +40 -40
- package/src/business/crm/index.ts +1 -1
- package/src/business/deals/api-schemas.ts +87 -87
- package/src/business/deals/index.ts +1 -1
- package/src/business/index.ts +5 -5
- package/src/business/projects/types.ts +144 -144
- package/src/commands/queue/types/task.ts +15 -15
- package/src/execution/core/runner-types.ts +61 -61
- package/src/execution/core/sse-executions.ts +7 -7
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -10
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -16
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -4
- package/src/execution/engine/agent/core/types.ts +25 -25
- package/src/execution/engine/agent/index.ts +6 -6
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -24
- package/src/execution/engine/index.ts +443 -443
- package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +298 -298
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -55
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -107
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -48
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -99
- package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -1
- package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +363 -363
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.test.ts +162 -162
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.test.ts +316 -316
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -18
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -194
- package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -7
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +204 -204
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +105 -105
- package/src/execution/engine/tools/integration/server/adapters/google-calendar/google-calendar-adapter.ts +428 -428
- package/src/execution/engine/tools/integration/server/adapters/google-calendar/index.ts +2 -2
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -261
- package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1474 -1474
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +103 -103
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.test.ts +88 -88
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +141 -141
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +76 -76
- package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-tools.ts +182 -182
- package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +310 -310
- package/src/execution/engine/tools/integration/service.test.ts +239 -239
- package/src/execution/engine/tools/integration/service.ts +172 -172
- package/src/execution/engine/tools/integration/tool.ts +255 -255
- package/src/execution/engine/tools/lead-service-types.ts +1005 -1005
- package/src/execution/engine/tools/messages.ts +43 -43
- package/src/execution/engine/tools/platform/acquisition/company-tools.ts +7 -7
- package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +6 -6
- package/src/execution/engine/tools/platform/acquisition/list-tools.ts +6 -6
- package/src/execution/engine/tools/platform/acquisition/types.ts +280 -280
- package/src/execution/engine/tools/platform/email/types.ts +97 -97
- package/src/execution/engine/tools/registry.ts +704 -704
- package/src/execution/engine/tools/tool-maps.ts +831 -831
- package/src/execution/engine/tools/types.ts +234 -234
- package/src/execution/engine/workflow/types.ts +195 -197
- package/src/execution/external/__tests__/api-schemas.test.ts +127 -127
- package/src/execution/external/api-schemas.ts +40 -40
- package/src/execution/external/index.ts +1 -1
- package/src/index.ts +18 -18
- package/src/integrations/credentials/__tests__/api-schemas.test.ts +420 -420
- package/src/integrations/credentials/api-schemas.ts +146 -146
- package/src/integrations/credentials/schemas.ts +200 -200
- package/src/integrations/oauth/__tests__/provider-registry.test.ts +7 -7
- package/src/integrations/oauth/provider-registry.ts +74 -74
- package/src/integrations/oauth/server/credentials.ts +43 -43
- package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +327 -327
- package/src/integrations/webhook-endpoints/api-schemas.ts +103 -103
- package/src/integrations/webhook-endpoints/types.ts +58 -58
- package/src/knowledge/README.md +32 -32
- package/src/knowledge/__tests__/queries.test.ts +626 -535
- package/src/knowledge/format.ts +99 -99
- package/src/knowledge/index.ts +5 -5
- package/src/knowledge/published.ts +5 -5
- package/src/knowledge/queries.ts +269 -218
- package/src/operations/activities/api-schemas.ts +80 -80
- package/src/operations/activities/types.ts +64 -64
- package/src/organization-model/README.md +149 -149
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -210
- package/src/organization-model/__tests__/defaults.test.ts +168 -168
- package/src/organization-model/__tests__/domains/actions.test.ts +78 -56
- package/src/organization-model/__tests__/domains/customers.test.ts +299 -299
- package/src/organization-model/__tests__/domains/entities.test.ts +56 -56
- package/src/organization-model/__tests__/domains/goals.test.ts +493 -493
- package/src/organization-model/__tests__/domains/identity.test.ts +280 -280
- package/src/organization-model/__tests__/domains/navigation.test.ts +268 -268
- package/src/organization-model/__tests__/domains/offerings.test.ts +414 -414
- package/src/organization-model/__tests__/domains/policies.test.ts +323 -323
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +293 -293
- package/src/organization-model/__tests__/domains/resources.test.ts +387 -277
- package/src/organization-model/__tests__/domains/roles.test.ts +463 -463
- package/src/organization-model/__tests__/domains/statuses.test.ts +246 -246
- package/src/organization-model/__tests__/domains/systems.test.ts +209 -209
- package/src/organization-model/__tests__/domains/topology.test.ts +188 -0
- package/src/organization-model/__tests__/flatten-additive-merge.test.ts +362 -361
- package/src/organization-model/__tests__/foundation.test.ts +77 -77
- package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -144
- package/src/organization-model/__tests__/graph.test.ts +1312 -862
- package/src/organization-model/__tests__/icons.test.ts +10 -1
- package/src/organization-model/__tests__/knowledge.test.ts +251 -15
- package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -438
- package/src/organization-model/__tests__/migration-helpers.test.ts +591 -591
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +103 -103
- package/src/organization-model/__tests__/recursive-system-schema.test.ts +535 -506
- package/src/organization-model/__tests__/resolve.test.ts +274 -164
- package/src/organization-model/__tests__/schema.test.ts +844 -301
- package/src/organization-model/__tests__/surface-projection.test.ts +284 -284
- package/src/organization-model/catalogs/lead-gen.ts +144 -144
- package/src/organization-model/content-kinds/config.ts +36 -36
- package/src/organization-model/content-kinds/index.ts +76 -72
- package/src/organization-model/content-kinds/pipeline.ts +68 -68
- package/src/organization-model/content-kinds/registry.ts +44 -44
- package/src/organization-model/content-kinds/status.ts +71 -71
- package/src/organization-model/content-kinds/template.ts +83 -83
- package/src/organization-model/content-kinds/types.ts +117 -117
- package/src/organization-model/contracts.ts +27 -27
- package/src/organization-model/defaults.ts +42 -50
- package/src/organization-model/domains/actions.ts +333 -239
- package/src/organization-model/domains/customers.ts +78 -78
- package/src/organization-model/domains/entities.ts +144 -144
- package/src/organization-model/domains/goals.ts +83 -83
- package/src/organization-model/domains/knowledge.ts +117 -101
- package/src/organization-model/domains/navigation.ts +139 -139
- package/src/organization-model/domains/offerings.ts +71 -71
- package/src/organization-model/domains/policies.ts +102 -102
- package/src/organization-model/domains/projects.ts +14 -14
- package/src/organization-model/domains/prospecting.ts +395 -395
- package/src/organization-model/domains/resources.ts +202 -124
- package/src/organization-model/domains/roles.ts +96 -96
- package/src/organization-model/domains/sales.test.ts +218 -218
- package/src/organization-model/domains/sales.ts +380 -380
- package/src/organization-model/domains/shared.ts +63 -63
- package/src/organization-model/domains/statuses.ts +339 -339
- package/src/organization-model/domains/systems.ts +217 -172
- package/src/organization-model/domains/topology.ts +261 -0
- package/src/organization-model/foundation.ts +75 -75
- package/src/organization-model/graph/build.ts +1043 -867
- package/src/organization-model/graph/index.ts +4 -4
- package/src/organization-model/graph/link.ts +10 -10
- package/src/organization-model/graph/schema.ts +75 -68
- package/src/organization-model/graph/types.ts +71 -64
- package/src/organization-model/helpers.ts +289 -241
- package/src/organization-model/icons.ts +78 -66
- package/src/organization-model/index.ts +128 -125
- package/src/organization-model/migration-helpers.ts +247 -244
- package/src/organization-model/ontology.ts +658 -0
- package/src/organization-model/organization-graph.mdx +110 -90
- package/src/organization-model/organization-model.mdx +225 -213
- package/src/organization-model/published.ts +299 -222
- package/src/organization-model/resolve.ts +146 -91
- package/src/organization-model/schema.ts +818 -659
- package/src/organization-model/surface-projection.ts +212 -212
- package/src/organization-model/types.ts +179 -155
- package/src/platform/api/types.ts +38 -38
- package/src/platform/constants/versions.ts +3 -3
- package/src/platform/index.ts +23 -23
- package/src/platform/registry/__tests__/command-view.test.ts +10 -10
- package/src/platform/registry/__tests__/resource-link.test.ts +35 -35
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +20 -20
- package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -245
- package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2053
- package/src/platform/registry/__tests__/validation.test.ts +1444 -1259
- package/src/platform/registry/command-view.ts +10 -10
- package/src/platform/registry/index.ts +103 -103
- package/src/platform/registry/resource-link.ts +32 -32
- package/src/platform/registry/resource-registry.ts +886 -886
- package/src/platform/registry/serialization.ts +295 -295
- package/src/platform/registry/serialized-types.ts +166 -166
- package/src/platform/registry/stats-types.ts +68 -68
- package/src/platform/registry/types.ts +425 -425
- package/src/platform/registry/validation.ts +876 -684
- package/src/platform/utils/__tests__/validation.test.ts +1084 -1084
- package/src/platform/utils/validation.ts +425 -425
- package/src/projects/api-schemas.test.ts +39 -39
- package/src/projects/api-schemas.ts +291 -291
- package/src/reference/_generated/contracts.md +2136 -2093
- package/src/reference/glossary.md +76 -76
- package/src/scaffold-registry/__tests__/index.test.ts +206 -206
- package/src/scaffold-registry/__tests__/schema.test.ts +166 -166
- package/src/scaffold-registry/index.ts +392 -392
- package/src/scaffold-registry/schema.ts +243 -243
- package/src/server.ts +289 -289
- package/src/supabase/database.types.ts +3 -0
- package/src/test-utils/README.md +37 -37
- package/src/test-utils/entities.ts +108 -108
- package/src/test-utils/fixtures/memberships.ts +82 -82
- package/src/test-utils/index.ts +12 -12
- package/src/test-utils/organization-model.ts +65 -65
- package/src/test-utils/published.ts +6 -6
- package/src/test-utils/rls/RLSTestContext.ts +588 -588
- package/src/test-utils/test-utils.test.ts +44 -44
|
@@ -1,200 +1,200 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Credential field definition
|
|
5
|
-
*/
|
|
6
|
-
export interface CredentialField {
|
|
7
|
-
key: string
|
|
8
|
-
label: string
|
|
9
|
-
type: 'password' | 'text'
|
|
10
|
-
required: boolean
|
|
11
|
-
placeholder?: string
|
|
12
|
-
description?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Credential schema definition
|
|
17
|
-
*/
|
|
18
|
-
export interface CredentialSchema {
|
|
19
|
-
type: string
|
|
20
|
-
label: string
|
|
21
|
-
description: string
|
|
22
|
-
fields?: CredentialField[]
|
|
23
|
-
docsUrl?: string
|
|
24
|
-
nameSuggestions: string[]
|
|
25
|
-
oauthProvider?: string // For OAuth types
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Zod schemas for runtime validation
|
|
30
|
-
*/
|
|
31
|
-
const CredentialFieldSchema = z.object({
|
|
32
|
-
key: z.string(),
|
|
33
|
-
label: z.string(),
|
|
34
|
-
type: z.enum(['password', 'text']),
|
|
35
|
-
required: z.boolean(),
|
|
36
|
-
placeholder: z.string().optional(),
|
|
37
|
-
description: z.string().optional()
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
const CredentialSchemaZod = z.object({
|
|
41
|
-
type: z.string(),
|
|
42
|
-
label: z.string(),
|
|
43
|
-
description: z.string(),
|
|
44
|
-
fields: z.array(CredentialFieldSchema).optional(),
|
|
45
|
-
docsUrl: z.string().url().optional(),
|
|
46
|
-
nameSuggestions: z.array(z.string()),
|
|
47
|
-
oauthProvider: z.string().optional()
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Credential Schema Registry
|
|
52
|
-
*
|
|
53
|
-
* Add new integration = add schema object here (no modal changes needed)
|
|
54
|
-
*
|
|
55
|
-
* Schema types:
|
|
56
|
-
* - oauth: OAuth-based authentication (handled via OAuth flow)
|
|
57
|
-
* - single_field: Single API key field (generic)
|
|
58
|
-
*/
|
|
59
|
-
export const CREDENTIAL_SCHEMAS: Record<string, CredentialSchema> = {
|
|
60
|
-
'google-sheets': {
|
|
61
|
-
type: 'oauth',
|
|
62
|
-
label: 'Google Sheets',
|
|
63
|
-
description: 'Google Sheets OAuth integration',
|
|
64
|
-
oauthProvider: 'google-sheets',
|
|
65
|
-
nameSuggestions: ['google-sheets-prod', 'google-sheets-dev', 'sheets-workspace']
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
dropbox: {
|
|
69
|
-
type: 'oauth',
|
|
70
|
-
label: 'Dropbox',
|
|
71
|
-
description: 'Dropbox OAuth integration',
|
|
72
|
-
oauthProvider: 'dropbox',
|
|
73
|
-
nameSuggestions: ['dropbox-prod', 'dropbox-dev', 'elevasis-dropbox']
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
oauth: {
|
|
77
|
-
type: 'oauth',
|
|
78
|
-
label: 'OAuth',
|
|
79
|
-
description: 'Generic OAuth credential',
|
|
80
|
-
nameSuggestions: []
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
'api-key': {
|
|
84
|
-
type: 'single_field',
|
|
85
|
-
label: 'API Key',
|
|
86
|
-
description: 'Single-field API key credential',
|
|
87
|
-
fields: [
|
|
88
|
-
{
|
|
89
|
-
key: 'apiKey',
|
|
90
|
-
label: 'API Key',
|
|
91
|
-
type: 'password',
|
|
92
|
-
required: true,
|
|
93
|
-
placeholder: 'Enter your API key',
|
|
94
|
-
description: 'API key for the service'
|
|
95
|
-
}
|
|
96
|
-
],
|
|
97
|
-
nameSuggestions: ['service-prod', 'service-dev', 'api-key']
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
'webhook-secret': {
|
|
101
|
-
type: 'single_field',
|
|
102
|
-
label: 'Webhook Secret',
|
|
103
|
-
description: 'Webhook signing secret for signature validation',
|
|
104
|
-
fields: [
|
|
105
|
-
{
|
|
106
|
-
key: 'signingSecret',
|
|
107
|
-
label: 'Signing Secret',
|
|
108
|
-
type: 'password',
|
|
109
|
-
required: true,
|
|
110
|
-
placeholder: 'whsec_...',
|
|
111
|
-
description: 'Webhook signing secret from provider dashboard'
|
|
112
|
-
}
|
|
113
|
-
],
|
|
114
|
-
nameSuggestions: ['my-org-cal-com-webhook', 'my-org-stripe-webhook', 'my-org-signature-api-webhook']
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
'api-key-secret': {
|
|
118
|
-
type: 'api-key-secret',
|
|
119
|
-
label: 'API Key + Secret',
|
|
120
|
-
description: 'API key and secret pair authentication',
|
|
121
|
-
fields: [
|
|
122
|
-
{
|
|
123
|
-
key: 'apiKey',
|
|
124
|
-
label: 'API Key',
|
|
125
|
-
type: 'password',
|
|
126
|
-
required: true
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
key: 'apiSecret',
|
|
130
|
-
label: 'API Secret',
|
|
131
|
-
type: 'password',
|
|
132
|
-
required: true
|
|
133
|
-
}
|
|
134
|
-
],
|
|
135
|
-
nameSuggestions: []
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
apify: {
|
|
139
|
-
type: 'single_field',
|
|
140
|
-
label: 'Apify',
|
|
141
|
-
description: 'Apify API token for running web-scraping actors (e.g. website crawl, Google Places scrape).',
|
|
142
|
-
fields: [
|
|
143
|
-
{
|
|
144
|
-
key: 'apiKey',
|
|
145
|
-
label: 'API Token',
|
|
146
|
-
type: 'password',
|
|
147
|
-
required: true,
|
|
148
|
-
placeholder: 'apify_api_...',
|
|
149
|
-
description: 'Personal API token from https://console.apify.com/account/integrations'
|
|
150
|
-
}
|
|
151
|
-
],
|
|
152
|
-
docsUrl: 'https://docs.apify.com/platform/integrations/api',
|
|
153
|
-
nameSuggestions: ['elevasis-apify', 'apify-prod', 'apify-dev']
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
clickup: {
|
|
157
|
-
type: 'single_field',
|
|
158
|
-
label: 'ClickUp',
|
|
159
|
-
description: 'ClickUp personal API token for creating tasks in tenant-managed ClickUp workspaces.',
|
|
160
|
-
fields: [
|
|
161
|
-
{
|
|
162
|
-
key: 'apiToken',
|
|
163
|
-
label: 'API Token',
|
|
164
|
-
type: 'password',
|
|
165
|
-
required: true,
|
|
166
|
-
placeholder: 'pk_...',
|
|
167
|
-
description: 'Personal API token from ClickUp settings. Personal tokens start with pk_.'
|
|
168
|
-
}
|
|
169
|
-
],
|
|
170
|
-
docsUrl: 'https://developer.clickup.com/docs/authentication',
|
|
171
|
-
nameSuggestions: ['clickup-demo', 'clickup-prod', 'clickup-dev']
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Get credential schema by type
|
|
177
|
-
* @param type - Credential type identifier
|
|
178
|
-
* @returns Validated credential schema
|
|
179
|
-
* @throws ZodError if schema is malformed
|
|
180
|
-
*/
|
|
181
|
-
export function getCredentialSchema(type: string): CredentialSchema {
|
|
182
|
-
const schema = CREDENTIAL_SCHEMAS[type] || CREDENTIAL_SCHEMAS['api-key']
|
|
183
|
-
return CredentialSchemaZod.parse(schema)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* List all available credential types (for frontend dropdown)
|
|
188
|
-
* @returns Array of credential schemas
|
|
189
|
-
*/
|
|
190
|
-
export function listCredentialSchemas(): CredentialSchema[] {
|
|
191
|
-
return Object.values(CREDENTIAL_SCHEMAS)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Get all credential type identifiers
|
|
196
|
-
* @returns Array of type strings
|
|
197
|
-
*/
|
|
198
|
-
export function getCredentialTypes(): string[] {
|
|
199
|
-
return Object.keys(CREDENTIAL_SCHEMAS)
|
|
200
|
-
}
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Credential field definition
|
|
5
|
+
*/
|
|
6
|
+
export interface CredentialField {
|
|
7
|
+
key: string
|
|
8
|
+
label: string
|
|
9
|
+
type: 'password' | 'text'
|
|
10
|
+
required: boolean
|
|
11
|
+
placeholder?: string
|
|
12
|
+
description?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Credential schema definition
|
|
17
|
+
*/
|
|
18
|
+
export interface CredentialSchema {
|
|
19
|
+
type: string
|
|
20
|
+
label: string
|
|
21
|
+
description: string
|
|
22
|
+
fields?: CredentialField[]
|
|
23
|
+
docsUrl?: string
|
|
24
|
+
nameSuggestions: string[]
|
|
25
|
+
oauthProvider?: string // For OAuth types
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Zod schemas for runtime validation
|
|
30
|
+
*/
|
|
31
|
+
const CredentialFieldSchema = z.object({
|
|
32
|
+
key: z.string(),
|
|
33
|
+
label: z.string(),
|
|
34
|
+
type: z.enum(['password', 'text']),
|
|
35
|
+
required: z.boolean(),
|
|
36
|
+
placeholder: z.string().optional(),
|
|
37
|
+
description: z.string().optional()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const CredentialSchemaZod = z.object({
|
|
41
|
+
type: z.string(),
|
|
42
|
+
label: z.string(),
|
|
43
|
+
description: z.string(),
|
|
44
|
+
fields: z.array(CredentialFieldSchema).optional(),
|
|
45
|
+
docsUrl: z.string().url().optional(),
|
|
46
|
+
nameSuggestions: z.array(z.string()),
|
|
47
|
+
oauthProvider: z.string().optional()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Credential Schema Registry
|
|
52
|
+
*
|
|
53
|
+
* Add new integration = add schema object here (no modal changes needed)
|
|
54
|
+
*
|
|
55
|
+
* Schema types:
|
|
56
|
+
* - oauth: OAuth-based authentication (handled via OAuth flow)
|
|
57
|
+
* - single_field: Single API key field (generic)
|
|
58
|
+
*/
|
|
59
|
+
export const CREDENTIAL_SCHEMAS: Record<string, CredentialSchema> = {
|
|
60
|
+
'google-sheets': {
|
|
61
|
+
type: 'oauth',
|
|
62
|
+
label: 'Google Sheets',
|
|
63
|
+
description: 'Google Sheets OAuth integration',
|
|
64
|
+
oauthProvider: 'google-sheets',
|
|
65
|
+
nameSuggestions: ['google-sheets-prod', 'google-sheets-dev', 'sheets-workspace']
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
dropbox: {
|
|
69
|
+
type: 'oauth',
|
|
70
|
+
label: 'Dropbox',
|
|
71
|
+
description: 'Dropbox OAuth integration',
|
|
72
|
+
oauthProvider: 'dropbox',
|
|
73
|
+
nameSuggestions: ['dropbox-prod', 'dropbox-dev', 'elevasis-dropbox']
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
oauth: {
|
|
77
|
+
type: 'oauth',
|
|
78
|
+
label: 'OAuth',
|
|
79
|
+
description: 'Generic OAuth credential',
|
|
80
|
+
nameSuggestions: []
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
'api-key': {
|
|
84
|
+
type: 'single_field',
|
|
85
|
+
label: 'API Key',
|
|
86
|
+
description: 'Single-field API key credential',
|
|
87
|
+
fields: [
|
|
88
|
+
{
|
|
89
|
+
key: 'apiKey',
|
|
90
|
+
label: 'API Key',
|
|
91
|
+
type: 'password',
|
|
92
|
+
required: true,
|
|
93
|
+
placeholder: 'Enter your API key',
|
|
94
|
+
description: 'API key for the service'
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
nameSuggestions: ['service-prod', 'service-dev', 'api-key']
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
'webhook-secret': {
|
|
101
|
+
type: 'single_field',
|
|
102
|
+
label: 'Webhook Secret',
|
|
103
|
+
description: 'Webhook signing secret for signature validation',
|
|
104
|
+
fields: [
|
|
105
|
+
{
|
|
106
|
+
key: 'signingSecret',
|
|
107
|
+
label: 'Signing Secret',
|
|
108
|
+
type: 'password',
|
|
109
|
+
required: true,
|
|
110
|
+
placeholder: 'whsec_...',
|
|
111
|
+
description: 'Webhook signing secret from provider dashboard'
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
nameSuggestions: ['my-org-cal-com-webhook', 'my-org-stripe-webhook', 'my-org-signature-api-webhook']
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
'api-key-secret': {
|
|
118
|
+
type: 'api-key-secret',
|
|
119
|
+
label: 'API Key + Secret',
|
|
120
|
+
description: 'API key and secret pair authentication',
|
|
121
|
+
fields: [
|
|
122
|
+
{
|
|
123
|
+
key: 'apiKey',
|
|
124
|
+
label: 'API Key',
|
|
125
|
+
type: 'password',
|
|
126
|
+
required: true
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
key: 'apiSecret',
|
|
130
|
+
label: 'API Secret',
|
|
131
|
+
type: 'password',
|
|
132
|
+
required: true
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
nameSuggestions: []
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
apify: {
|
|
139
|
+
type: 'single_field',
|
|
140
|
+
label: 'Apify',
|
|
141
|
+
description: 'Apify API token for running web-scraping actors (e.g. website crawl, Google Places scrape).',
|
|
142
|
+
fields: [
|
|
143
|
+
{
|
|
144
|
+
key: 'apiKey',
|
|
145
|
+
label: 'API Token',
|
|
146
|
+
type: 'password',
|
|
147
|
+
required: true,
|
|
148
|
+
placeholder: 'apify_api_...',
|
|
149
|
+
description: 'Personal API token from https://console.apify.com/account/integrations'
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
docsUrl: 'https://docs.apify.com/platform/integrations/api',
|
|
153
|
+
nameSuggestions: ['elevasis-apify', 'apify-prod', 'apify-dev']
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
clickup: {
|
|
157
|
+
type: 'single_field',
|
|
158
|
+
label: 'ClickUp',
|
|
159
|
+
description: 'ClickUp personal API token for creating tasks in tenant-managed ClickUp workspaces.',
|
|
160
|
+
fields: [
|
|
161
|
+
{
|
|
162
|
+
key: 'apiToken',
|
|
163
|
+
label: 'API Token',
|
|
164
|
+
type: 'password',
|
|
165
|
+
required: true,
|
|
166
|
+
placeholder: 'pk_...',
|
|
167
|
+
description: 'Personal API token from ClickUp settings. Personal tokens start with pk_.'
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
docsUrl: 'https://developer.clickup.com/docs/authentication',
|
|
171
|
+
nameSuggestions: ['clickup-demo', 'clickup-prod', 'clickup-dev']
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get credential schema by type
|
|
177
|
+
* @param type - Credential type identifier
|
|
178
|
+
* @returns Validated credential schema
|
|
179
|
+
* @throws ZodError if schema is malformed
|
|
180
|
+
*/
|
|
181
|
+
export function getCredentialSchema(type: string): CredentialSchema {
|
|
182
|
+
const schema = CREDENTIAL_SCHEMAS[type] || CREDENTIAL_SCHEMAS['api-key']
|
|
183
|
+
return CredentialSchemaZod.parse(schema)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* List all available credential types (for frontend dropdown)
|
|
188
|
+
* @returns Array of credential schemas
|
|
189
|
+
*/
|
|
190
|
+
export function listCredentialSchemas(): CredentialSchema[] {
|
|
191
|
+
return Object.values(CREDENTIAL_SCHEMAS)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get all credential type identifiers
|
|
196
|
+
* @returns Array of type strings
|
|
197
|
+
*/
|
|
198
|
+
export function getCredentialTypes(): string[] {
|
|
199
|
+
return Object.keys(CREDENTIAL_SCHEMAS)
|
|
200
|
+
}
|
|
@@ -38,13 +38,13 @@ describe('OAuth Provider Registry', () => {
|
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
describe('listProviders', () => {
|
|
41
|
-
it('should return all providers as array', () => {
|
|
42
|
-
const providers = listProviders()
|
|
43
|
-
expect(providers).toHaveLength(Object.keys(OAUTH_PROVIDERS).length)
|
|
44
|
-
expect(providers).toContainEqual(OAUTH_PROVIDERS['google-sheets'])
|
|
45
|
-
expect(providers).toContainEqual(OAUTH_PROVIDERS['google-calendar'])
|
|
46
|
-
expect(providers).toContainEqual(OAUTH_PROVIDERS.dropbox)
|
|
47
|
-
})
|
|
41
|
+
it('should return all providers as array', () => {
|
|
42
|
+
const providers = listProviders()
|
|
43
|
+
expect(providers).toHaveLength(Object.keys(OAUTH_PROVIDERS).length)
|
|
44
|
+
expect(providers).toContainEqual(OAUTH_PROVIDERS['google-sheets'])
|
|
45
|
+
expect(providers).toContainEqual(OAUTH_PROVIDERS['google-calendar'])
|
|
46
|
+
expect(providers).toContainEqual(OAUTH_PROVIDERS.dropbox)
|
|
47
|
+
})
|
|
48
48
|
|
|
49
49
|
it('should return array with correct provider structure', () => {
|
|
50
50
|
const providers = listProviders()
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import type { OAuthProviderConfig } from './types'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* OAuth Provider Registry
|
|
5
|
-
*
|
|
6
|
-
* Add new integration = add config object here (no new code needed)
|
|
7
|
-
*
|
|
8
|
-
* Standard token exchange methods:
|
|
9
|
-
* - basic-auth: client_id:client_secret in Authorization header
|
|
10
|
-
* - form-encoded: credentials in URL-encoded body (Google)
|
|
11
|
-
* - json-body: credentials in JSON body (most providers)
|
|
12
|
-
*
|
|
13
|
-
* Custom overrides for edge cases:
|
|
14
|
-
* - customAuthFlow: Override authorization URL building
|
|
15
|
-
* - customTokenExchange: Override token exchange logic
|
|
16
|
-
*/
|
|
17
|
-
export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
|
18
|
-
'google-sheets': {
|
|
19
|
-
id: 'google-sheets',
|
|
20
|
-
name: 'Google Sheets',
|
|
21
|
-
authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
22
|
-
tokenUrl: 'https://oauth2.googleapis.com/token',
|
|
23
|
-
authParams: {
|
|
24
|
-
access_type: 'offline', // Required for refresh token
|
|
25
|
-
prompt: 'consent' // Force consent to get refresh token on reconnect
|
|
26
|
-
},
|
|
27
|
-
tokenExchange: 'form-encoded',
|
|
28
|
-
scopes: ['https://www.googleapis.com/auth/spreadsheets']
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
'google-calendar': {
|
|
32
|
-
id: 'google-calendar',
|
|
33
|
-
name: 'Google Calendar',
|
|
34
|
-
authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
35
|
-
tokenUrl: 'https://oauth2.googleapis.com/token',
|
|
36
|
-
authParams: {
|
|
37
|
-
access_type: 'offline', // Required for refresh token
|
|
38
|
-
prompt: 'consent' // Force consent to get refresh token on reconnect
|
|
39
|
-
},
|
|
40
|
-
tokenExchange: 'form-encoded',
|
|
41
|
-
scopes: ['https://www.googleapis.com/auth/calendar.readonly']
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
dropbox: {
|
|
45
|
-
id: 'dropbox',
|
|
46
|
-
name: 'Dropbox',
|
|
47
|
-
authUrl: 'https://www.dropbox.com/oauth2/authorize',
|
|
48
|
-
tokenUrl: 'https://api.dropboxapi.com/oauth2/token',
|
|
49
|
-
authParams: {
|
|
50
|
-
token_access_type: 'offline' // Required for refresh token
|
|
51
|
-
},
|
|
52
|
-
tokenExchange: 'form-encoded',
|
|
53
|
-
scopes: ['files.content.write', 'files.content.read', 'files.metadata.write']
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Get provider config by ID
|
|
59
|
-
* @throws Error if provider not found
|
|
60
|
-
*/
|
|
61
|
-
export function getProviderConfig(providerId: string): OAuthProviderConfig {
|
|
62
|
-
const config = OAUTH_PROVIDERS[providerId]
|
|
63
|
-
if (!config) {
|
|
64
|
-
throw new Error(`Unknown OAuth provider: ${providerId}`)
|
|
65
|
-
}
|
|
66
|
-
return config
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* List all available providers (for frontend)
|
|
71
|
-
*/
|
|
72
|
-
export function listProviders(): OAuthProviderConfig[] {
|
|
73
|
-
return Object.values(OAUTH_PROVIDERS)
|
|
74
|
-
}
|
|
1
|
+
import type { OAuthProviderConfig } from './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OAuth Provider Registry
|
|
5
|
+
*
|
|
6
|
+
* Add new integration = add config object here (no new code needed)
|
|
7
|
+
*
|
|
8
|
+
* Standard token exchange methods:
|
|
9
|
+
* - basic-auth: client_id:client_secret in Authorization header
|
|
10
|
+
* - form-encoded: credentials in URL-encoded body (Google)
|
|
11
|
+
* - json-body: credentials in JSON body (most providers)
|
|
12
|
+
*
|
|
13
|
+
* Custom overrides for edge cases:
|
|
14
|
+
* - customAuthFlow: Override authorization URL building
|
|
15
|
+
* - customTokenExchange: Override token exchange logic
|
|
16
|
+
*/
|
|
17
|
+
export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
|
18
|
+
'google-sheets': {
|
|
19
|
+
id: 'google-sheets',
|
|
20
|
+
name: 'Google Sheets',
|
|
21
|
+
authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
22
|
+
tokenUrl: 'https://oauth2.googleapis.com/token',
|
|
23
|
+
authParams: {
|
|
24
|
+
access_type: 'offline', // Required for refresh token
|
|
25
|
+
prompt: 'consent' // Force consent to get refresh token on reconnect
|
|
26
|
+
},
|
|
27
|
+
tokenExchange: 'form-encoded',
|
|
28
|
+
scopes: ['https://www.googleapis.com/auth/spreadsheets']
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
'google-calendar': {
|
|
32
|
+
id: 'google-calendar',
|
|
33
|
+
name: 'Google Calendar',
|
|
34
|
+
authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
35
|
+
tokenUrl: 'https://oauth2.googleapis.com/token',
|
|
36
|
+
authParams: {
|
|
37
|
+
access_type: 'offline', // Required for refresh token
|
|
38
|
+
prompt: 'consent' // Force consent to get refresh token on reconnect
|
|
39
|
+
},
|
|
40
|
+
tokenExchange: 'form-encoded',
|
|
41
|
+
scopes: ['https://www.googleapis.com/auth/calendar.readonly']
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
dropbox: {
|
|
45
|
+
id: 'dropbox',
|
|
46
|
+
name: 'Dropbox',
|
|
47
|
+
authUrl: 'https://www.dropbox.com/oauth2/authorize',
|
|
48
|
+
tokenUrl: 'https://api.dropboxapi.com/oauth2/token',
|
|
49
|
+
authParams: {
|
|
50
|
+
token_access_type: 'offline' // Required for refresh token
|
|
51
|
+
},
|
|
52
|
+
tokenExchange: 'form-encoded',
|
|
53
|
+
scopes: ['files.content.write', 'files.content.read', 'files.metadata.write']
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get provider config by ID
|
|
59
|
+
* @throws Error if provider not found
|
|
60
|
+
*/
|
|
61
|
+
export function getProviderConfig(providerId: string): OAuthProviderConfig {
|
|
62
|
+
const config = OAUTH_PROVIDERS[providerId]
|
|
63
|
+
if (!config) {
|
|
64
|
+
throw new Error(`Unknown OAuth provider: ${providerId}`)
|
|
65
|
+
}
|
|
66
|
+
return config
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* List all available providers (for frontend)
|
|
71
|
+
*/
|
|
72
|
+
export function listProviders(): OAuthProviderConfig[] {
|
|
73
|
+
return Object.values(OAUTH_PROVIDERS)
|
|
74
|
+
}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OAuth Provider Credentials
|
|
3
|
-
* Maps provider IDs to environment variable names
|
|
4
|
-
* Single source of truth for credential lookup
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const PROVIDER_ENV_VARS: Record<string, { clientIdEnv: string; clientSecretEnv: string }> = {
|
|
8
|
-
'google-sheets': {
|
|
9
|
-
clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',
|
|
10
|
-
clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET'
|
|
11
|
-
},
|
|
12
|
-
'google-calendar': {
|
|
13
|
-
clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',
|
|
14
|
-
clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET'
|
|
15
|
-
},
|
|
16
|
-
dropbox: {
|
|
17
|
-
clientIdEnv: 'DROPBOX_APP_KEY',
|
|
18
|
-
clientSecretEnv: 'DROPBOX_APP_SECRET'
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get OAuth client credentials for a provider
|
|
24
|
-
* @throws Error if provider unknown or credentials missing
|
|
25
|
-
*/
|
|
26
|
-
export function getOAuthCredentials(providerId: string): { clientId: string; clientSecret: string } {
|
|
27
|
-
const config = PROVIDER_ENV_VARS[providerId]
|
|
28
|
-
if (!config) {
|
|
29
|
-
throw new Error(`Unknown OAuth provider: ${providerId}`)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const clientId = process.env[config.clientIdEnv]
|
|
33
|
-
const clientSecret = process.env[config.clientSecretEnv]
|
|
34
|
-
|
|
35
|
-
if (!clientId) {
|
|
36
|
-
throw new Error(`Missing environment variable: ${config.clientIdEnv}`)
|
|
37
|
-
}
|
|
38
|
-
if (!clientSecret) {
|
|
39
|
-
throw new Error(`Missing environment variable: ${config.clientSecretEnv}`)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return { clientId, clientSecret }
|
|
43
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Provider Credentials
|
|
3
|
+
* Maps provider IDs to environment variable names
|
|
4
|
+
* Single source of truth for credential lookup
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const PROVIDER_ENV_VARS: Record<string, { clientIdEnv: string; clientSecretEnv: string }> = {
|
|
8
|
+
'google-sheets': {
|
|
9
|
+
clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',
|
|
10
|
+
clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET'
|
|
11
|
+
},
|
|
12
|
+
'google-calendar': {
|
|
13
|
+
clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',
|
|
14
|
+
clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET'
|
|
15
|
+
},
|
|
16
|
+
dropbox: {
|
|
17
|
+
clientIdEnv: 'DROPBOX_APP_KEY',
|
|
18
|
+
clientSecretEnv: 'DROPBOX_APP_SECRET'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get OAuth client credentials for a provider
|
|
24
|
+
* @throws Error if provider unknown or credentials missing
|
|
25
|
+
*/
|
|
26
|
+
export function getOAuthCredentials(providerId: string): { clientId: string; clientSecret: string } {
|
|
27
|
+
const config = PROVIDER_ENV_VARS[providerId]
|
|
28
|
+
if (!config) {
|
|
29
|
+
throw new Error(`Unknown OAuth provider: ${providerId}`)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const clientId = process.env[config.clientIdEnv]
|
|
33
|
+
const clientSecret = process.env[config.clientSecretEnv]
|
|
34
|
+
|
|
35
|
+
if (!clientId) {
|
|
36
|
+
throw new Error(`Missing environment variable: ${config.clientIdEnv}`)
|
|
37
|
+
}
|
|
38
|
+
if (!clientSecret) {
|
|
39
|
+
throw new Error(`Missing environment variable: ${config.clientSecretEnv}`)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return { clientId, clientSecret }
|
|
43
|
+
}
|