mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-07-30 17:59:13 -04:00
- 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.
102 lines
3.1 KiB
TypeScript
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()
|
|
}
|