Files
supabase/packages/common/configcat.ts
Coenen BenjaminandCharis Lam 11289328e5 add support for warehouse connection string (#49914)
Add support for connection string for warehouse. 
This PR gives the ability to enable warehouse on a project and also get
the connection string to connect to.

> This project is only available in staging for now and gated behind a
feature flag

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
  - Added a Warehouse connection option to the Connect dialog.
- Select schemas and tables to replicate, with setup progress, error
recovery, and retry support.
- View copyable Warehouse connection details, credentials guidance,
command-line instructions, and DuckLake setup scripts.
  - Warehouse availability is controlled by feature configuration.

- **Tests**
- Added coverage for Warehouse table selection, setup script generation,
URL parsing, and connection configuration utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Benjamin <5719034+bnjjj@users.noreply.github.com>
Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
2026-09-07 11:24:42 +02:00

101 lines
3.1 KiB
TypeScript

import * as configcat from 'configcat-js'
let client: configcat.IConfigCatClient
/**
* To set up ConfigCat for another app
* - Declare `FeatureFlagProvider` at the _app level
* - Pass in `getFlags` as `getConfigCatFlags` into `FeatureFlagProvider`
* - [Joshen] Wondering if this should just be baked into FeatureFlagProvider, rather than passed as a prop
* - Ensure that your app has the `NEXT_PUBLIC_CONFIGCAT_PROXY_URL` env var
* - [Joshen] Wondering if we can just set a default value for each env var, so can skip setting up env var in Vercel
* - Verify that your flags are now loading by console logging `flagValues` in `FeatureFlagProvider`'s useEffect
* - Can now use ConfigCat feature flags with the `useFlag` hook
*/
async function getClient() {
if (client) return client
const proxyUrl = process.env.NEXT_PUBLIC_CONFIGCAT_PROXY_URL
const sdkKey = process.env.NEXT_PUBLIC_CONFIGCAT_SDK_KEY
if (!sdkKey && !proxyUrl) {
console.log('Skipping ConfigCat set up as env vars are not present')
return undefined
}
const options = { pollIntervalSeconds: 7 * 60 } // 7 minutes
try {
if (proxyUrl) {
const proxyClient = configcat.getClient(
'configcat-proxy/frontend-v2',
configcat.PollingMode.AutoPoll,
{ ...options, baseUrl: proxyUrl }
)
const cacheState = await proxyClient.waitForReady()
if (cacheState !== configcat.ClientCacheState.NoFlagData) {
client = proxyClient
return client
}
proxyClient.dispose()
}
if (sdkKey) {
client = configcat.getClient(sdkKey, configcat.PollingMode.AutoPoll, options)
return client
}
console.error('ConfigCat proxy unreachable and SDK key is missing')
return undefined
} catch (error: any) {
console.error(`Failed to get ConfigCat client: ${error.message}`)
return undefined
}
}
/**
* Reads a ConfigCat string-array-style flag, targeted by `targetingKey` rather than user email. The
* flag value is a comma-separated list, or the `'none'` sentinel for an empty list.
*/
export async function getStringArrayFlag(flagKey: string, targetingKey: string): Promise<string[]> {
const client = await getClient()
if (!client) return []
await client.waitForReady()
const rawValue = await client.getValueAsync(flagKey, '', new configcat.User(targetingKey))
if (!rawValue || rawValue === 'none') return []
return rawValue
.split(',')
.map((value) => value.trim())
.filter(Boolean)
}
export async function getFlags(userEmail: string = '', customAttributes?: Record<string, string>) {
const client = await getClient()
const _customAttributes = {
...customAttributes,
is_staff: !!userEmail ? userEmail.includes('@supabase.').toString() : 'false',
}
if (!client) {
return []
}
await client.waitForReady()
if (userEmail) {
return client.getAllValuesAsync(
new configcat.User(userEmail, undefined, undefined, _customAttributes)
)
} else {
return client.getAllValuesAsync(
new configcat.User('anonymous', undefined, undefined, _customAttributes)
)
}
}