(refactor): Migrate dedicated databases from custom SDK to compute SDK

This commit is contained in:
Jake Barnby
2026-03-26 17:00:17 +13:00
parent 2e49353837
commit 37fdbd9516
7 changed files with 65 additions and 1066 deletions
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -24,12 +24,12 @@ import {
TablesDB,
Domains,
Webhooks,
/*DocumentsDB,*/
DocumentsDB,
Compute,
Realtime,
Organizations
} from '@appwrite.io/console';
import { Sources } from '$lib/sdk/sources';
import { DedicatedDatabases } from '$lib/sdk/dedicatedDatabases';
import {
REGION_FRA,
REGION_NYC,
@@ -138,8 +138,8 @@ const sdkForProject = {
migrations: new Migrations(clientProject),
sites: new Sites(clientProject),
tablesDB: new TablesDB(clientProject),
/*documentsDB: new DocumentsDB(clientProject),*/
dedicatedDatabases: new DedicatedDatabases(clientProject),
documentsDB: new DocumentsDB(clientProject),
compute: new Compute(clientProject),
console: new Console(clientProject), // for suggestions API
webhooks: new Webhooks(clientProject)
};
@@ -10,13 +10,13 @@ import {
toSupportiveEntity,
toSupportiveRecord
} from './terminology';
import type { Models } from '@appwrite.io/console';
import { Backend, Engine, type Models } from '@appwrite.io/console';
export type DedicatedDatabaseParams = {
databaseId: string;
name: string;
enabled?: boolean;
engine?: 'postgres' | 'mysql' | 'mariadb' | 'mongodb';
engine?: Engine;
region?: string;
tier?: string;
highAvailability?: boolean;
@@ -131,29 +131,28 @@ export function useDatabaseSdk(
return await baseSdk.documentsDB.create(params);
}
case 'shared': {
// Shared (free tier) databases via compute/databases with type: 'shared'
const sharedParams = params as DedicatedDatabaseParams;
return (await baseSdk.dedicatedDatabases.create({
return (await baseSdk.compute.createDatabase({
databaseId: sharedParams.databaseId,
name: sharedParams.name,
backend: 'edge',
engine: 'postgres',
region: sharedParams.region,
type: 'shared'
backend: Backend.Edge,
engine: Engine.Postgres,
region: sharedParams.region as any,
type: 'shared' as any
})) as unknown as Models.Database;
}
case 'dedicated': {
const dedicatedParams = params as DedicatedDatabaseParams;
return (await baseSdk.dedicatedDatabases.create({
return (await baseSdk.compute.createDatabase({
databaseId: dedicatedParams.databaseId,
name: dedicatedParams.name,
backend: 'edge',
backend: Backend.Edge,
engine: dedicatedParams.engine,
region: dedicatedParams.region,
region: dedicatedParams.region as any,
tier: dedicatedParams.tier,
highAvailability: dedicatedParams.highAvailability,
backupEnabled: dedicatedParams.backupEnabled,
backupSchedule: dedicatedParams.backupSchedule,
backupCron: dedicatedParams.backupSchedule,
backupRetentionDays: dedicatedParams.backupRetentionDays,
backupPitr: dedicatedParams.backupPitr,
pitrRetentionDays: dedicatedParams.pitrRetentionDays
@@ -167,20 +166,29 @@ export function useDatabaseSdk(
},
async list(params): Promise<Models.DatabaseList> {
const results = await Promise.all([
baseSdk.tablesDB.list(params)
// not available just yet!
// baseSdk.documentsDB.list(params),
const [tablesResult, dedicatedResult] = await Promise.all([
baseSdk.tablesDB.list(params),
baseSdk.compute.listDatabases({ queries: params.queries, search: params.search })
]);
return results.reduce(
(acc, curr) => ({
total: acc.total + curr.total,
databases: [...acc.databases, ...curr.databases]
}),
{ total: 0, databases: [] as Models.Database[] }
const dedicatedAsDatabases = (dedicatedResult.databases ?? []).map(
(db) =>
({
$id: db.$id,
$createdAt: db.$createdAt,
$updatedAt: db.$updatedAt,
name: db.name,
enabled: true,
type: db.type,
policies: [],
archives: []
}) as unknown as Models.Database
);
return {
total: tablesResult.total + (dedicatedResult.total ?? 0),
databases: [...tablesResult.databases, ...dedicatedAsDatabases]
};
},
async createEntity(params) {
@@ -271,7 +279,7 @@ export function useDatabaseSdk(
return await baseSdk.documentsDB.delete(params);
case 'shared':
case 'dedicated':
await baseSdk.dedicatedDatabases.delete(params);
await baseSdk.compute.deleteDatabase(params);
return {};
case 'vectordb':
throw new Error('Database type not supported yet');
@@ -1,8 +1,8 @@
<script module lang="ts">
import { IndexType, OrderBy } from '@appwrite.io/console';
import { TablesDBIndexType, OrderBy } from '@appwrite.io/console';
export type CreateIndexesCallbackType = {
key: string;
type: IndexType;
type: TablesDBIndexType;
fields: string[];
lengths: (number | null)[];
orders: OrderBy[];
@@ -40,14 +40,14 @@
let key = $state('');
let initializedForOpen = $state(false);
let selectedType = $state<IndexType>(IndexType.Key);
let selectedType = $state<TablesDBIndexType>(TablesDBIndexType.Key);
const { dependencies, terminology } = getTerminologies();
const fieldOptions = $derived(
entity.fields
.filter((field) => {
if (selectedType === IndexType.Spatial) {
if (selectedType === TablesDBIndexType.Spatial) {
// keep only spatial
return isSpatialType(field);
}
@@ -69,12 +69,12 @@
const types = $derived(
[
{ value: IndexType.Key, label: 'Key' },
{ value: IndexType.Unique, label: 'Unique' },
{ value: IndexType.Fulltext, label: 'Fulltext' },
{ value: IndexType.Spatial, label: 'Spatial' }
{ value: TablesDBIndexType.Key, label: 'Key' },
{ value: TablesDBIndexType.Unique, label: 'Unique' },
{ value: TablesDBIndexType.Fulltext, label: 'Fulltext' },
{ value: TablesDBIndexType.Spatial, label: 'Spatial' }
].filter((type) => {
if (type.value === IndexType.Spatial && !$regionalConsoleVariables?.supportForSpatials)
if (type.value === TablesDBIndexType.Spatial && !$regionalConsoleVariables?.supportForSpatials)
return false;
return true;
})
@@ -82,7 +82,7 @@
// order options derived from selected type
let orderOptions = $derived.by(() =>
selectedType === IndexType.Spatial
selectedType === TablesDBIndexType.Spatial
? [
{ value: OrderBy.Asc, label: 'ASC' },
{ value: OrderBy.Desc, label: 'DESC' },
@@ -98,7 +98,7 @@
// and the field already is not spatial type
$effect(() => {
const firstField = entity.fields.find((field) => field.key === fieldList.at(0)?.value);
if (selectedType === IndexType.Spatial && firstField && !isSpatialType(firstField)) {
if (selectedType === TablesDBIndexType.Spatial && firstField && !isSpatialType(firstField)) {
fieldList = [{ value: '', order: null, length: null }];
}
});
@@ -119,7 +119,7 @@
const isSpatial = field.length && isSpatialType(field[0]);
const order = isSpatial ? null : OrderBy.Asc;
selectedType = isSpatial ? IndexType.Spatial : IndexType.Key;
selectedType = isSpatial ? TablesDBIndexType.Spatial : TablesDBIndexType.Key;
fieldList = externalFieldKey
? [{ value: externalFieldKey, order, length: null }]
@@ -129,7 +129,7 @@
}
const addFieldDisabled = $derived(
selectedType === IndexType.Spatial ||
selectedType === TablesDBIndexType.Spatial ||
!fieldList.at(-1)?.value ||
(!fieldList.at(-1)?.order && fieldList.at(-1)?.order !== null)
);
@@ -160,7 +160,7 @@
export async function create() {
const fieldType = terminology.field.lower.singular;
if (!key || !selectedType || (selectedType !== IndexType.Spatial && addFieldDisabled)) {
if (!key || !selectedType || (selectedType !== TablesDBIndexType.Spatial && addFieldDisabled)) {
addNotification({
type: 'error',
message: `Selected ${fieldType} key or type invalid`
@@ -239,7 +239,7 @@
required
options={[
// allow system fields only for non-spatial index types
...(selectedType === IndexType.Spatial
...(selectedType === TablesDBIndexType.Spatial
? []
: [
{ value: '$id', label: '$id', leadingIcon: IconFingerPrint },
@@ -269,7 +269,7 @@
bind:value={field.order}
placeholder="Select order" />
{#if selectedType === IndexType.Key}
{#if selectedType === TablesDBIndexType.Key}
<InputNumber
id={`length-${index}`}
label={index === 0 ? 'Length' : undefined}
@@ -6,7 +6,7 @@
import { Modal } from '$lib/components';
import { type Entity, SideSheet } from '$database/(entity)';
import { isSmallViewport } from '$lib/stores/viewport';
import { IndexType, OrderBy } from '@appwrite.io/console';
import { TablesDBIndexType, OrderBy } from '@appwrite.io/console';
import { capitalize } from '$lib/helpers/string';
import type { Columns } from '$database/store';
import { isRelationship } from '../table-[table]/rows/store';
@@ -68,7 +68,7 @@
indexes = mockSuggestions.columns.slice(0, 3).map((column, index) => ({
key: column.name,
type: IndexType.Key,
type: TablesDBIndexType.Key,
fields: [column.name],
orders: index === 2 ? OrderBy.Desc : OrderBy.Asc,
lengths: []
@@ -85,7 +85,7 @@
indexes = suggestions.indexes.map((index) => {
return {
key: index.columns[0],
type: index.type as IndexType,
type: index.type as TablesDBIndexType,
orders: (index.orders?.[0] as OrderBy) || OrderBy.Asc,
fields: index.columns,
lengths: index.lengths ?? []
@@ -113,7 +113,7 @@
if (indexes.length < MAX_INDEXES) {
indexes.push({
key: '',
type: IndexType.Key,
type: TablesDBIndexType.Key,
orders: OrderBy.Asc,
fields: [],
lengths: null
@@ -134,9 +134,9 @@
}
}
function getOrderOptions(selectedType: IndexType) {
function getOrderOptions(selectedType: TablesDBIndexType) {
const base = [OrderBy.Asc, OrderBy.Desc];
const values = selectedType === IndexType.Spatial ? [...base, null] : base;
const values = selectedType === TablesDBIndexType.Spatial ? [...base, null] : base;
return values.map((order) => ({
label: order ? capitalize(String(order)) : 'None',
@@ -166,7 +166,7 @@
// prepare lengths array
let lengths: (number | null)[];
if (index.type === IndexType.Key) {
if (index.type === TablesDBIndexType.Key) {
// only validate if it's a key index
lengths = index.fields.map((columnKey, i) => {
const maxSize = columnMap.get(columnKey);
@@ -293,9 +293,9 @@
}
const typeOptions = $derived(
Object.values(IndexType)
Object.values(TablesDBIndexType)
.filter((type) => {
if (type === IndexType.Spatial && !$regionalConsoleVariables?.supportForSpatials)
if (type === TablesDBIndexType.Spatial && !$regionalConsoleVariables?.supportForSpatials)
return false;
return true;
})
@@ -1,5 +1,5 @@
import { writable } from 'svelte/store';
import { IndexType, OrderBy } from '@appwrite.io/console';
import { TablesDBIndexType, OrderBy } from '@appwrite.io/console';
import { columnOptions } from '../table-[table]/columns/store';
export type EntityColumnSuggestions = {
@@ -34,7 +34,7 @@ export type IndexOrder = OrderBy | null;
export type SuggestedIndexSchema = {
key: string;
type: IndexType;
type: TablesDBIndexType;
orders: IndexOrder;
fields: string[];
lengths?: number[] | undefined;
@@ -5,7 +5,7 @@
import { IconDuplicate } from '@appwrite.io/pink-icons-svelte';
import { copy } from '$lib/helpers/copy';
import { addNotification } from '$lib/stores/notifications';
import type { DedicatedDatabase } from '$lib/sdk/dedicatedDatabases';
import type { Models } from '@appwrite.io/console';
let {
show = $bindable(false),
@@ -13,7 +13,7 @@
connectionCommand
}: {
show: boolean;
database: DedicatedDatabase;
database: Models.DedicatedDatabase;
connectionCommand: string;
} = $props();