Deploy: VectorsDB + DocumentsDB preview#2931
Conversation
update: move things around.
update: db page to svelte5.
optimize: imports, singular sources of truth.
fix: height issues on mobile.
…preview, metadata defaults
Resolve conflicts keeping documentsdb renames (entityColumnSuggestions, DatabasesIndexType, $database path aliases) while incorporating main's feature flag filters (supportForSpatials, supportForIntegerIds) and getSupportedColumns helper.
Console (appwrite/console)Project ID: Tip Environment variable changes require redeployment to take effect |
WalkthroughThis pull request introduces comprehensive support for multiple database types (TablesDB, DocumentsDB, and VectorsDB) into the console application. The changes include a new JSON5 editor component for NoSQL document management with CodeMirror integration, refactored database abstraction layers to handle multiple entity types uniformly, new collection-scoped routes and layouts, updated type system to support schema-based and non-schema-based databases, and migration of table-specific state to shared entity-level stores. The implementation adds database creation wizards, collection management interfaces, document editing capabilities, and index management alongside existing table functionality. Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 8
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/createPolicy.svelte (2)
237-267:⚠️ Potential issue | 🔴 CriticalFix the daily preset lookup typo.
getPolicyById('dank')always returnsundefined, so toggling this switch will throw whenmarkPolicyCheckedreadspolicy.label.🩹 Minimal fix
- {`@const` dailyPolicy = getPolicyById('dank')} + {`@const` dailyPolicy = getPolicyById('daily')}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/backups/createPolicy.svelte around lines 237 - 267, The daily preset lookup uses the wrong id string in getPolicyById('dank') causing dailyPolicy to be undefined; change the id to the correct preset id (e.g., getPolicyById('daily') or the actual "daily" preset key used by your policy definitions) so dailyPolicy is a valid object before calling markPolicyChecked(event, dailyPolicy) and update any tests or usages that relied on the old typo; the symbols to change are getPolicyById and the dailyPolicy variable in createPolicy.svelte where the switch calls markPolicyChecked.
145-165:⚠️ Potential issue | 🟠 MajorKeep preset ids stable in the reset path.
presetPoliciesis a shared store, and the new flow now relies on fixed ids (getPolicyById('daily' | 'none'),filteredPresetPolicies). Replacing everypolicy.idwithID.unique()here means one visit through the single-policy backups-tab flow can break subsequent renders in the other flows.🩹 Minimal fix
if ($currentPlan?.backupPolicies === 1 && isFromBackupsTab) { presetPolicies.update((all) => all.map((policy) => { - policy.id = ID.unique(); - policy.checked = policy.label === 'Daily'; + policy.checked = policy.id === 'daily'; return policy; }) ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/backups/createPolicy.svelte around lines 145 - 165, The reactive block that runs when isShowing resets presetPolicies and currently reassigns policy.id = ID.unique(), which breaks consumers that expect stable ids (e.g., getPolicyById('daily' | 'none') and filteredPresetPolicies); update the presetPolicies map inside the isShowing branch to only modify policy.checked (and any other non-id fields) without changing policy.id so existing stable ids remain intact, and remove the ID.unique() assignment from that update path; locate the reactive block around isShowing, the resetFormVariables() call, and the presetPolicies.update(...) where policy.id is set and delete or stop changing the id there.src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/indexes.svelte (1)
239-247:⚠️ Potential issue | 🟡 MinorImprove type safety of
SuggestedIndexSchema.typeto prevent unsafe cast.The
typeproperty inSuggestedIndexSchemais defined asstring(line 37 in store.ts), but it's populated exclusively withDatabasesIndexTypeenum values. The cast toTablesDBIndexTypeat line 243 masks this mismatch. While the cast appears safe in the current data flow (suggestions API returnsDatabasesIndexTypevalues), this creates a maintenance risk if enum definitions diverge.Change
SuggestedIndexSchema.typefromstringtoDatabasesIndexTypeto enforce type correctness at the source. This eliminates the unsafe cast and clarifies that indexes come from the suggestions engine which uses the olderDatabasesIndexType.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/indexes.svelte around lines 239 - 247, Update the SuggestedIndexSchema.type declaration from string to DatabasesIndexType in store.ts so the schema accurately reflects the enum values produced by the suggestions engine; then remove the unsafe cast at the createIndex call (where index.type is cast to TablesDBIndexType) and pass the typed value directly or map explicitly if needed, ensuring any code using SuggestedIndexSchema (e.g., the createIndex invocation in indexes.svelte) compiles without a string-to-enum cast and preserves type safety between DatabasesIndexType and TablesDBIndexType.src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/create.svelte (1)
1-9:⚠️ Potential issue | 🟠 MajorChange
typefield inCreateIndexesCallbackTypefromstringtoDatabasesIndexType.The exported callback type currently declares
type: string, but the component passes aDatabasesIndexTypeenum value. This type mismatch forces consumers to cast the value (e.g.,as TablesDBIndexType). Instead, use the enum type directly to maintain type safety and eliminate casting:export type CreateIndexesCallbackType = { key: string; type: DatabasesIndexType; fields: string[]; lengths: (number | null)[]; orders: OrderBy[]; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/create.svelte around lines 1 - 9, Update the CreateIndexesCallbackType so its `type` property uses the DatabasesIndexType enum instead of a plain string: locate the exported type alias CreateIndexesCallbackType in the file and change the `type: string` declaration to `type: DatabasesIndexType` (ensure DatabasesIndexType is imported at the top as it already is); this preserves type-safety and removes the need for downstream casts when passing enum values.
🟡 Minor comments (14)
src/routes/(console)/(migration-wizard)/wizard.svelte-84-84 (1)
84-84:⚠️ Potential issue | 🟡 MinorAlign fallback project name capitalization with the rest of this PR.
Line 84 uses
"New project", while other updated defaults in this PR use"New Project", causing minor UI copy inconsistency.💡 Suggested fix
- return isExisting ? currentSelectedProject.name : newProjName || 'New project'; + return isExisting ? currentSelectedProject.name : newProjName || 'New Project';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/(migration-wizard)/wizard.svelte at line 84, The fallback default string in the return expression "return isExisting ? currentSelectedProject.name : newProjName || 'New project';" is capitalized inconsistently; change the literal 'New project' to 'New Project' so the ternary/OR expression uses the same capitalization as other defaults in this PR (update the string in the expression inside wizard.svelte).src/routes/(console)/project-[region]-[project]/databases/database-[database]/breadcrumbs.svelte-11-18 (1)
11-18:⚠️ Potential issue | 🟡 MinorInconsistent optional chaining may cause runtime error during navigation.
Line 16 uses
organization?.$id(defensive), but line 18 accessesorganization.namedirectly. During page transitions,page.data.organizationcan briefly be undefined, causing a runtime error.🛡️ Proposed fix
{ href: resolveRoute('/(console)/organization-[organization]', { organization: organization?.$id ?? project.teamId }), - title: organization.name + title: organization?.name ?? '' },Based on learnings: "In SvelteKit apps, shared layout components that use
$derived(page.data.*)should use optional chaining when accessing properties that may not be present on all routes. During page transitions, reactive statements can briefly evaluate with different page.data structures."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/breadcrumbs.svelte around lines 11 - 18, The breadcrumb component accesses page.data.organization inconsistently: it uses organization?.$id defensively but reads organization.name directly, which can throw if organization is undefined during transitions; update the title (and any other direct property reads) to use optional chaining and a safe fallback (e.g., organization?.name ?? '') so resolveRoute and the breadcrumb array always handle a missing organization; locate the variable organization and the object literal returned in the breadcrumbs array to apply the change.src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/store.ts-43-49 (1)
43-49:⚠️ Potential issue | 🟡 MinorType inconsistency:
contextinitialized asnullbut typed asstring | undefined.Line 9 declares
context?: string | undefinedbut line 45 initializes it asnull. Similarly, line 47 initializesentityasnullbut the type (line 12-15) uses optional field syntax withoutnull.🔧 Suggested fix
export const entityColumnSuggestions = writable<EntityColumnSuggestions>({ enabled: false, - context: null, + context: undefined, thinking: false, - entity: null, + entity: undefined, force: false });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/store.ts around lines 43 - 49, The EntityColumnSuggestions initial state uses null for context and entity but the type definition for EntityColumnSuggestions declares context?: string | undefined and entity as optional (no null); update either the type or the initial value to match: change the initial store value in entityColumnSuggestions to use undefined (omit context/entity or set them to undefined) or modify the EntityColumnSuggestions type to allow null (e.g., context: string | undefined | null and entity: <type> | null) so the declared types and the initial values are consistent.src/lib/elements/forms/inputTags.svelte-31-47 (1)
31-47:⚠️ Potential issue | 🟡 MinorPotential error state conflict between reactive blocks.
The reactive block at lines 43-47 unconditionally sets
error = nullwhentags.length <= max, which will clear errors set byhandleInvalid(e.g., "This field is required"). This could hide validation errors when the user hasn't exceeded the max limit.Consider preserving the existing error state when max validation passes:
🐛 Proposed fix
$: if (max !== undefined && tags.length > max) { error = `Maximum ${max} fields allowed`; -} else if (max === undefined || tags.length <= max) { - error = null; +} else if (error === `Maximum ${max} fields allowed`) { + // Only clear the max-related error, preserve other validation errors + error = null; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/elements/forms/inputTags.svelte` around lines 31 - 47, The max-validation reactive block currently unconditionally clears error when tags.length <= max, wiping out other validation messages from handleInvalid; change that block to only clear the max-related error (e.g., compare error to the max message `Maximum ${max} fields allowed` or use a dedicated constant like MAX_ERROR_MSG) and leave any other existing error untouched, so modify the reactive block that references max, tags and error to only set error = null when the current error equals the max error message (or clear/set a separate maxError flag) and otherwise preserve error set by handleInvalid.src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/activity.svelte-27-60 (1)
27-60:⚠️ Potential issue | 🟡 MinorAdd error handling to prevent indefinite loading state.
If
listDocumentLogsorlistRowLogsthrows an error,loadingremainstrueand the user sees a perpetual skeleton. Wrap the API calls in try/catch and ensureloadingis set tofalsein a finally block.🛡️ Proposed fix
async function loadRecordLogs(event?: CustomEvent<number>) { loading = true; if (event) { offset = pageToOffset(event.detail, limit); } const { $databaseId: databaseId, entityId, $id: recordId } = toSupportiveRecord(record); + try { if (terminology.type === 'documentsdb' || terminology.type === 'vectorsdb') { const collectionService = getCollectionService( page.params.region, page.params.project, terminology.type ); recordActivityLogs = await collectionService.listDocumentLogs({ databaseId: databaseId, collectionId: entityId, documentId: recordId, queries: [Query.limit(limit), Query.offset(offset)] }); } else { recordActivityLogs = await sdk .forProject(page.params.region, page.params.project) .tablesDB.listRowLogs({ databaseId: databaseId, tableId: entityId, rowId: recordId, queries: [Query.limit(limit), Query.offset(offset)] }); } + } catch (error) { + recordActivityLogs = null; + } finally { + loading = false; + } - - loading = false; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/activity.svelte around lines 27 - 60, The loadRecordLogs function can leave loading true if listDocumentLogs or listRowLogs throws; wrap the API invocation block in try/catch/finally (around the calls that assign recordActivityLogs) so any thrown error is caught (log or surface it via console/processLogger) and ensure loading = false in the finally block; in the catch set recordActivityLogs to an empty array or a safe fallback and preserve existing offset behavior — locate the logic inside loadRecordLogs where listDocumentLogs and tablesDB.listRowLogs are called and add the try/catch/finally around those calls.src/routes/(console)/project-[region]-[project]/databases/create/+page.svelte-39-40 (1)
39-40:⚠️ Potential issue | 🟡 MinorValidate
typequery parameter against allowed values.The
typequery param is cast toDatabaseTypewithout validation. If a user navigates with an invalid?type=invalid, the UI may behave unexpectedly or show an invalid database type card selected.🛡️ Proposed fix
+ const validTypes: DatabaseType[] = ['tablesdb', 'documentsdb', 'vectorsdb']; const typeFromParams = page.url.searchParams.get('type') ?? (null as DatabaseType); - let type = $state(typeFromParams ?? 'tablesdb') as DatabaseType; + let type = $state<DatabaseType>( + validTypes.includes(typeFromParams as DatabaseType) + ? (typeFromParams as DatabaseType) + : 'tablesdb' + );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/create/+page.svelte around lines 39 - 40, The code currently casts page.url.searchParams.get('type') to DatabaseType without validation; update the logic around typeFromParams and type to validate the query value against the allowed DatabaseType values (e.g., the set of enum/string variants used elsewhere) and only use it if it matches; otherwise fall back to the safe default ('tablesdb'). Locate the symbols typeFromParams and type (and any DatabaseType enum/union) and implement a check (e.g., allowedValues.includes(typeFromParams)) before assigning/casting, ensuring invalid values do not become the selected type.src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/inputs/displayName.svelte-15-15 (1)
15-15:⚠️ Potential issue | 🟡 MinorUnused prop declaration.
The
inModalprop is declared in the type definition but not destructured in the props binding, making it inaccessible.Proposed fix
Either remove from type if unused:
}: { collectionId: string; databaseType: string; - inModal?: boolean; onSuccess?: () => Promise<void> | void;Or add to destructuring if needed:
let { collectionId, databaseType, + inModal = false, onSuccess = null,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/inputs/displayName.svelte at line 15, The type declares an optional prop named inModal but it’s never destructured so the component cannot access it; either remove inModal from the props type if it’s unused, or add it to the component’s props binding (destructure/export it where other props are defined) so the displayName.svelte component can read inModal (e.g., include inModal alongside the existing destructured props or add export let inModal:boolean|undefined).src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/editPermissions.svelte-51-51 (1)
51-51:⚠️ Potential issue | 🟡 MinorTypo: "make suer" → "make sure".
- // TODO: `@itznotabug`, make suer this doesn't trigger or lose spreadsheet scroll state! + // TODO: `@itznotabug`, make sure this doesn't trigger or lose spreadsheet scroll state!🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/editPermissions.svelte at line 51, Fix the typo in the TODO comment in editPermissions.svelte: change "make suer" to "make sure" in the existing comment "// TODO: `@itznotabug`, make suer this doesn't trigger or lose spreadsheet scroll state!" so the comment reads "// TODO: `@itznotabug`, make sure this doesn't trigger or lose spreadsheet scroll state!" to improve readability and correctness.src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/editPermissions.svelte-60-65 (1)
60-65:⚠️ Potential issue | 🟡 MinorType-check the caught error before accessing
.message.The
errorin the catch block is of typeunknown. Accessing.messagedirectly may fail if the error is not an Error instance.🛡️ Proposed fix
} catch (error) { + const message = error instanceof Error ? error.message : String(error); addNotification({ - message: error.message, + message, type: 'error' }); trackError(error, analytics.submit.record('UpdatePermissions'));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/editPermissions.svelte around lines 60 - 65, The catch block assumes `error` has a `.message` property; since `error` is `unknown` you should type-check it before accessing `.message` — update the `catch (error)` handling in the `editPermissions.svelte` code to first check `if (error instanceof Error)` and use `error.message` for `addNotification` and pass the `Error` to `trackError`; otherwise convert the unknown to a string (e.g., `String(error)` or a fallback message) for `addNotification` and call `trackError` with a safe wrapper or metadata so code using `analytics.submit.record('UpdatePermissions')` and `trackError(error, ...)` always receives a valid value.src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/editPermissions.svelte-25-25 (1)
25-25:⚠️ Potential issue | 🟡 MinorPermissions state won't update if
recordprop changes.The
permissionsstate is initialized once fromrecord.$permissionsbut won't react if therecordprop changes. If this component is reused with different records without remounting, stale permissions will be displayed.🔧 Proposed fix using $derived or $effect
If the component should react to record changes:
- let permissions = $state(record.$permissions); + let permissions = $state<string[]>([]); + + $effect(() => { + permissions = [...record.$permissions]; + });Alternatively, if the component is always remounted when record changes, this can be left as-is but should be documented.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/editPermissions.svelte at line 25, The permissions variable is initialized once from record.$permissions (let permissions = $state(record.$permissions)) and will not update when the record prop changes; change this to a reactive binding so permissions tracks record updates — e.g. replace the one-time init with a reactive statement or derived/effect that reassigns permissions when record or record.$permissions changes (reference variables: permissions, record, record.$permissions, $state) so the component shows fresh permissions whenever record changes.src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte-48-48 (1)
48-48:⚠️ Potential issue | 🟡 MinorType annotation mismatch.
columnsErroris typed asstringbut initialized tonull. Usestring | nullfor correctness.✏️ Proposed fix
- let columnsError: string = $state(null); + let columnsError: string | null = $state(null);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte at line 48, columnsError is declared as string but initialized with null; update its type to allow null by changing the annotation on columnsError to string | null so the initialization with $state(null) is type-correct (i.e., modify the declaration of columnsError to use string | null while keeping the $state(null) initializer).src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.svelte-71-73 (1)
71-73:⚠️ Potential issue | 🟡 MinorRemove debug console.log statement.
This
console.logappears to be a debug artifact that should be removed before merging.🧹 Proposed fix
async function onSelect(file: Models.File, localFile = false) { $isCollectionsJsonImportInProgress = true; - console.log(file, localFile); - try {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.svelte around lines 71 - 73, Remove the stray debug console.log statement from this Svelte route component (search for any console.log in the file, e.g., near the export let data: PageData declaration or inside onMount/ lifecycle code) — delete the console.log line(s) entirely (do not leave commented-out logs) and run the build/linter to confirm no unused variables or warnings remain.src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/store.ts-9-9 (1)
9-9:⚠️ Potential issue | 🟡 MinorPotential runtime error if
collection.indexesis undefined.The derived store directly accesses
$page.data.collection.indexeswithout defensive checks. Ifcollectionorindexesis undefined during navigation, this could throw.🛡️ Add defensive access
-export const indexes = derived(page, ($page) => $page.data.collection.indexes as Models.Index[]); +export const indexes = derived(page, ($page) => ($page.data.collection?.indexes ?? []) as Models.Index[]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/store.ts at line 9, The derived store exported as indexes currently dereferences $page.data.collection.indexes directly which can throw if collection or indexes is undefined; change the derived callback in the indexes export to defensively access the path (use optional chaining on $page.data.collection?.indexes and default to an empty array) and still cast to Models.Index[] so the store always yields a safe array even during navigation or loading.src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/view.svelte-1536-1543 (1)
1536-1543:⚠️ Potential issue | 🟡 MinorMutating a prop directly may cause unexpected behavior.
Line 1541 assigns
showSuggestions = false, butshowSuggestionsis a prop. In Svelte 5, props are not bindable by default, so this mutation won't propagate to the parent. If this is intentional local state, consider using a separate state variable.🔧 Use local state instead of mutating prop
+ let localShowSuggestions = $state(showSuggestions); + + // Sync with prop changes + $effect(() => { + localShowSuggestions = showSuggestions; + }); // Then in the template: - {`#if` ($isSmallViewport && showSuggestions) || (showSuggestions && hasStartedEditing)} + {`#if` ($isSmallViewport && localShowSuggestions) || (localShowSuggestions && hasStartedEditing)} <Suggestions - show={showSuggestions} + show={localShowSuggestions} showMock={showMockSuggestions} onMobileClick={() => { - showSuggestions = false; + localShowSuggestions = false; applySuggestedAttributes(); }} />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/view.svelte around lines 1536 - 1543, The code currently mutates the prop showSuggestions inside the Suggestions onMobileClick handler (showSuggestions = false), which won't propagate in Svelte 5; instead create local state or emit an event: either introduce a local boolean (e.g., isSuggestionsVisible) initialized from the prop showSuggestions and use that in the {`#if` ...} and set isSuggestionsVisible = false in the onMobileClick before calling applySuggestedAttributes(), or use createEventDispatcher in this component to dispatch a "closeSuggestions" (or similar) event from the Suggestions onMobileClick handler so the parent can update its showSuggestions prop; update references to showSuggestions in this file (the {`#if` ...} and the Suggestions show= prop) to use the chosen local variable or to rely on the dispatched event accordingly and keep applySuggestedAttributes() call intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 07a98a7d-f426-4cb6-9729-5219f9cbc9a9
⛔ Files ignored due to path filters (14)
bun.lockis excluded by!**/*.locksrc/routes/(console)/project-[region]-[project]/databases/(assets)/dark/documents-db.svgis excluded by!**/*.svgsrc/routes/(console)/project-[region]-[project]/databases/(assets)/dark/mongo-db.svgis excluded by!**/*.svgsrc/routes/(console)/project-[region]-[project]/databases/(assets)/dark/tables-db.svgis excluded by!**/*.svgsrc/routes/(console)/project-[region]-[project]/databases/(assets)/dark/vectors-db.svgis excluded by!**/*.svgsrc/routes/(console)/project-[region]-[project]/databases/(assets)/documents-db.svgis excluded by!**/*.svgsrc/routes/(console)/project-[region]-[project]/databases/(assets)/tables-db.svgis excluded by!**/*.svgsrc/routes/(console)/project-[region]-[project]/databases/(assets)/vectors-db.svgis excluded by!**/*.svgstatic/images/databases/empty-documentsdb-dark.svgis excluded by!**/*.svgstatic/images/databases/empty-documentsdb-light.svgis excluded by!**/*.svgstatic/images/databases/empty-tablesdb-dark.svgis excluded by!**/*.svgstatic/images/databases/empty-tablesdb-light.svgis excluded by!**/*.svgstatic/images/databases/empty-vectorsdb-dark.svgis excluded by!**/*.svgstatic/images/databases/empty-vectorsdb-light.svgis excluded by!**/*.svg
📒 Files selected for processing (148)
bugs.mdeslint.config.jspackage.jsonsrc/lib/actions/analytics.tssrc/lib/commandCenter/commands.tssrc/lib/components/columnSelector.sveltesrc/lib/components/csvImportBox.sveltesrc/lib/components/customId.sveltesrc/lib/components/filters/content.sveltesrc/lib/components/filters/filters.sveltesrc/lib/components/id.sveltesrc/lib/components/modal.sveltesrc/lib/components/sortButton.sveltesrc/lib/components/viewSelector.sveltesrc/lib/constants.tssrc/lib/elements/forms/Seekbar.sveltesrc/lib/elements/forms/inputId.sveltesrc/lib/elements/forms/inputProjectId.sveltesrc/lib/elements/forms/inputTags.sveltesrc/lib/helpers/faker.tssrc/lib/helpers/object.tssrc/lib/helpers/search.tssrc/lib/helpers/types.tssrc/lib/helpers/unsavedChanges.tssrc/lib/layout/footer.sveltesrc/lib/layout/progress.sveltesrc/lib/stores/migration.tssrc/lib/stores/navigation.tssrc/lib/stores/preferences.tssrc/lib/stores/sdk.tssrc/lib/stores/viewport.tssrc/routes/(console)/(migration-wizard)/resource-form.sveltesrc/routes/(console)/(migration-wizard)/wizard.sveltesrc/routes/(console)/onboarding/create-project/+page.sveltesrc/routes/(console)/organization-[organization]/change-plan/+page.sveltesrc/routes/(console)/project-[region]-[project]/+layout.sveltesrc/routes/(console)/project-[region]-[project]/auth/+layout.sveltesrc/routes/(console)/project-[region]-[project]/auth/user-[user]/deleteUser.sveltesrc/routes/(console)/project-[region]-[project]/databases/+layout.sveltesrc/routes/(console)/project-[region]-[project]/databases/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/create.sveltesrc/routes/(console)/project-[region]-[project]/databases/create/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/create/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/index.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/init.svelte.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/navigation.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/sdk.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/types.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/create.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/activity.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/editPermissions.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/field/index.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/header.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/create.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/view.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/layouts/empty.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/layouts/index.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/layouts/sheetOptions.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/layouts/sidesheet.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/layouts/spreadsheet.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/settings/danger.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(observer)/columnObserver.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/columns.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/indexes.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/input.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/+layout.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/+layout.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/[...rest]/+page.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/createPolicy.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/breadcrumbs.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/embeddingModal.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/extensions/duplicates.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/extensions/highlighting.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/extensions/hover.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/extensions/index.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/extensions/readonly.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/helpers/constants.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/helpers/errorMessages.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/helpers/keymaps.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/helpers/theme.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/index.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/editor/view.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/inputs/displayName.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/error.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/icons/CheckCircleDuotone.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/index.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/save.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/suggestions.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+layout.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+layout.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/activity/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/activity/+page.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/header.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/settings/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/settings/displayName.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/header.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/settings/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/createColumnDropdown.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/deleteColumn.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/edit.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/createColumn.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/cell/edit.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/columns/columnForm.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/columns/columnItem.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/create.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/edit.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/editRelated.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/sheetOptions.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.sveltesrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.tssrc/routes/(console)/project-[region]-[project]/databases/database-[database]/table.sveltesrc/routes/(console)/project-[region]-[project]/databases/empty.sveltesrc/routes/(console)/project-[region]-[project]/databases/grid.sveltesrc/routes/(console)/project-[region]-[project]/databases/store.tssrc/routes/(console)/project-[region]-[project]/databases/table.sveltesrc/routes/(console)/project-[region]-[project]/functions/+page.sveltesrc/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.sveltesrc/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/executeFunction.sveltesrc/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.sveltesrc/routes/(console)/project-[region]-[project]/settings/+page.sveltesrc/routes/(console)/project-[region]-[project]/settings/migrations/(import)/wizard.sveltesrc/routes/(console)/project-[region]-[project]/settings/updateLabels.sveltesrc/routes/(console)/project-[region]-[project]/updateVariables.sveltesrc/routes/(console)/verify-email/+page.sveltesrc/themes/dark-cloud.jsonsrc/themes/dark.jsonsrc/themes/light-cloud.jsonsrc/themes/light.json
💤 Files with no reviewable changes (1)
- src/routes/(console)/project-[region]-[project]/databases/create.svelte
| // `databaseType` fallback for legacy cases. | ||
| deleteEntityDetails: async ( | ||
| orgId: string, | ||
| entityId: string, | ||
| databaseType: string = 'tables' | ||
| ) => { | ||
| // remove from account preferences | ||
| const removeCustomTableColumns = updateAndSync((n) => { | ||
| n = ensureObjectProperty(n, 'tables'); | ||
| delete n.tables[tableId]; | ||
| n = ensureObjectProperty(n, databaseType); | ||
| delete n.tables[entityId]; | ||
| return n; | ||
| }); |
There was a problem hiding this comment.
Bug: databaseType parameter ignored when deleting from tables.
The deleteEntityDetails function accepts a databaseType parameter but hardcodes 'tables' on line 229 when deleting custom table columns. This means collections/vectors entities won't be properly cleaned up.
🐛 Proposed fix
// remove from account preferences
const removeCustomTableColumns = updateAndSync((n) => {
n = ensureObjectProperty(n, databaseType);
- delete n.tables[entityId];
+ delete n[databaseType][entityId];
return n;
});📝 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.
| // `databaseType` fallback for legacy cases. | |
| deleteEntityDetails: async ( | |
| orgId: string, | |
| entityId: string, | |
| databaseType: string = 'tables' | |
| ) => { | |
| // remove from account preferences | |
| const removeCustomTableColumns = updateAndSync((n) => { | |
| n = ensureObjectProperty(n, 'tables'); | |
| delete n.tables[tableId]; | |
| n = ensureObjectProperty(n, databaseType); | |
| delete n.tables[entityId]; | |
| return n; | |
| }); | |
| // `databaseType` fallback for legacy cases. | |
| deleteEntityDetails: async ( | |
| orgId: string, | |
| entityId: string, | |
| databaseType: string = 'tables' | |
| ) => { | |
| // remove from account preferences | |
| const removeCustomTableColumns = updateAndSync((n) => { | |
| n = ensureObjectProperty(n, databaseType); | |
| delete n[databaseType][entityId]; | |
| return n; | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lib/stores/preferences.ts` around lines 220 - 231, In
deleteEntityDetails, the databaseType parameter is ignored because the code
deletes from the hardcoded n.tables; change the logic to use the databaseType
variable throughout: call ensureObjectProperty(n, databaseType) and delete the
entity via delete n[databaseType][entityId] (instead of delete
n.tables[entityId]) so collections/vectors are cleaned up; update any related
closure (removeCustomTableColumns) name or comments if needed to reflect the
generic databaseType usage.
| <EmptyDatabaseCloud | ||
| disabled={$canWriteDatabases} | ||
| onDatabaseTypeSelected={async (type) => { | ||
| await goto( | ||
| withPath( | ||
| resolveRoute( | ||
| '/(console)/project-[region]-[project]/databases/create', | ||
| page.params | ||
| ), | ||
| `?type=${type}` | ||
| ) | ||
| ); | ||
| }} /> |
There was a problem hiding this comment.
Inverted disabled prop logic.
The disabled prop is set to $canWriteDatabases, which is true when the user can write. This would disable the component when the user has permissions, which is the opposite of intended behavior.
Proposed fix
<EmptyDatabaseCloud
- disabled={$canWriteDatabases}
+ disabled={!$canWriteDatabases}
onDatabaseTypeSelected={async (type) => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/routes/`(console)/project-[region]-[project]/databases/+page.svelte
around lines 77 - 89, The EmptyDatabaseCloud component is being disabled
incorrectly because the disabled prop is bound to $canWriteDatabases (true when
the user can write); invert this logic so the component is disabled only when
the user cannot write. Update the disabled prop on EmptyDatabaseCloud to use the
negation of $canWriteDatabases (i.e., disabled={!$canWriteDatabases}) while
leaving the onDatabaseTypeSelected handler (the async function calling goto with
withPath(resolveRoute(...), `?type=${type}`)) unchanged.
| let selectedPolicyGroup: null | string = null; | ||
| $: if (selectedPolicyGroup) { | ||
| if (selectedPolicyGroup === 'custom') { | ||
| if (listOfCustomPolicies.length === 0) { | ||
| showCustomPolicy = true; | ||
| } | ||
|
|
||
| presetPolicies.update((policies) => { | ||
| return policies.map((policy) => ({ | ||
| ...policy, | ||
| checked: false | ||
| })); | ||
| }); | ||
| } else if (selectedPolicyGroup !== 'custom') { | ||
| listOfCustomPolicies = []; | ||
| showCustomPolicy = false; | ||
|
|
||
| presetPolicies.update((policies) => { | ||
| return policies.map((policy) => ({ | ||
| ...policy, | ||
| checked: selectedPolicyGroup !== 'none' && policy.id === selectedPolicyGroup | ||
| })); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Leaving custom should also clear the edit session.
If a user starts editing a custom policy and then clicks daily or none, this block clears listOfCustomPolicies but leaves policyInEdit and policyBeingEdited alive. The editor stays open, and Save/Cancel can re-add the custom policy alongside the preset, so the supposedly exclusive selector ends up submitting both.
🩹 Minimal fix
} else if (selectedPolicyGroup !== 'custom') {
listOfCustomPolicies = [];
showCustomPolicy = false;
+ policyInEdit = null;
+ policyBeingEdited = null;
presetPolicies.update((policies) => {
return policies.map((policy) => ({📝 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.
| let selectedPolicyGroup: null | string = null; | |
| $: if (selectedPolicyGroup) { | |
| if (selectedPolicyGroup === 'custom') { | |
| if (listOfCustomPolicies.length === 0) { | |
| showCustomPolicy = true; | |
| } | |
| presetPolicies.update((policies) => { | |
| return policies.map((policy) => ({ | |
| ...policy, | |
| checked: false | |
| })); | |
| }); | |
| } else if (selectedPolicyGroup !== 'custom') { | |
| listOfCustomPolicies = []; | |
| showCustomPolicy = false; | |
| presetPolicies.update((policies) => { | |
| return policies.map((policy) => ({ | |
| ...policy, | |
| checked: selectedPolicyGroup !== 'none' && policy.id === selectedPolicyGroup | |
| })); | |
| }); | |
| } | |
| let selectedPolicyGroup: null | string = null; | |
| $: if (selectedPolicyGroup) { | |
| if (selectedPolicyGroup === 'custom') { | |
| if (listOfCustomPolicies.length === 0) { | |
| showCustomPolicy = true; | |
| } | |
| presetPolicies.update((policies) => { | |
| return policies.map((policy) => ({ | |
| ...policy, | |
| checked: false | |
| })); | |
| }); | |
| } else if (selectedPolicyGroup !== 'custom') { | |
| listOfCustomPolicies = []; | |
| showCustomPolicy = false; | |
| policyInEdit = null; | |
| policyBeingEdited = null; | |
| presetPolicies.update((policies) => { | |
| return policies.map((policy) => ({ | |
| ...policy, | |
| checked: selectedPolicyGroup !== 'none' && policy.id === selectedPolicyGroup | |
| })); | |
| }); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/backups/createPolicy.svelte
around lines 183 - 206, When selectedPolicyGroup changes away from 'custom' you
need to fully clear the custom editing session; in the branch where
selectedPolicyGroup !== 'custom' (the same block that sets listOfCustomPolicies
= [] and showCustomPolicy = false and updates presetPolicies) also reset the
editor state by clearing policyInEdit and policyBeingEdited (set them to
null/false as used in this file) so the custom editor closes and no pending edit
can re-add a custom policy.
| {@const none = getPolicyById('none')} | ||
| {@const dailPreset = getPolicyById('daily')} | ||
| <Card.Selector | ||
| variant="secondary" | ||
| imageRadius="s" | ||
| id={dailPreset.id} | ||
| name={dailPreset.id} | ||
| value={dailPreset.id} | ||
| title="Backup every 24 hours" | ||
| bind:group={selectedPolicyGroup}> | ||
| One backup every 24 hours, retained for 30 days | ||
| </Card.Selector> |
There was a problem hiding this comment.
The card copy does not match the preset being submitted.
This selector binds the daily preset, but the description says it is retained for 30 days while presetPolicies defines that preset as 7 days. Users will choose a 7-day policy after reading 30-day copy.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/backups/createPolicy.svelte
around lines 302 - 313, The Card.Selector for the daily preset (dailPreset from
getPolicyById('daily')) has copy saying "retained for 30 days" which conflicts
with the actual presetPolicies retention (7 days); update the selector text to
match the actual preset retention (e.g., "One backup every 24 hours, retained
for 7 days") or, if the intent was 30 days, change the bound preset id from
'daily' to the correct preset id that has 30-day retention—ensure the
description in the Card.Selector and the preset referenced by
getPolicyById('daily') stay consistent.
| let { | ||
| state = null, | ||
| onUndo = null | ||
| }: { | ||
| state: 'saving' | 'saved' | null; | ||
| onUndo?: () => Promise<void> | void; | ||
| } = $props(); |
There was a problem hiding this comment.
state prop should be $bindable() if mutated internally.
The component mutates state on line 29, but state is not declared with $bindable(). In Svelte 5, props are readonly by default. This will cause a runtime error when the effect tries to set state = null.
🔧 Proposed fix
let {
- state = null,
+ state = $bindable(null),
onUndo = null
}: {
state: 'saving' | 'saved' | null;
onUndo?: () => Promise<void> | void;
} = $props();📝 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.
| let { | |
| state = null, | |
| onUndo = null | |
| }: { | |
| state: 'saving' | 'saved' | null; | |
| onUndo?: () => Promise<void> | void; | |
| } = $props(); | |
| let { | |
| state = $bindable(null), | |
| onUndo = null | |
| }: { | |
| state: 'saving' | 'saved' | null; | |
| onUndo?: () => Promise<void> | void; | |
| } = $props(); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/save.svelte
around lines 15 - 21, The prop "state" is mutated internally (see assignment to
state in the save component), so change its declaration to use Svelte 5 binding
by making state $bindable() in the props destructure; update the existing let {
state = null, onUndo = null } ... = $props() to wrap the initial value with
$bindable (so the component can assign to state), keeping the same type union
'saving' | 'saved' | null and leaving onUndo unchanged.
| export function buildInitDoc() { | ||
| const now = new Date().toISOString(); | ||
| return { | ||
| $id: ID.unique(), | ||
| $createdAt: toLocaleDateTime(now), | ||
| $updatedAt: toLocaleDateTime(now) | ||
| }; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check how toLocaleDateTime is used and what format it returns
rg -n "toLocaleDateTime" --type ts -A 2 -B 2 | head -40Repository: appwrite/console
Length of output: 2185
🏁 Script executed:
# Get the implementation of toLocaleDateTime
cat -n src/lib/helpers/date.ts | sed -n '38,60p'Repository: appwrite/console
Length of output: 825
🏁 Script executed:
# Get the test cases to understand expected behavior
cat -n src/lib/helpers/date.test.ts | sed -n '1,50p'Repository: appwrite/console
Length of output: 1730
🏁 Script executed:
# Check the full buildInitDoc function context in the target file
cat -n "src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+layout.svelte" | sed -n '1,30p'Repository: appwrite/console
Length of output: 1384
🏁 Script executed:
# Find where buildInitDoc is called
rg -n "buildInitDoc" --type ts --type svelte -B 3 -A 5Repository: appwrite/console
Length of output: 90
🏁 Script executed:
# Also check what $createdAt and $updatedAt should be in Appwrite
rg -n "\$createdAt|\$updatedAt" --type ts --type svelte | head -30Repository: appwrite/console
Length of output: 90
🏁 Script executed:
# Search for buildInitDoc usage without file type restriction
rg -n "buildInitDoc" -B 3 -A 5Repository: appwrite/console
Length of output: 8796
🏁 Script executed:
# Check Appwrite SDK types for document metadata fields
rg -n "createdAt|updatedAt" --type ts | grep -E "(type|interface|Document)" | head -20Repository: appwrite/console
Length of output: 2658
Remove toLocaleDateTime() conversion in buildInitDoc()—return ISO 8601 strings instead.
The function converts the ISO timestamp to a display format ('Nov 15, 2022, 08:26'), but Appwrite document metadata fields ($createdAt, $updatedAt) expect ISO 8601 strings. This will cause document creation to fail or produce malformed timestamps.
Replace toLocaleDateTime(now) with now directly:
Fix
export function buildInitDoc() {
const now = new Date().toISOString();
return {
$id: ID.unique(),
$createdAt: now,
$updatedAt: now
};
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+layout.svelte
around lines 11 - 18, The buildInitDoc() function is converting the ISO
timestamp via toLocaleDateTime() which produces a display format incompatible
with Appwrite's metadata; change buildInitDoc() so $createdAt and $updatedAt
receive the raw ISO string (the now variable) instead of toLocaleDateTime(now).
Locate buildInitDoc, remove calls to toLocaleDateTime for $createdAt and
$updatedAt and assign now (created by new Date().toISOString()) directly while
keeping $id generated by ID.unique().
| onSuccess={async () => { | ||
| await invalidate(Dependencies.TEAM); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check what dependency other collection settings invalidate
rg -n "invalidate\(Dependencies\." --type=svelte -g '**/collection-*/**' -C2Repository: appwrite/console
Length of output: 90
🏁 Script executed:
cat -n src/routes/\(console\)/project-\[region\]-\[project\]/databases/database-\[database\]/collection-\[collection\]/settings/displayName.svelteRepository: appwrite/console
Length of output: 2488
🏁 Script executed:
# Search for invalidate patterns in collection settings without file type restriction
rg -n "invalidate\(Dependencies\." src/routes -A1 -B1 | grep -A2 -B2 "collection"Repository: appwrite/console
Length of output: 4245
🏁 Script executed:
# Look for other collection settings pages and their invalidation patterns
fd "settings" src/routes -t f | grep collectionRepository: appwrite/console
Length of output: 42
🏁 Script executed:
# Find other settings pages within collections
fd "settings" src/routes -t f -path "*collection-*" | head -20Repository: appwrite/console
Length of output: 228
🏁 Script executed:
# Check what Dependencies.TEAM is used for
rg "Dependencies\.TEAM" src/routes --type=svelte -B2 -A2 | head -40Repository: appwrite/console
Length of output: 90
🏁 Script executed:
# Verify the Dependencies enum definition
fd "constants" src -t f | xargs grep -l "Dependencies" 2>/dev/nullRepository: appwrite/console
Length of output: 80
🏁 Script executed:
# Read the Dependencies enum definition
cat -n src/lib/constants.ts | grep -A50 "Dependencies"Repository: appwrite/console
Length of output: 2468
🏁 Script executed:
# Find settings pages in collection directories
find src/routes -path "*collection-*" -name "*.svelte" | grep settingsRepository: appwrite/console
Length of output: 313
🏁 Script executed:
# Check Dependencies.TEAM usage without file type
rg "Dependencies\.TEAM" src/routes -B2 -A2 | head -60Repository: appwrite/console
Length of output: 4647
Change Dependencies.TEAM to Dependencies.COLLECTION on line 32.
Collection display name updates should invalidate the collection dependency, not the team dependency. Additionally, line 49 has inverted button logic: disabled={columnDisplayNameInput?.hasChanged()} disables the button when changes exist, but should disable it when no changes exist: disabled={!columnDisplayNameInput?.hasChanged()}.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/settings/displayName.svelte
around lines 31 - 32, Replace the invalidated dependency in the onSuccess
callback from Dependencies.TEAM to Dependencies.COLLECTION so collection display
name changes trigger collection cache invalidation (look for the onSuccess
handler that calls invalidate(Dependencies.TEAM)); also invert the button
disabled logic on the save/cancel button that uses
columnDisplayNameInput?.hasChanged() so it is disabled when there are no changes
(change disabled={columnDisplayNameInput?.hasChanged()} to
disabled={!columnDisplayNameInput?.hasChanged()}), ensuring the UI only enables
the action when the input has actually changed.
| </svelte:fragment> | ||
|
|
||
| <svelte:fragment slot="actions"> | ||
| <Button disabled={columnDisplayNameInput?.hasChanged()} submit>Update</Button> |
There was a problem hiding this comment.
Button disabled logic appears inverted.
The button is disabled when columnDisplayNameInput?.hasChanged() returns true. Typically, an "Update" button should be disabled when there are no changes (i.e., hasChanged() returns false), and enabled when there are changes.
🐛 Proposed fix
- <Button disabled={columnDisplayNameInput?.hasChanged()} submit>Update</Button>
+ <Button disabled={!columnDisplayNameInput?.hasChanged()} submit>Update</Button>📝 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.
| <Button disabled={columnDisplayNameInput?.hasChanged()} submit>Update</Button> | |
| <Button disabled={!columnDisplayNameInput?.hasChanged()} submit>Update</Button> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/routes/`(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/settings/displayName.svelte
at line 49, The Update Button's disabled prop is inverted: change the logic in
the Button component that currently uses columnDisplayNameInput?.hasChanged() so
the button is disabled when there are no changes and enabled when there are
changes; replace the condition with the negation (i.e., use
!columnDisplayNameInput?.hasChanged()) so that Update is disabled when
hasChanged() is false and enabled when hasChanged() is true, referring to the
Button element and the columnDisplayNameInput?.hasChanged() call to locate the
fix.

Preview deployment branch for VectorsDB and DocumentsDB features.
Do not merge — this branch is for deployment and testing only.
Summary by CodeRabbit
New Features
Improvements