Skip to content

Commit 902ea0a

Browse files
committed
merge: feat-documentsdb into feat-vectordb
2 parents 995af51 + 76cd63c commit 902ea0a

File tree

22 files changed

+713
-58
lines changed

22 files changed

+713
-58
lines changed

bugs.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# VectorDB Console Bugs
2+
3+
> VectorsDB shares the `collection-[collection]` route with documentsdb -- no separate pages needed.
4+
> The `sdk.ts` abstraction (`useDatabaseSdk`) already handles all three types.
5+
> The `.bind()` ternary in spreadsheet.svelte is intentional -- sdk.ts returns `Record` types but the spreadsheet expects raw `Models.Document`. Refactoring would require touching the entire document pipeline.
6+
7+
## ~~Critical -- Will break vectorsdb in production~~ FIXED
8+
9+
### ~~1. `collection-[collection]/+page.ts` -- listDocuments hardcoded to `documentsDB`~~ FIXED
10+
11+
### ~~2. `collection-[collection]/+page.svelte` -- EmptySheet type hardcoded to `"documentsdb"`~~ FIXED
12+
13+
### ~~3. `empty.svelte` -- vectorsdb gets tablesdb layout~~ FIXED
14+
15+
### ~~4. `empty.svelte` CSS -- no vectorsdb selector~~ FIXED
16+
17+
### ~~5. `empty.svelte` -- index-only check excludes vectorsdb~~ FIXED
18+
19+
---
20+
21+
## ~~Major -- UX bugs~~ FIXED
22+
23+
### ~~6. Keyboard hint hardcodes `Cmd` (macOS only)~~ FIXED
24+
25+
### 7. `Mod-g` conflicts with browser "Find next"
26+
27+
**File:** `editor/view.svelte:1137`
28+
`Cmd+G` / `Ctrl+G` is the standard "Find next" shortcut after `Cmd+F`.
29+
**Status:** Deprioritized -- CodeMirror captures keys when focused, minor edge case.
30+
31+
---
32+
33+
## Minor -- Cleanup / consistency
34+
35+
### 9. `getCollectionService()` type signature too broad
36+
37+
**File:** `(entity)/helpers/sdk.ts:118`
38+
Accepts all `DatabaseType` but only handles `documentsdb` and `vectorsdb`. Calling with `legacy` or `tablesdb` throws at runtime.
39+
**Fix:** Narrow parameter type to `Extract<DatabaseType, 'documentsdb' | 'vectorsdb'>`.
40+
41+
### 10. `create.svelte` -- `dimension` not reset on modal close
42+
43+
**File:** `(entity)/views/create.svelte`
44+
`id` and `name` are reset in `updateAndCleanup()` but `dimension` is not. Reopening the modal after creating a collection with dimension 1536 will still show 1536.
45+
**Fix:** Add `dimension = 768;` to the reset paths.
46+
47+
### 11. `create.svelte` -- No max bound on dimension input
48+
49+
**File:** `(entity)/views/create.svelte`
50+
The `InputNumber` has `min={1}` but no `max`. A user could enter an arbitrarily large value.
51+
**Fix:** Add a sensible `max` (e.g., 16384).
52+
53+
### 12. Magic number `768` repeated
54+
55+
**Files:** `create.svelte:39`, `+layout.svelte:277`
56+
**Fix:** Extract to a constant like `DEFAULT_VECTOR_DIMENSION`.

bun.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121
"dependencies": {
2222
"@ai-sdk/svelte": "^1.1.24",
23-
"@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@f16c734",
23+
"@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@e259e61",
2424
"@appwrite.io/pink-icons": "0.25.0",
2525
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@bfe7ce3",
2626
"@appwrite.io/pink-legacy": "^1.0.3",
@@ -49,6 +49,7 @@
4949
"dayjs": "^1.11.13",
5050
"deep-equal": "^2.2.3",
5151
"echarts": "^5.6.0",
52+
"flatted": "^3.4.2",
5253
"ignore": "^6.0.2",
5354
"json5": "^2.2.3",
5455
"nanoid": "^5.1.5",

src/app.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
sizes="120x120"
2727
href="%sveltekit.assets%/logos/apple-touch-icon-120x120.png" />
2828

29-
<!-- apple web app meta tags -->
30-
<meta name="apple-mobile-web-app-capable" content="yes" />
29+
<!-- web app / standalone display meta tags -->
30+
<meta name="mobile-web-app-capable" content="yes" />
3131
<meta name="apple-mobile-web-app-title" content="Appwrite Console" />
3232
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
3333

src/lib/actions/analytics.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ export enum Submit {
236236
UserUpdatePassword = 'submit_user_update_password',
237237
UserUpdatePhone = 'submit_user_update_phone',
238238
UserUpdateMfa = 'submit_user_update_mfa',
239+
UserUpdateImpersonation = 'submit_user_update_impersonation',
239240
UserUpdatePreferences = 'submit_user_update_preferences',
240241
UserUpdateStatus = 'submit_user_update_status',
241242
UserUpdateVerificationEmail = 'submit_user_update_verification_email',
@@ -329,6 +330,7 @@ export enum Submit {
329330
FunctionUpdateSchedule = 'submit_function_update_schedule',
330331
FunctionUpdateConfiguration = 'submit_function_update_configuration',
331332
FunctionUpdateLogging = 'submit_function_update_logging',
333+
FunctionUpdateResourceLimits = 'submit_function_update_resource_limits',
332334
FunctionUpdateTimeout = 'submit_function_update_timeout',
333335
FunctionUpdateEvents = 'submit_function_update_events',
334336
FunctionUpdateScopes = 'submit_function_key_update_scopes',
@@ -453,6 +455,7 @@ export enum Submit {
453455
SiteUpdateEvents = 'submit_site_update_events',
454456
SiteUpdateScopes = 'submit_site_key_update_scopes',
455457
SiteUpdateBuildSettings = 'submit_site_update_build_settings',
458+
SiteUpdateResourceLimits = 'submit_site_update_resource_limits',
456459
SiteUpdateSinglePageApplication = 'submit_site_update_single_page_application',
457460
SiteConnectRepo = 'submit_site_connect_repo',
458461
SiteRedeploy = 'submit_site_redeploy',

src/lib/stores/sdk.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import {
2424
TablesDB,
2525
Domains,
2626
DocumentsDB,
27+
Webhooks,
2728
Realtime,
2829
Organizations,
29-
VectorsDB,
30-
Webhooks
30+
VectorsDB
3131
} from '@appwrite.io/console';
3232
import { Sources } from '$lib/sdk/sources';
3333
import {

src/routes/(console)/project-[region]-[project]/auth/user-[user]/+page.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import UpdateName from './updateName.svelte';
88
import UpdatePassword from './updatePassword.svelte';
99
import UpdatePhone from './updatePhone.svelte';
10+
import UpdateImpersonation from './updateImpersonation.svelte';
1011
import UpdatePrefs from './updatePrefs.svelte';
1112
import UpdateStatus from './updateStatus.svelte';
1213
import type { PageData } from './$types';
@@ -22,6 +23,7 @@
2223
<UpdatePassword />
2324
<UpdateLabels />
2425
<UpdatePrefs />
26+
<UpdateImpersonation />
2527
<UpdateMfa />
2628
<DangerZone project={data.project} />
2729
</Container>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<script lang="ts">
2+
import { invalidate } from '$app/navigation';
3+
import { page } from '$app/state';
4+
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
5+
import { CardGrid } from '$lib/components';
6+
import { Dependencies } from '$lib/constants';
7+
import { Button, Form } from '$lib/elements/forms';
8+
import { addNotification } from '$lib/stores/notifications';
9+
import { sdk } from '$lib/stores/sdk';
10+
import { Alert, Layout, Link, Selector, Typography } from '@appwrite.io/pink-svelte';
11+
import { onMount } from 'svelte';
12+
import { user } from './store';
13+
14+
let impersonator = false;
15+
16+
$: currentImpersonator = Boolean($user?.impersonator);
17+
18+
onMount(() => {
19+
impersonator = currentImpersonator;
20+
});
21+
22+
async function updateImpersonator() {
23+
try {
24+
await sdk.forProject(page.params.region, page.params.project).users.updateImpersonator({
25+
userId: $user.$id,
26+
impersonator
27+
});
28+
29+
await invalidate(Dependencies.USER);
30+
31+
addNotification({
32+
message: `Impersonation capability has been ${impersonator ? 'enabled' : 'disabled'}`,
33+
type: 'success'
34+
});
35+
trackEvent(Submit.UserUpdateImpersonation);
36+
} catch (error) {
37+
impersonator = currentImpersonator;
38+
39+
addNotification({
40+
message: error.message,
41+
type: 'error'
42+
});
43+
trackError(error, Submit.UserUpdateImpersonation);
44+
}
45+
}
46+
</script>
47+
48+
<Form onSubmit={updateImpersonator}>
49+
<CardGrid>
50+
<svelte:fragment slot="title">User impersonation</svelte:fragment>
51+
<svelte:fragment slot="aside">
52+
<Layout.Stack gap="m">
53+
<Selector.Switch
54+
id="user-impersonation"
55+
bind:checked={impersonator}
56+
label="User impersonation">
57+
<svelte:fragment slot="description">
58+
<div class="u-margin-block-start-8">
59+
<Typography.Text variant="m-400">
60+
Enabling this option allows this user to impersonate other users
61+
through your app using the Appwrite Client SDK.
62+
<Link.Anchor
63+
target="_blank"
64+
rel="noopener noreferrer"
65+
href="https://appwrite.io/docs/products/auth">
66+
Learn more.
67+
</Link.Anchor>
68+
</Typography.Text>
69+
</div>
70+
</svelte:fragment>
71+
</Selector.Switch>
72+
73+
<Alert.Inline status="info">
74+
Only grant this permission to trusted operator or support accounts. Actions are
75+
logged under the account that initiated impersonation.
76+
</Alert.Inline>
77+
</Layout.Stack>
78+
</svelte:fragment>
79+
80+
<svelte:fragment slot="actions">
81+
<Button disabled={impersonator === currentImpersonator} submit>Update</Button>
82+
</svelte:fragment>
83+
</CardGrid>
84+
</Form>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { Page } from '@sveltejs/kit';
2+
import { getContext, setContext } from 'svelte';
3+
import {
4+
type AnalyticsResult,
5+
type DatabaseSdkResult,
6+
type DependenciesResult,
7+
type TerminologyResult,
8+
useAnalytics,
9+
useDependencies,
10+
useTerminology,
11+
useDatabaseSdk
12+
} from '$database/(entity)';
13+
14+
const TERMINOLOGIES_KEY = Symbol('terminologies');
15+
16+
export type Terminologies = {
17+
analytics: AnalyticsResult;
18+
terminology: TerminologyResult;
19+
dependencies: DependenciesResult;
20+
databaseSdk: DatabaseSdkResult;
21+
};
22+
23+
export function getTerminologies(): Terminologies {
24+
return getContext<Terminologies>(TERMINOLOGIES_KEY);
25+
}
26+
27+
export function setTerminologies(page: Page) {
28+
setContext(TERMINOLOGIES_KEY, buildTerminologies(page));
29+
}
30+
31+
function buildTerminologies(page: Page): Terminologies {
32+
const terminology = useTerminology(page);
33+
return {
34+
terminology,
35+
analytics: useAnalytics(terminology),
36+
dependencies: useDependencies(terminology),
37+
databaseSdk: useDatabaseSdk(page, terminology)
38+
};
39+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<script lang="ts">
2+
import { onMount } from 'svelte';
3+
import { page } from '$app/state';
4+
import { sdk } from '$lib/stores/sdk';
5+
import { Activity } from '$lib/layout';
6+
import { rowActivitySheet } from '../store';
7+
import { pageToOffset } from '$lib/helpers/load';
8+
import { type Models, Query } from '@appwrite.io/console';
9+
import { Skeleton } from '@appwrite.io/pink-svelte';
10+
11+
let limit = 25; /* default */
12+
let offset = $state(0);
13+
let loading = $state(true);
14+
let rowActivityLogs = $state<Models.LogList | null>(null);
15+
16+
onMount(loadRowLogs);
17+
18+
async function loadRowLogs(event?: CustomEvent<number>) {
19+
loading = true;
20+
21+
if (event) {
22+
offset = pageToOffset(event.detail, limit);
23+
}
24+
25+
const row = $rowActivitySheet.row;
26+
27+
rowActivityLogs = await sdk
28+
.forProject(page.params.region, page.params.project)
29+
.tablesDB.listRowLogs({
30+
databaseId: row.$databaseId,
31+
tableId: row.$tableId,
32+
rowId: row.$id,
33+
queries: [Query.limit(limit), Query.offset(offset)]
34+
});
35+
36+
loading = false;
37+
}
38+
</script>
39+
40+
{#if loading}
41+
<div style:margin-block="" style:margin-inline-end="2.25rem">
42+
<!--<Skeleton variant="line" height={25} width="25%" />-->
43+
<Skeleton variant="line" height={40} width="auto" />
44+
</div>
45+
{:else if rowActivityLogs}
46+
<div class="row-activity-wrapper">
47+
<Activity
48+
{limit}
49+
{offset}
50+
insideSideSheet
51+
on:page={loadRowLogs}
52+
logs={rowActivityLogs}
53+
useCreateLinkForPagination={false} />
54+
</div>
55+
{/if}
56+
57+
<style lang="scss">
58+
.row-activity-wrapper {
59+
& :global(.console-container) {
60+
margin-inline: unset;
61+
padding-inline-end: unset;
62+
63+
@media (max-width: 768px) {
64+
margin-block: 0.5rem;
65+
}
66+
}
67+
}
68+
</style>

0 commit comments

Comments
 (0)