Files
Compass/common/src/secrets.ts
MartinBraquet 4c76b643e3 Add voice recording, transcription, and audio player components
- Implemented `AudioPlayer` for custom audio playback controls.
- Added `useAudioRecorder` hook for managing microphone audio recording with visual feedback.
- Introduced audio transcription API integration using OpenAI Whisper.
- Created `blobToBase64` utility to encode recorded blobs for API consumption.
- Added IndexedDB-based `recording-store` for saving in-progress recordings.
- Developed `VoiceAutofillSection` for guided recording, playback, transcription, and editing.
2026-07-25 18:01:58 +02:00

102 lines
3.1 KiB
TypeScript

import {SecretManagerServiceClient} from '@google-cloud/secret-manager'
import {IS_DEV} from 'common/envs/constants'
import {refreshConfig} from 'common/envs/prod'
import {IS_LOCAL} from 'common/hosting/constants'
import {debug} from 'common/logger'
import {zip} from 'lodash'
// List of secrets that are available to backend (api, functions, scripts, etc.)
// Edit them at:
// https://console.cloud.google.com/security/secret-manager?project=compass-130ba
export const secrets = (
[
// 'STRIPE_APIKEY',
// 'STRIPE_WEBHOOKSECRET',
'SUPABASE_KEY',
'SUPABASE_JWT_SECRET',
'SUPABASE_DB_PASSWORD',
'TEST_CREATE_USER_KEY',
'GEODB_API_KEY',
'RESEND_KEY',
'COMPASS_API_KEY',
'NEXT_PUBLIC_FIREBASE_API_KEY',
'DISCORD_WEBHOOK_MEMBERS',
'DISCORD_WEBHOOK_GENERAL',
'DISCORD_WEBHOOK_HEALTH',
'DISCORD_WEBHOOK_REPORTS',
'DISCORD_WEBHOOK_CONTACT',
'VAPID_PUBLIC_KEY',
'VAPID_PRIVATE_KEY',
'DB_ENC_MASTER_KEY_BASE64',
'GOOGLE_CLIENT_SECRET',
'GEMINI_API_KEY',
'OPENAI_API_KEY',
// Some typescript voodoo to keep the string literal types while being not readonly.
] as const
).concat()
type SecretId = (typeof secrets)[number]
// Fetches all secrets from google cloud.
// For deployed google cloud service, no credential is needed.
// For local and Vercel deployments: requires credentials json object.
export const getSecrets = async (credentials?: any, ...ids: SecretId[]) => {
if (!ids.length && IS_LOCAL) return {}
// console.debug('Fetching secrets...')
let client: SecretManagerServiceClient
if (credentials) {
const projectId = credentials['project_id']
client = new SecretManagerServiceClient({
credentials,
projectId,
})
} else {
client = new SecretManagerServiceClient()
}
const projectId = await client.getProjectId()
const secretIds = ids.length > 0 ? ids : secrets
debug('secretIds', secretIds)
const fullSecretNames = secretIds.map(
(secret: string) => `${client.projectPath(projectId)}/secrets/${secret}/versions/latest`,
)
const secretValues = await Promise.all(
fullSecretNames.map(async (name) => {
try {
const [response] = await client.accessSecretVersion({name})
return response.payload!.data!.toString()
} catch (err) {
// In dev, tolerate secrets that haven't been provisioned yet instead of
// crashing startup. Prod still fails loudly on a missing secret.
if (IS_DEV) {
debug(`Missing secret ${name}, skipping (dev).`)
return undefined
}
throw err
}
}),
)
const pairs = zip(secretIds, secretValues).filter(([, value]) => value != null) as [
string,
string,
][]
return Object.fromEntries(pairs)
}
// Fetches all secrets and loads them into process.env.
// Useful for running random backend code.
export const loadSecretsToEnv = async (credentials?: any) => {
const allSecrets = await getSecrets(credentials)
for (const [key, value] of Object.entries(allSecrets)) {
if (key && value) {
process.env[key] = value
// console.debug(key, value)
}
}
refreshConfig()
}