diff --git a/.env.example b/.env.example index ae9250596..9ba4011c0 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ PUBLIC_CONSOLE_MODE=self-hosted +PUBLIC_CONSOLE_FEATURE_FLAGS= PUBLIC_APPWRITE_MULTI_REGION=false PUBLIC_APPWRITE_ENDPOINT=http://localhost/v1 - PUBLIC_STRIPE_KEY= PUBLIC_GROWTH_ENDPOINT= \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2a37e81d1..998d91f7e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -78,6 +78,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} build-args: | "PUBLIC_CONSOLE_MODE=cloud" + "PUBLIC_CONSOLE_FEATURE_FLAGS="sites,csv-import" "PUBLIC_APPWRITE_MULTI_REGION=true" "PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}" "PUBLIC_STRIPE_KEY=${{ secrets.PUBLIC_STRIPE_KEY_STAGE }}" @@ -116,6 +117,7 @@ jobs: build-args: | "PUBLIC_CONSOLE_MODE=self-hosted" "PUBLIC_APPWRITE_MULTI_REGION=false" + "PUBLIC_CONSOLE_FEATURE_FLAGS="sites,csv-import" "PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}" publish-cloud-no-regions: @@ -153,5 +155,6 @@ jobs: build-args: | "PUBLIC_CONSOLE_MODE=cloud" "PUBLIC_APPWRITE_MULTI_REGION=false" + "PUBLIC_CONSOLE_FEATURE_FLAGS="sites,csv-import" "PUBLIC_STRIPE_KEY=${{ secrets.PUBLIC_STRIPE_KEY_STAGE }}" "PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}" diff --git a/Dockerfile b/Dockerfile index 774fb6903..e172247b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,6 +21,7 @@ ADD ./src /app/src ADD ./static /app/static ARG PUBLIC_CONSOLE_MODE +ARG PUBLIC_CONSOLE_FEATURE_FLAGS ARG PUBLIC_APPWRITE_MULTI_REGION ARG PUBLIC_APPWRITE_ENDPOINT ARG PUBLIC_GROWTH_ENDPOINT @@ -31,6 +32,7 @@ ARG SENTRY_RELEASE ENV PUBLIC_APPWRITE_ENDPOINT=$PUBLIC_APPWRITE_ENDPOINT ENV PUBLIC_GROWTH_ENDPOINT=$PUBLIC_GROWTH_ENDPOINT ENV PUBLIC_CONSOLE_MODE=$PUBLIC_CONSOLE_MODE +ENV PUBLIC_CONSOLE_FEATURE_FLAGS=$PUBLIC_CONSOLE_FEATURE_FLAGS ENV PUBLIC_APPWRITE_MULTI_REGION=$PUBLIC_APPWRITE_MULTI_REGION ENV PUBLIC_STRIPE_KEY=$PUBLIC_STRIPE_KEY ENV SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN diff --git a/build.js b/build.js index f56506dae..affdf3ddd 100644 --- a/build.js +++ b/build.js @@ -24,6 +24,7 @@ async function main() { log(bold().magenta('APPWRITE CONSOLE')); log(); logEnv('CONSOLE MODE', env?.PUBLIC_CONSOLE_MODE); + logEnv('CONSOLE FEATURE FLAGS', env?.PUBLIC_CONSOLE_FEATURE_FLAGS); logEnv('MULTI REGION', env?.PUBLIC_APPWRITE_MULTI_REGION); logEnv('APPWRITE ENDPOINT', env?.PUBLIC_APPWRITE_ENDPOINT, 'relative'); logEnv('GROWTH ENDPOINT', env?.PUBLIC_GROWTH_ENDPOINT); diff --git a/compose.yml b/compose.yml index 6166d3776..587619414 100644 --- a/compose.yml +++ b/compose.yml @@ -5,6 +5,7 @@ services: context: . args: PUBLIC_CONSOLE_MODE: ${PUBLIC_CONSOLE_MODE} + PUBLIC_CONSOLE_FEATURE_FLAGS: ${PUBLIC_CONSOLE_FEATURE_FLAGS} PUBLIC_APPWRITE_MULTI_REGION: ${PUBLIC_APPWRITE_MULTI_REGION} PUBLIC_APPWRITE_ENDPOINT: ${PUBLIC_APPWRITE_ENDPOINT} PUBLIC_GROWTH_ENDPOINT: ${PUBLIC_GROWTH_ENDPOINT} @@ -21,6 +22,7 @@ services: - build/ environment: - PUBLIC_CONSOLE_MODE + - PUBLIC_CONSOLE_FEATURE_FLAGS - PUBLIC_APPWRITE_MULTI_REGION - PUBLIC_APPWRITE_ENDPOINT - PUBLIC_GROWTH_ENDPOINT diff --git a/src/lib/flags.ts b/src/lib/flags.ts new file mode 100644 index 000000000..54d5ba576 --- /dev/null +++ b/src/lib/flags.ts @@ -0,0 +1,24 @@ +import { env } from '$env/dynamic/public'; +import type { Account } from './stores/user'; +import type { Organization } from './stores/organization'; + +// Parse feature flags from env as a string array (exact match only) +const flagsRaw = (env.PUBLIC_CONSOLE_FEATURE_FLAGS ?? '').split(','); + +function isFlagEnabled(name: string) { + // loose generic to allow safe access while retaining type safety + return (data: T) => { + const { account, organization } = data; + + return !!( + flagsRaw.includes(name) || + account?.prefs?.[`flags-${name}`] || + organization?.prefs?.[`flags-${name}`] + ); + }; +} + +export const flags = { + showSites: isFlagEnabled('sites'), + showCsvImport: isFlagEnabled('csv-import') +}; diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte index 98627a228..289cb6368 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte @@ -24,8 +24,7 @@ import { base } from '$app/paths'; import { IconPlus } from '@appwrite.io/pink-icons-svelte'; import type { Models } from '@appwrite.io/console'; - import { organization } from '$lib/stores/organization'; - import { APPWRITE_OFFICIALS_ORG, isCloud } from '$lib/system'; + import { flags } from '$lib/flags'; export let data: PageData; @@ -88,14 +87,6 @@ $isCsvImportInProgress = false; } } - - /** - * Controls visibility of CSV Imports feature: - * - Shown if running on self-hosted - * - Shown on cloud only if the organization is Appwrite's. - * - Hidden on cloud for any non-Appwrite organization. - */ - $: showCsvImports = !isCloud || $organization.$id === APPWRITE_OFFICIALS_ORG; {#key page.params.collection} @@ -109,7 +100,7 @@ analyticsSource="database_documents" /> - {#if showCsvImports} + {#if flags.showCsvImport(data)}