mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
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>
101 lines
3.1 KiB
TypeScript
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)
|
|
)
|
|
}
|
|
}
|