From 9791d314b534b156dd72505732a4a00eb8cda7f0 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Sun, 3 May 2026 20:12:05 +0530 Subject: [PATCH 1/5] feat: add rust function runtime template support --- bun.lock | 4 +- package.json | 2 +- src/lib/stores/runtimes.ts | 16 +- .../functions/create-function/+page.svelte | 40 ++--- .../create-function/deploy/+page.svelte | 9 +- .../create-function/manual/+page.svelte | 2 +- .../repository-[repository]/+page.svelte | 2 +- .../template-[template]/+page.svelte | 139 ++++++++++-------- src/routes/(public)/functions/deploy/+page.ts | 15 +- static/icons/dark/color/rust.svg | 1 + static/icons/dark/grayscale/rust.svg | 1 + static/icons/light/color/rust.svg | 1 + static/icons/light/grayscale/rust.svg | 1 + 13 files changed, 140 insertions(+), 93 deletions(-) create mode 100644 static/icons/dark/color/rust.svg create mode 100644 static/icons/dark/grayscale/rust.svg create mode 100644 static/icons/light/color/rust.svg create mode 100644 static/icons/light/grayscale/rust.svg diff --git a/bun.lock b/bun.lock index 3e2c925ae..616c2964a 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "name": "@appwrite/console", "dependencies": { "@ai-sdk/svelte": "^1.1.24", - "@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@33968aa", + "@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@93d2dfa", "@appwrite.io/pink-icons": "0.25.0", "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@bfe7ce3", "@appwrite.io/pink-legacy": "^1.0.3", @@ -124,7 +124,7 @@ "@analytics/type-utils": ["@analytics/type-utils@0.6.4", "", {}, "sha512-Ou1gQxFakOWLcPnbFVsrPb8g1wLLUZYYJXDPjHkG07+5mustGs5yqACx42UAu4A6NszNN6Z5gGxhyH45zPWRxw=="], - "@appwrite.io/console": ["@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@33968aa", { "dependencies": { "json-bigint": "1.0.0" } }], + "@appwrite.io/console": ["@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@93d2dfa", { "dependencies": { "json-bigint": "1.0.0" } }], "@appwrite.io/pink-icons": ["@appwrite.io/pink-icons@0.25.0", "", {}, "sha512-0O3i2oEuh5mWvjO80i+X6rbzrWLJ1m5wmv2/M3a1p2PyBJsFxN8xQMTEmTn3Wl/D26SsM7SpzbdW6gmfgoVU9Q=="], diff --git a/package.json b/package.json index a18b34eaa..99b100b0a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "@ai-sdk/svelte": "^1.1.24", - "@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@33968aa", + "@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@93d2dfa", "@appwrite.io/pink-icons": "0.25.0", "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@bfe7ce3", "@appwrite.io/pink-legacy": "^1.0.3", diff --git a/src/lib/stores/runtimes.ts b/src/lib/stores/runtimes.ts index c42f8b1f7..c30d0ae04 100644 --- a/src/lib/stores/runtimes.ts +++ b/src/lib/stores/runtimes.ts @@ -1,5 +1,7 @@ -export function getIconFromRuntime(runtime: string) { +export function getIconFromRuntime(runtime?: string) { switch (true) { + case !runtime: + return undefined; case runtime.includes('node'): return 'node'; case runtime.includes('php'): @@ -18,6 +20,18 @@ export function getIconFromRuntime(runtime: string) { return 'deno'; case runtime.includes('flutter'): return 'flutter'; + case runtime.includes('dotnet'): + return 'dotnet'; + case runtime.includes('java'): + return 'java'; + case runtime.includes('swift'): + return 'swift'; + case runtime.includes('kotlin'): + return 'kotlin'; + case runtime.includes('cpp'): + return 'cpp'; + case runtime.includes('rust'): + return 'rust'; default: return undefined; } diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/+page.svelte index 42be5ca74..a9c2e00cd 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/+page.svelte @@ -21,6 +21,7 @@ import Wizard from '$lib/layout/wizard.svelte'; import { Link } from '$lib/elements'; import { Button } from '$lib/elements/forms'; + import { getIconFromRuntime } from '$lib/stores/runtimes'; import { regionalConsoleVariables } from '../../store'; export let data; @@ -36,17 +37,17 @@ const starterTemplate = data.templates.find((template) => template.id === 'starter'); - const baseRuntimesList = [ - ...new Map( - data.runtimesList.runtimes.map((runtime) => { - const base = runtime.name.split('-')[0]; - return [base, runtime]; - }) - ).values() - ]; + const latestRuntimesByKey = new Map(); + for (const runtime of data.runtimesList.runtimes) { + latestRuntimesByKey.set(runtime.key, runtime); + } - const starterTemplateRuntimes = starterTemplate.runtimes.filter((r) => - baseRuntimesList.some((base) => base.$id === r.name) + const starterTemplateRuntimeIds = new Set( + starterTemplate?.runtimes.map((runtime) => runtime.name) ?? [] + ); + + const starterTemplateRuntimes = [...latestRuntimesByKey.values()].filter((runtime) => + starterTemplateRuntimeIds.has(runtime.$id) ); function connect(e: Models.ProviderRepository) { @@ -131,11 +132,8 @@ Quick start - {#each starterTemplateRuntimes.slice(0, 6) as template} - {@const iconName = template.name.split('-')[0]} - {@const runtimeDetail = baseRuntimesList.find( - (runtime) => runtime.$id === template.name - )} + {#each starterTemplateRuntimes as runtime} + {@const iconName = getIconFromRuntime(runtime.key)} + ) + `?runtime=${runtime.$id}`}> - - + + {#if iconName} + + {/if} - {runtimeDetail?.name} + {runtime.name} diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte index 26410e3e6..e0e389e91 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte @@ -59,13 +59,16 @@ data.runtimesList?.runtimes?.map((r) => ({ value: r.$id, label: `${r.name} - ${r.version}`, - leadingHtml: `` + leadingHtml: `` })) || [] ); onMount(() => { - const runtimeParam = data.runtime || page.url.searchParams.get('runtime') || 'node-18.0'; - runtime = runtimeParam as Runtime; + const runtimeParam = data.runtime || page.url.searchParams.get('runtime'); + const runtimeOption = data.runtimesList.runtimes.find( + (runtime) => runtime.$id === runtimeParam + ); + runtime = (runtimeOption?.$id ?? data.runtimesList.runtimes[0]?.$id) as Runtime; entrypoint = page.url.searchParams.get('entrypoint') || ''; diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte index c1452020d..d0e10cdf4 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte @@ -32,7 +32,7 @@ const runtimeOptions = data.runtimesList.runtimes.map((runtime) => { const { $id: value, name, version, key } = runtime; const label = `${name} - ${version}`; - const iconName = getIconFromRuntime(key); + const iconName = getIconFromRuntime(key) ?? 'empty'; const iconSrc = iconFor(iconName, 'color'); const leadingHtml = `${iconName}`; diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/repository-[repository]/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/repository-[repository]/+page.svelte index 58d29ad20..7b19202d0 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/repository-[repository]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/repository-[repository]/+page.svelte @@ -37,7 +37,7 @@ return { value: runtime.$id, label: `${runtime.name} - ${runtime.version}`, - leadingHtml: `` + leadingHtml: `` }; }); diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte index 8aef379d1..cfb1bcd80 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte @@ -11,7 +11,7 @@ import { installation, repository } from '$lib/stores/vcs'; import { Fieldset, Layout, Icon, Divider, Empty, Typography } from '@appwrite.io/pink-svelte'; import { IconGithub } from '@appwrite.io/pink-icons-svelte'; - import { onMount } from 'svelte'; + import { onMount, untrack } from 'svelte'; import { writable } from 'svelte/store'; import ProductionBranch from '$lib/components/git/productionBranchFieldset.svelte'; import Configuration from './configuration.svelte'; @@ -37,64 +37,83 @@ import { Dependencies } from '$lib/constants'; import { getIconFromRuntime } from '$lib/stores/runtimes'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import type { PageData } from './$types'; - export let data; + let { data }: { data: PageData } = $props(); - const specificationOptions = (data.specificationsList?.specifications ?? []).map((size) => ({ - label: - `${size.cpus} CPU, ${size.memory} MB RAM` + - (!size.enabled ? ` (Upgrade to use this)` : ''), - value: size.slug, - disabled: !size.enabled - })); + const specificationOptions = $derived( + (data.specificationsList?.specifications ?? []).map((size) => ({ + label: + `${size.cpus} CPU, ${size.memory} MB RAM` + + (!size.enabled ? ` (Upgrade to use this)` : ''), + value: size.slug, + disabled: !size.enabled + })) + ); - let showExitModal = false; - let isCreatingRepository = false; + let showExitModal = $state(false); + let isCreatingRepository = $state(false); - let formComponent: Form; - let isSubmitting = writable(false); + let formComponent = $state
(); + let isSubmitting = $state(writable(false)); - let name = data.template.name; - let id: string | null = null; - let runtime: Runtime; - let branch = 'main'; - let rootDir = './'; - let connectBehaviour: 'now' | 'later' = 'now'; - let repositoryBehaviour: 'new' | 'existing' = 'new'; - let repositoryName = undefined; - let repositoryPrivate = true; - let selectedInstallationId = ''; - let selectedRepository = ''; - let showConfig = false; - let silentMode = false; - let entrypoint = ''; - let selectedScopes: Scopes[] = []; - let execute = true; - let variables: Partial[] = []; - let specification = specificationOptions[0]?.value || ''; + let name = $state(untrack(() => data.template.name)); + let id = $state(null); + let runtime = $state(); + let branch = $state('main'); + let rootDir = $state('./'); + let connectBehaviour = $state<'now' | 'later'>('now'); + let repositoryBehaviour = $state<'new' | 'existing'>('new'); + let repositoryName = $state(); + let repositoryPrivate = $state(true); + let selectedInstallationId = $state(''); + let selectedRepository = $state(''); + let showConfig = $state(false); + let silentMode = $state(false); + let entrypoint = $state(''); + let selectedScopes = $state([]); + let execute = $state(true); + let variables = $state[]>([]); + let specification = $state(untrack(() => specificationOptions[0]?.value || '')); + + const availableRuntimes: Models.Runtime[] = $derived( + data.runtimesList.runtimes.filter((runtime) => + data.template.runtimes.some((templateRuntime) => templateRuntime.name === runtime.$id) + ) + ); + + function sortRuntimesByVersionDesc(a: Models.Runtime, b: Models.Runtime) { + return b.version.localeCompare(a.version, undefined, { numeric: true }); + } + + function selectInitialRuntime() { + const runtimeParam = page.url.searchParams.get('runtime'); + const requestedRuntime = availableRuntimes.find((runtime) => runtime.$id === runtimeParam); + + if (requestedRuntime) { + return requestedRuntime.$id as Runtime; + } + + const runtimeById = new Map( + data.runtimesList.runtimes.map((runtime) => [runtime.$id, runtime]) + ); + const preferredRuntime = data.template.runtimes + .map((runtime) => runtimeById.get(runtime.name)) + .find(Boolean); + const preferredRuntimes = preferredRuntime + ? availableRuntimes.filter((runtime) => runtime.key === preferredRuntime.key) + : []; + const runtimes = preferredRuntimes.length ? preferredRuntimes : availableRuntimes; + + return [...runtimes].sort(sortRuntimesByVersionDesc)[0]?.$id as Runtime; + } onMount(async () => { if (!$installation?.$id) { $installation = data.installations.installations[0]; } selectedInstallationId = $installation?.$id; - if (data.template.runtimes && data.template.runtimes.length > 0) { - const targetRuntime = data.template.runtimes[0].name; - const matchingRuntimes = Object.values(Runtime).filter((r) => - r.startsWith(targetRuntime.split('-')[0]) - ); - - matchingRuntimes.sort((a, b) => { - const versionA = a.split('-')[1]; - const versionB = b.split('-')[1]; - return versionB.localeCompare(versionA, undefined, { numeric: true }); - }); - if (page.url.searchParams.has('runtime')) { - runtime = page.url.searchParams.get('runtime') as Runtime; - } else { - runtime = matchingRuntimes[0] as Runtime; - } - } + runtime = selectInitialRuntime(); }); async function createRepository() { @@ -210,18 +229,18 @@ } } - $: if (repositoryBehaviour === 'new') { - selectedInstallationId ??= $installation?.$id; - repositoryName ??= name.split(' ').join('-').toLowerCase(); - } + $effect(() => { + if (repositoryBehaviour === 'new') { + selectedInstallationId ??= $installation?.$id; + repositoryName ??= name.split(' ').join('-').toLowerCase(); + } + }); - $: if (connectBehaviour === 'later') { - selectedRepository = null; - } - - $: availableRuntimes = data.runtimesList.runtimes.filter((runtime) => - data.template.runtimes.some((templateRuntime) => templateRuntime.name === runtime.$id) - ); + $effect(() => { + if (connectBehaviour === 'later') { + selectedRepository = null; + } + }); @@ -259,7 +278,7 @@ return { value: runtime.$id, label: `${runtime.name} - ${runtime.version}`, - leadingHtml: `` + leadingHtml: `` }; })} diff --git a/src/routes/(public)/functions/deploy/+page.ts b/src/routes/(public)/functions/deploy/+page.ts index 929de33ec..28defa677 100644 --- a/src/routes/(public)/functions/deploy/+page.ts +++ b/src/routes/(public)/functions/deploy/+page.ts @@ -31,6 +31,16 @@ export const load: PageLoad = async ({ parent, url }) => { const envParam = url.searchParams.get('env'); const envKeys = envParam ? envParam.split(',').map((key: string) => key.trim()) : []; + // Get available runtimes + const runtimesList = await sdk.forConsole.functions.listRuntimes(); + + const runtimeOption = runtimesList.runtimes.find((option) => option.$id === runtime); + const runtimeId = runtimeOption?.$id ?? runtimesList.runtimes[0]?.$id; + + if (!runtimeId) { + redirect(302, base + '/'); + } + const deploymentData: { type: 'repo'; repository: { @@ -48,12 +58,9 @@ export const load: PageLoad = async ({ parent, url }) => { rootDirectory: null }, name: name || '', - runtime: runtime || 'node-18.0' + runtime: runtimeId }; - // Get available runtimes - const runtimesList = await sdk.forConsole.functions.listRuntimes(); - const info = getRepositoryInfo(repository); if (!info) { redirect(302, base + '/'); diff --git a/static/icons/dark/color/rust.svg b/static/icons/dark/color/rust.svg new file mode 100644 index 000000000..7364d9ede --- /dev/null +++ b/static/icons/dark/color/rust.svg @@ -0,0 +1 @@ + diff --git a/static/icons/dark/grayscale/rust.svg b/static/icons/dark/grayscale/rust.svg new file mode 100644 index 000000000..af2f8dd01 --- /dev/null +++ b/static/icons/dark/grayscale/rust.svg @@ -0,0 +1 @@ + diff --git a/static/icons/light/color/rust.svg b/static/icons/light/color/rust.svg new file mode 100644 index 000000000..7364d9ede --- /dev/null +++ b/static/icons/light/color/rust.svg @@ -0,0 +1 @@ + diff --git a/static/icons/light/grayscale/rust.svg b/static/icons/light/grayscale/rust.svg new file mode 100644 index 000000000..9c3a86e0c --- /dev/null +++ b/static/icons/light/grayscale/rust.svg @@ -0,0 +1 @@ + From d15dbf77ffcd2c173e7889f18bf0db5a4e413e39 Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Mon, 4 May 2026 11:13:59 +0530 Subject: [PATCH 2/5] Derive scope categories from backend data --- .../overview/api-keys/scopes.svelte | 51 ++++--------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte index 7309623b5..aec5705c4 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte @@ -51,30 +51,6 @@ Database: 'Databases' }; - enum Category { - Project = 'Project', - Auth = 'Auth', - Databases = 'Databases', - Functions = 'Functions', - Messaging = 'Messaging', - Sites = 'Sites', - Storage = 'Storage', - Domains = 'Domains', - Other = 'Other' - } - - const categoryOrder = [ - Category.Project, - Category.Auth, - Category.Databases, - Category.Functions, - Category.Storage, - Category.Messaging, - Category.Sites, - Category.Domains, - Category.Other - ]; - function normalizeCategory(category: string): string { return categoryAliasMap[category] ?? category; } @@ -95,16 +71,9 @@ }); const categories = $derived.by(() => { - const availableCategories = new Set( - filteredScopes.map((scope) => normalizeCategory(scope.category)) + return Array.from( + new Set(filteredScopes.map((scope) => normalizeCategory(scope.category))) ); - - return [ - ...categoryOrder.filter((category) => availableCategories.has(category)), - ...Array.from(availableCategories).filter( - (category) => !categoryOrder.includes(category as Category) - ) - ]; }); const scopeCatalog = $derived( @@ -130,13 +99,6 @@ const result = await sdk.forConsole.console.listProjectScopes(); const scopesById = new Map(); - for (const scope of localScopes) { - scopesById.set(scope.scope, { - ...scope, - category: normalizeCategory(scope.category) - }); - } - for (const scope of result.scopes) { scopesById.set(scope.$id, { scope: scope.$id, @@ -147,6 +109,15 @@ }); } + for (const scope of localScopes) { + if (!scopesById.has(scope.scope)) { + scopesById.set(scope.scope, { + ...scope, + category: normalizeCategory(scope.category) + }); + } + } + allScopesList = Array.from(scopesById.values()); for (const s of filteredScopes) { From 62924e130d131ff38fdcc3708cd9b3c9abe028bb Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Mon, 4 May 2026 11:18:32 +0530 Subject: [PATCH 3/5] Fix repeated cloud scopes and deprecated badge copy --- .../overview/api-keys/scopes.svelte | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte index aec5705c4..826a37324 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte @@ -56,15 +56,34 @@ } const filteredScopes = $derived.by(() => { + const scopesById = new Map(allScopesList.map((scope) => [scope.scope, scope])); + const databasesWriteIndex = allScopesList.findIndex((s) => s.scope === 'databases.write'); if (isCloud && databasesWriteIndex !== -1) { + const normalizedBackupScopes = cloudOnlyBackupScopes.map((scope) => ({ + ...scope, + category: normalizeCategory(scope.category) + })); + const backupScopeIds = new Set(normalizedBackupScopes.map((scope) => scope.scope)); + + for (const scope of normalizedBackupScopes) { + if (!scopesById.has(scope.scope)) { + scopesById.set(scope.scope, scope); + } + } + + const mergedScopes = Array.from(scopesById.values()); + const nonBackupScopes = mergedScopes.filter( + (scope) => !backupScopeIds.has(scope.scope) + ); + const mergedDatabasesWriteIndex = nonBackupScopes.findIndex( + (s) => s.scope === 'databases.write' + ); + return [ - ...allScopesList.slice(0, databasesWriteIndex + 1), - ...cloudOnlyBackupScopes.map((scope) => ({ - ...scope, - category: normalizeCategory(scope.category) - })), - ...allScopesList.slice(databasesWriteIndex + 1) + ...nonBackupScopes.slice(0, mergedDatabasesWriteIndex + 1), + ...normalizedBackupScopes.map((scope) => scopesById.get(scope.scope) ?? scope), + ...nonBackupScopes.slice(mergedDatabasesWriteIndex + 1) ]; } return allScopesList; @@ -76,12 +95,7 @@ ); }); - const scopeCatalog = $derived( - new Set([ - ...filteredScopes.map((s) => s.scope), - ...(isCloud ? cloudOnlyBackupScopes.map((s) => s.scope) : []) - ]) - ); + const scopeCatalog = $derived(new Set(filteredScopes.map((s) => s.scope))); let activeScopes: Record = $state({}); @@ -206,11 +220,11 @@ on:change={(event) => onCategoryChange(event, category)}> {#each filteredScopes.filter((s) => s.category === category) as scope} - + {#if scope.deprecated} From ce6fdc5a6aaec5d9fa5d2c1f95016decbb0ea3f6 Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Mon, 4 May 2026 11:20:38 +0530 Subject: [PATCH 4/5] Align deprecated badge with scope name --- .../overview/api-keys/scopes.svelte | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte index 826a37324..045c8e7f9 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte @@ -37,7 +37,15 @@ type ScopeDefinition } from '$lib/constants'; import { sdk } from '$lib/stores/sdk'; - import { Accordion, Alert, Badge, Divider, Layout, Selector } from '@appwrite.io/pink-svelte'; + import { + Accordion, + Alert, + Badge, + Divider, + Layout, + Selector, + Typography + } from '@appwrite.io/pink-svelte'; import type { Scopes } from '@appwrite.io/console'; let { scopes = $bindable([]) }: { scopes: Scopes[] } = $props(); @@ -220,16 +228,25 @@ on:change={(event) => onCategoryChange(event, category)}> {#each filteredScopes.filter((s) => s.category === category) as scope} - + - {#if scope.deprecated} - - {/if} + + + + {#if scope.deprecated} + + {/if} + + + {scope.description} + + {/each} @@ -237,3 +254,9 @@ {/each} + + From 52eb56934a3d23965f6d432545a0ba2e2e2b57ed Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Mon, 4 May 2026 12:09:50 +0530 Subject: [PATCH 5/5] Make scope descriptions toggle checkboxes --- .../overview/api-keys/scopes.svelte | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte index 045c8e7f9..1209581be 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte @@ -234,18 +234,29 @@ id={scope.scope} bind:checked={activeScopes[scope.scope]} /> - - - {#if scope.deprecated} - - {/if} - - - {scope.description} - + {/each}