-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Expand file tree
/
Copy pathgenerate-deployment-config.ts
More file actions
123 lines (112 loc) · 4.46 KB
/
Copy pathgenerate-deployment-config.ts
File metadata and controls
123 lines (112 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env bun
/**
* Generates deployment facts from the canonical OAuth registry.
*
* The setup package cannot import the application registry at runtime, so it
* consumes this checked-in projection instead. Deployment policy does not
* belong here; special availability rules remain handwritten in
* `packages/deployment-config/src/service-account-metadata.ts`.
*
* Usage:
* bun run scripts/generate-deployment-config.ts
* bun run scripts/generate-deployment-config.ts --check
*/
import { readFile, writeFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { getAllOAuthServices } from '../apps/sim/lib/oauth/utils'
import integrationsJson from '../packages/deployment-config/src/integrations.json'
import { formatGeneratedSource } from './format-generated-source'
interface DeploymentIntegration {
authType: 'oauth' | 'api-key' | 'none'
oauthServiceId?: string
}
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url))
const ROOT = resolve(SCRIPT_DIR, '..')
const OUTPUT_PATH = resolve(
ROOT,
'packages/deployment-config/src/service-account-providers.generated.ts'
)
const CHECK_MODE = process.argv.includes('--check')
interface CanonicalOAuthDeploymentFacts {
credentialConfiguredOAuthServiceIds: readonly string[]
serviceAccountProviders: ReadonlyMap<string, string>
}
function buildOAuthDeploymentFacts(): CanonicalOAuthDeploymentFacts {
const canonicalServices = new Map<
string,
{ credentialConfigured: boolean; serviceAccountProviderId?: string }
>()
for (const service of getAllOAuthServices()) {
if (canonicalServices.has(service.serviceId)) {
throw new Error(`Duplicate canonical OAuth service id: ${service.serviceId}`)
}
canonicalServices.set(service.serviceId, {
credentialConfigured: Boolean(service.clientConfiguration),
serviceAccountProviderId: service.serviceAccountProviderId,
})
}
const catalogServiceIds = new Set<string>()
for (const integration of integrationsJson.integrations as readonly DeploymentIntegration[]) {
if (integration.authType !== 'oauth') continue
if (!integration.oauthServiceId) {
throw new Error(
'Generated integration catalog contains an OAuth entry without oauthServiceId'
)
}
catalogServiceIds.add(integration.oauthServiceId)
}
const providers = new Map<string, string>()
const credentialConfiguredOAuthServiceIds: string[] = []
for (const serviceId of [...catalogServiceIds].sort()) {
if (!canonicalServices.has(serviceId)) {
throw new Error(`Integration catalog references unknown OAuth service: ${serviceId}`)
}
const service = canonicalServices.get(serviceId)
if (service?.credentialConfigured) credentialConfiguredOAuthServiceIds.push(serviceId)
const providerId = service?.serviceAccountProviderId
if (providerId) providers.set(serviceId, providerId)
}
return { credentialConfiguredOAuthServiceIds, serviceAccountProviders: providers }
}
function renderOAuthDeploymentFacts(facts: CanonicalOAuthDeploymentFacts): string {
const quote = (value: string) => `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`
const entries = [...facts.serviceAccountProviders]
.map(
([serviceId, providerId]) =>
` ${/^[A-Za-z_$][\w$]*$/.test(serviceId) ? serviceId : quote(serviceId)}: ${quote(providerId)},`
)
.join('\n')
const credentialConfiguredServiceIds = facts.credentialConfiguredOAuthServiceIds
.map((serviceId) => ` ${quote(serviceId)},`)
.join('\n')
return `/**
* Generated by \`bun run deployment-config:generate\` from the canonical OAuth
* registry and integration catalog. Do not edit this file directly.
*/
export const SERVICE_ACCOUNT_PROVIDER_BY_OAUTH_SERVICE_ID = {
${entries}
} as const
/** OAuth services whose users supply app credentials when connecting an account. */
export const CREDENTIAL_CONFIGURED_OAUTH_SERVICE_IDS = [
${credentialConfiguredServiceIds}
] as const
`
}
const generated = formatGeneratedSource(
renderOAuthDeploymentFacts(buildOAuthDeploymentFacts()),
OUTPUT_PATH,
ROOT
)
if (CHECK_MODE) {
const current = await readFile(OUTPUT_PATH, 'utf8').catch(() => '')
if (current !== generated) {
throw new Error(
'Deployment config is stale. Run `bun run deployment-config:generate` and commit the result.'
)
}
process.stdout.write('Deployment config is current.\n')
} else {
await writeFile(OUTPUT_PATH, generated)
process.stdout.write(`Generated ${OUTPUT_PATH}\n`)
}