Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@
scopes: ($func.scopes as Scopes[]) || undefined,
installationId: $installation.$id || undefined,
providerRepositoryId: selectedRepository || undefined,
providerBranch: branch || undefined
providerBranch: branch || undefined,
providerSilentMode: $func.providerSilentMode ?? undefined,
providerRootDirectory: $func.providerRootDirectory ?? undefined,
buildSpecification: $func.buildSpecification || undefined
});
}
if (commit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
providerRepositoryId: '',
providerBranch: '',
providerSilentMode: true,
providerRootDirectory: ''
providerRootDirectory: '',
buildSpecification: $func.buildSpecification || undefined
});
await invalidate(Dependencies.FUNCTION);
dispatch('success');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
providerRepositoryId: func.providerRepositoryId || undefined,
providerBranch: selectedBranch,
providerSilentMode: silentMode,
providerRootDirectory: selectedDir
providerRootDirectory: selectedDir,
buildSpecification: func.buildSpecification || undefined
});
await invalidate(Dependencies.FUNCTION);
addNotification({
Expand Down Expand Up @@ -129,7 +130,21 @@
selectedDir !== func?.providerRootDirectory;

async function connect(selectedInstallationId: string, selectedRepository: string) {
let nextBranch = func?.providerBranch ?? 'main';
try {
const branchList = await sdk
.forProject(page.params.region, page.params.project)
.vcs.listRepositoryBranches({
installationId: selectedInstallationId,
providerRepositoryId: selectedRepository
});
const sorted = sortBranches(branchList.branches);
nextBranch =
sorted.find((branch) => branch.name === func?.providerBranch)?.name ??
sorted.find((branch) => branch.name === 'main' || branch.name === 'master')?.name ??
sorted[0]?.name ??
nextBranch;
Comment on lines 132 to +146
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 If listRepositoryBranches throws (network blip, access revoked, empty repo), the catch { return; } at the bottom silently abandons the entire connection — functions.update never runs and the user sees no feedback. Consider wrapping only the branch fetch in its own try/catch so a failure there still allows the connection to proceed with the nextBranch fallback.

Suggested change
async function connect(selectedInstallationId: string, selectedRepository: string) {
let nextBranch = func?.providerBranch ?? 'main';
try {
const branchList = await sdk
.forProject(page.params.region, page.params.project)
.vcs.listRepositoryBranches({
installationId: selectedInstallationId,
providerRepositoryId: selectedRepository
});
const sorted = sortBranches(branchList.branches);
nextBranch =
sorted.find((branch) => branch.name === func?.providerBranch)?.name ??
sorted.find((branch) => branch.name === 'main' || branch.name === 'master')?.name ??
sorted[0]?.name ??
nextBranch;
async function connect(selectedInstallationId: string, selectedRepository: string) {
let nextBranch = func?.providerBranch ?? 'main';
try {
const branchList = await sdk
.forProject(page.params.region, page.params.project)
.vcs.listRepositoryBranches({
installationId: selectedInstallationId,
providerRepositoryId: selectedRepository
}).catch(() => null);
if (branchList) {
const sorted = sortBranches(branchList.branches);
nextBranch =
sorted.find((branch) => branch.name === func?.providerBranch)?.name ??
sorted.find((branch) => branch.name === 'main' || branch.name === 'master')?.name ??
sorted[0]?.name ??
nextBranch;
}


if (!isValueOfStringEnum(Runtime, func.runtime)) {
throw new Error(`Invalid runtime: ${func.runtime}`);
}
Expand All @@ -148,7 +163,10 @@
scopes: (func.scopes as Scopes[]) || undefined,
installationId: selectedInstallationId,
providerRepositoryId: selectedRepository,
providerBranch: 'main'
providerBranch: nextBranch,
providerSilentMode: func.providerSilentMode ?? undefined,
providerRootDirectory: func.providerRootDirectory ?? undefined,
buildSpecification: func.buildSpecification || undefined
});
await invalidate(Dependencies.FUNCTION);
} catch {
Expand Down Expand Up @@ -275,7 +293,7 @@
{#if showSelectRoot}
<SelectRootModal
bind:show={showSelectRoot}
product="sites"
product="functions"
bind:rootDir={selectedDir}
branch={selectedBranch} />
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@
import { isCloud } from '$lib/system';
import { Button } from '$lib/elements/forms';
import { symmetricDifference } from '$lib/helpers/array';
import { cloudOnlyBackupScopes, type ScopeDefinition } from '$lib/constants';
import {
cloudOnlyBackupScopes,
scopes as localScopes,
type ScopeDefinition
} from '$lib/constants';
import { sdk } from '$lib/stores/sdk';
import { Accordion, Alert, Badge, Divider, Layout, Selector } from '@appwrite.io/pink-svelte';
import type { Scopes } from '@appwrite.io/console';
Expand All @@ -41,39 +45,68 @@
let allScopesList: ScopeDefinition[] = $state([]);
let mounted = $state(false);
let loadError: string | null = $state(null);
const effectiveScopes = $derived(getEffectiveScopes(scopes));

const categoryAliasMap: Record<string, string> = {
Database: 'Databases'
};

enum Category {
Project = 'Project',
Auth = 'Auth',
Database = 'Database',
Databases = 'Databases',
Functions = 'Functions',
Messaging = 'Messaging',
Sites = 'Sites',
Storage = 'Storage',
Domains = 'Domains',
Other = 'Other'
}

const categories = [
const categoryOrder = [
Category.Project,
Category.Auth,
Category.Database,
Category.Databases,
Category.Functions,
Category.Storage,
Category.Messaging,
Category.Sites,
Category.Domains,
Category.Other
];

function normalizeCategory(category: string): string {
return categoryAliasMap[category] ?? category;
}

const filteredScopes = $derived.by(() => {
const databasesWriteIndex = allScopesList.findIndex((s) => s.scope === 'databases.write');
if (isCloud && databasesWriteIndex !== -1) {
return [
...allScopesList.slice(0, databasesWriteIndex + 1),
...cloudOnlyBackupScopes,
...cloudOnlyBackupScopes.map((scope) => ({
...scope,
category: normalizeCategory(scope.category)
})),
...allScopesList.slice(databasesWriteIndex + 1)
];
}
return allScopesList;
});
Comment thread
greptile-apps[bot] marked this conversation as resolved.

const categories = $derived.by(() => {
const availableCategories = 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(
new Set([
...filteredScopes.map((s) => s.scope),
Expand All @@ -95,16 +128,29 @@
onMount(async () => {
try {
const result = await sdk.forConsole.console.listProjectScopes();
allScopesList = result.scopes.map((s) => ({
scope: s.$id,
description: s.description,
category: s.category,
deprecated: s.deprecated,
icon: ''
}));
const scopesById = new Map<string, ScopeDefinition>();

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,
description: scope.description,
category: normalizeCategory(scope.category),
deprecated: scope.deprecated,
icon: ''
});
}

allScopesList = Array.from(scopesById.values());

for (const s of filteredScopes) {
activeScopes[s.scope] = scopes.includes(s.scope as Scopes);
activeScopes[s.scope] = effectiveScopes.includes(s.scope);
}
mounted = true;
} catch (e) {
Expand All @@ -129,8 +175,9 @@

function categoryState(category: string, s: string[]): boolean | 'indeterminate' {
const scopesByCategory = filteredScopes.filter((n) => n.category === category);
const scopeSet = new Set(getEffectiveScopes(s));
const activeInCategory = scopesByCategory.filter((scopeItem) =>
s.includes(scopeItem.scope as Scopes)
scopeSet.has(scopeItem.scope)
);

if (activeInCategory.length === 0) {
Expand All @@ -142,7 +189,7 @@
return 'indeterminate';
}

function onCategoryChange(event: CustomEvent<boolean | 'indeterminate'>, category: Category) {
function onCategoryChange(event: CustomEvent<boolean | 'indeterminate'>, category: string) {
const { detail } = event;
if (detail === 'indeterminate') return;
filteredScopes.forEach((s) => {
Expand Down Expand Up @@ -177,7 +224,7 @@
{@const checked = categoryState(category, scopes)}
{@const isLastItem = index === categories.length - 1}
{@const scopesLength = filteredScopes.filter(
(n) => n.category === category && scopes.includes(n.scope as Scopes)
(n) => n.category === category && effectiveScopes.includes(n.scope)
).length}
<Accordion
selectable
Expand Down
Loading