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
146 changes: 75 additions & 71 deletions bun.lock

Large diffs are not rendered by default.

71 changes: 36 additions & 35 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@
"@faker-js/faker": "^9.9.0",
"@plausible-analytics/tracker": "^0.4.4",
"@popperjs/core": "^2.11.8",
"@sentry/sveltekit": "^8.38.0",
"@sentry/sveltekit": "^8.55.1",
"@stripe/stripe-js": "^3.5.0",
"@threlte/core": "^8.3.1",
"@threlte/extras": "^9.7.1",
"ai": "^6.0.67",
"analytics": "^0.8.16",
"@threlte/core": "^8.5.2",
"@threlte/extras": "^9.13.0",
"ai": "^6.0.138",
"analytics": "^0.8.19",
"cron-parser": "^4.9.0",
"dayjs": "^1.11.13",
"dayjs": "^1.11.20",
"deep-equal": "^2.2.3",
"echarts": "^5.6.0",
"flatted": "^3.4.2",
"ignore": "^6.0.2",
"nanoid": "^5.1.5",
"nanoid": "^5.1.7",
"nanotar": "^0.1.1",
"pretty-bytes": "^6.1.1",
"remarkable": "^2.0.1",
Expand All @@ -49,49 +49,50 @@
"tippy.js": "^6.3.7"
},
"devDependencies": {
"@eslint/compat": "^1.3.1",
"@eslint/js": "^9.31.0",
"@eslint/compat": "^1.4.1",
"@eslint/js": "^9.39.4",
"@melt-ui/pp": "^0.3.2",
"@melt-ui/svelte": "^0.86.5",
"@playwright/test": "^1.55.1",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.49.5",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/svelte": "^5.2.8",
"@melt-ui/svelte": "^0.86.6",
"@playwright/test": "^1.58.2",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.55.0",
"@sveltejs/vite-plugin-svelte": "^5.1.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/svelte": "^5.3.1",
"@testing-library/user-event": "^14.6.1",
"@types/deep-equal": "^1.0.4",
"@types/remarkable": "^2.0.8",
"@types/three": "^0.182.0",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"@typescript-eslint/eslint-plugin": "^8.57.2",
"@typescript-eslint/parser": "^8.57.2",
"@vitest/ui": "^3.2.4",
"color": "^5.0.0",
"eslint": "^9.31.0",
"eslint-config-prettier": "^10.1.0",
"eslint-plugin-svelte": "^3.3.3",
"globals": "^16.0.0",
"color": "^5.0.3",
"eslint": "^9.39.4",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-svelte": "^3.16.0",
"globals": "^16.5.0",
"jsdom": "^26.1.0",
"kleur": "^4.1.5",
"prettier": "^3.5.3",
"prettier-plugin-svelte": "^3.3.3",
"sass": "^1.86.0",
"svelte": "^5.25.3",
"svelte-check": "^4.1.5",
"prettier": "^3.8.1",
"prettier-plugin-svelte": "^3.5.1",
"sass": "^1.98.0",
"svelte": "^5.55.0",
"svelte-check": "^4.4.5",
"svelte-preprocess": "^6.0.3",
"svelte-sequential-preprocessor": "^2.0.2",
"tldts": "^7.0.7",
"svelte-sequential-preprocessor": "^2.0.3",
"tldts": "^7.0.27",
"tslib": "^2.8.1",
"typescript": "^5.8.2",
"typescript-eslint": "^8.30.1",
"vite": "^7.0.6",
"typescript": "^5.9.3",
"typescript-eslint": "^8.57.2",
"vite": "^7.3.1",
"vitest": "^3.2.4"
},
"overrides": {
"vite": "npm:rolldown-vite@latest",
"minimatch": "10.2.3",
"immutable": "^5.1.5",
"flatted": "^3.4.2"
"flatted": "^3.4.2",
"picomatch": "^2.3.2"
}
}
3 changes: 1 addition & 2 deletions src/lib/commandCenter/commandCenter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
{
callback: toggleCommandCenter,
keys: ['k'],
ctrl: true,
forceEnable: true
ctrl: true
},
{
label: 'Toggle debug overlay',
Expand Down
5 changes: 4 additions & 1 deletion src/lib/components/navbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import { beforeNavigate } from '$app/navigation';
import { page } from '$app/state';
import type { Models } from '@appwrite.io/console';
import { isProjectBlocked as getIsProjectBlocked } from '$lib/helpers/project';

let showSupport = false;

Expand Down Expand Up @@ -108,6 +109,7 @@
}

$: currentOrg = organizations.find((org) => org.isSelected);
$: isProjectBlocked = getIsProjectBlocked(currentProject);

beforeNavigate(() => (showAccountMenu = false));
</script>
Expand Down Expand Up @@ -137,7 +139,7 @@
size="xs"
variant="secondary"
href={`${base}/project-${currentProject.region}-${currentProject.$id}/get-started`}
>Connect</Button.Anchor>
disabled={isProjectBlocked}>Connect</Button.Anchor>
</div>
{/if}
</div>
Expand Down Expand Up @@ -201,6 +203,7 @@
<Button.Button
variant="text"
aria-label="Toggle Command Center"
disabled={isProjectBlocked}
on:click={toggleCommandCenter}
icon>
<Icon icon={IconSearch} />
Expand Down
5 changes: 5 additions & 0 deletions src/lib/helpers/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { page } from '$app/state';
import { get } from 'svelte/store';
import { sdk } from '$lib/stores/sdk';
import { projectRegion } from '$routes/(console)/project-[region]-[project]/store';
import type { Models } from '@appwrite.io/console';

/**
* Returns the current project ID.
Expand Down Expand Up @@ -42,3 +43,7 @@ export function getProjectEndpoint(): string {

return currentProjectRegion ? `${protocol}//${currentProjectRegion.$id}.${hostname}/v1` : href;
}

export function isProjectBlocked(project: Models.Project | null | undefined): boolean {
return project?.status !== 'paused' && !!project?.blocks?.length;
}
38 changes: 23 additions & 15 deletions src/lib/layout/shell.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import { BillingPlanGroup, type Models } from '@appwrite.io/console';
import { getSidebarState, isInDatabasesRoute, updateSidebarState } from '$lib/helpers/sidebar';
import { isTabletViewport } from '$lib/stores/viewport';
import { isProjectBlocked as getIsProjectBlocked } from '$lib/helpers/project';

export let showHeader = true;
export let showFooter = true;
Expand Down Expand Up @@ -180,7 +181,7 @@
$: shouldRenderSidebar =
!$isNewWizardStatusOpen && showSideNavigation && !$showOnboardingAnimation;
$: hasSidebarSpace = shouldRenderSidebar && !$isTabletViewport && !!selectedProject;

$: isProjectBlocked = getIsProjectBlocked(selectedProject);
$: {
if ($isSidebarOpen) {
yOnMenuOpen = window.scrollY;
Expand Down Expand Up @@ -211,20 +212,22 @@
<Navbar {...navbarProps} bind:sideBarIsOpen={$isSidebarOpen} bind:showAccountMenu />
{/if}

{#if shouldRenderSidebar}
<Sidebar
project={selectedProject}
progressCard={getProgressCard()}
avatar={navbarProps.avatar}
bind:subNavigation
bind:sideBarIsOpen={$isSidebarOpen}
bind:showAccountMenu
bind:state />
{/if}

{#if !$showOnboardingAnimation}
<SideNavigation bind:subNavigation />
{/if}
<div class="shell-sidebar-area" inert={isProjectBlocked || undefined}>
{#if shouldRenderSidebar}
<Sidebar
project={selectedProject}
progressCard={getProgressCard()}
avatar={navbarProps.avatar}
bind:subNavigation
bind:sideBarIsOpen={$isSidebarOpen}
bind:showAccountMenu
bind:state />
{/if}

{#if !$showOnboardingAnimation}
<SideNavigation bind:subNavigation />
{/if}
</div>

<div
class="content"
Expand Down Expand Up @@ -255,6 +258,11 @@
</main>

<style lang="scss">
.shell-sidebar-area {
position: relative;
z-index: 2;
}

.content {
width: 100%;

Expand Down
105 changes: 68 additions & 37 deletions src/routes/(console)/project-[region]-[project]/+error.svelte
Original file line number Diff line number Diff line change
@@ -1,46 +1,77 @@
<script lang="ts">
import { page } from '$app/state';
import { Container } from '$lib/layout';
import { Card, Link, Typography } from '@appwrite.io/pink-svelte';
import { Button } from '$lib/elements/forms';
import { currentPlan, organizationList } from '$lib/stores/organization';
import SupportWizard from '$routes/(console)/supportWizard.svelte';
import { capitalize } from '$lib/helpers/string';
import { currentPlan } from '$lib/stores/organization';
import { wizard } from '$lib/stores/wizard';
import { Badge, Layout, Typography } from '@appwrite.io/pink-svelte';
import type { Models } from '@appwrite.io/console';

function getResource(id: string) {
id = id.replace('/(console)/project-[region]-[project]/', '');
let parts = id.split('/');
const resource = parts[0];

return resource === 'settings' ? 'project' : resource;
function contactSupport() {
wizard.start(SupportWizard);
}

$: allOrgsHavePremiumSupport = $organizationList.teams.every(
(team) => (team as Models.Organization).billingPlanDetails.premiumSupport
);

$: hasPremiumSupport = $currentPlan?.premiumSupport ?? allOrgsHavePremiumSupport ?? false;
</script>

<Container>
{#if page.error.type === 'general_resource_blocked'}
{@const resource = getResource(page.route.id)}
<Card.Base>
<Typography.Title size="s">Your {capitalize(resource)} is paused</Typography.Title>
<p class="text-red-500">
We've detected unusual activity and temporarily paused your {resource}. If you
believe this is a mistake or need urgent access, please contact
{#if $currentPlan?.premiumSupport}
<Link.Button
on:click={() => {
wizard.start(SupportWizard);
}}>support</Link.Button
>.
{:else}
support@appwrite.io.
{/if}
</p>
</Card.Base>
{:else}
<Typography.Title size="xl"
>{'status' in page.error
? page.error.status || 'Invalid Argument'
: 'Invalid Argument'}</Typography.Title>
{#if page.error.type === 'general_resource_blocked'}
<section class="resource-blocked">
<div class="resource-blocked__content">
<Layout.Stack gap="s" alignItems="center">
<Badge type="error" variant="secondary" content="Access blocked" />
<Typography.Title size="l" align="center">
This resource page can&apos;t be accessed. Check your permissions or contact
support for help.
</Typography.Title>
<div class="u-margin-block-start-16">
{#if hasPremiumSupport}
<Button secondary on:click={contactSupport}>Contact support</Button>
{:else}
<Button secondary href="mailto:support@appwrite.io">Contact support</Button>
{/if}
</div>
</Layout.Stack>
</div>
</section>
{:else}
<section class="resource-blocked resource-blocked--default">
<div class="resource-blocked__content">
<Layout.Stack gap="s" alignItems="center">
<Typography.Title size="s" align="center">
{'status' in page.error
? page.error.status || 'Invalid Argument'
: 'Invalid Argument'}
Comment on lines +44 to +47
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

In SvelteKit +error.svelte, is the HTTP status exposed on $app/state's page.statuswhilepage.error only contains the error payload/body?

💡 Result:

Yes, in SvelteKit +error.svelte, the HTTP status is exposed on $app/state's page.status, while page.error contains only the error payload/body (typically { message: string } or extended App.Error object without the status code).

Citations:


Use page.status to display the HTTP error status.

In SvelteKit error routes, the HTTP status is exposed on page.status while page.error contains only the error payload. The current code checks for status in page.error, which never exists, so all error pages will display "Invalid Argument" instead of the actual HTTP status code.

Suggested fix
-                    {'status' in page.error
-                        ? page.error.status || 'Invalid Argument'
-                        : 'Invalid Argument'}
+                    {page.status || 'Invalid Argument'}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Typography.Title size="s" align="center">
{'status' in page.error
? page.error.status || 'Invalid Argument'
: 'Invalid Argument'}
<Typography.Title size="s" align="center">
{page.status || 'Invalid Argument'}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/`(console)/project-[region]-[project]/+error.svelte around lines
44 - 47, The error title currently checks 'status' in page.error (which is
always false) so replace that check to use the SvelteKit-provided page.status;
update the Typography.Title expression that currently references page.error to
instead render page.status (e.g. use page.status ?? 'Invalid Argument' or a
ternary checking page.status) so the actual HTTP status code is shown; modify
the expression near Typography.Title in +error.svelte and remove the 'status' in
page.error conditional.

</Typography.Title>
<p class="u-text-center">{page.error.message}</p>
</Layout.Stack>
</div>
</section>
{/if}

<style>
.resource-blocked {
min-height: calc(100vh - 48px - 2rem);
display: flex;
align-items: center;
justify-content: center;
padding: 4rem 1.5rem;
text-align: center;
}

.resource-blocked__content {
width: min(100%, 33rem);
max-width: 33rem;
}

<Typography.Title>{page.error.message}</Typography.Title>
{/if}
</Container>
.resource-blocked p {
margin: 0;
color: var(--fgcolor-neutral-secondary, #56565c);
font-size: 1rem;
line-height: 1.5;
text-wrap: balance;
}
</style>
Loading
Loading