From 06ea808b3191b985ebaae105c0fe5569094e68b6 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Tue, 3 Mar 2026 15:55:33 +0000 Subject: [PATCH 1/4] Add platform migration support --- src/Migration/Destinations/Appwrite.php | 79 ++++++++++- src/Migration/Resource.php | 4 + .../Resources/Integrations/Platform.php | 104 ++++++++++++++ src/Migration/Source.php | 17 +++ src/Migration/Sources/Appwrite.php | 134 +++++++++++++++++- src/Migration/Sources/CSV.php | 5 + src/Migration/Sources/Firebase.php | 6 +- src/Migration/Sources/JSON.php | 5 + src/Migration/Sources/NHost.php | 5 + src/Migration/Transfer.php | 12 +- .../Unit/Adapters/MockDestination.php | 1 + tests/Migration/Unit/Adapters/MockSource.php | 18 +++ 12 files changed, 382 insertions(+), 8 deletions(-) create mode 100644 src/Migration/Resources/Integrations/Platform.php diff --git a/src/Migration/Destinations/Appwrite.php b/src/Migration/Destinations/Appwrite.php index 6b730a18..12173cbb 100644 --- a/src/Migration/Destinations/Appwrite.php +++ b/src/Migration/Destinations/Appwrite.php @@ -46,6 +46,7 @@ use Utopia\Migration\Resources\Functions\Deployment; use Utopia\Migration\Resources\Functions\EnvVar; use Utopia\Migration\Resources\Functions\Func; +use Utopia\Migration\Resources\Integrations\Platform; use Utopia\Migration\Resources\Sites\Deployment as SiteDeployment; use Utopia\Migration\Resources\Sites\EnvVar as SiteEnvVar; use Utopia\Migration\Resources\Sites\Site; @@ -83,7 +84,9 @@ public function __construct( string $endpoint, string $key, protected UtopiaDatabase $database, - protected array $collectionStructure + protected array $collectionStructure, + protected ?UtopiaDatabase $dbForPlatform = null, + protected string $projectInternalId = '', ) { $this->project = $project; $this->endpoint = $endpoint; @@ -142,6 +145,9 @@ public static function getSupportedResources(): array Resource::TYPE_SITE, Resource::TYPE_SITE_DEPLOYMENT, Resource::TYPE_SITE_VARIABLE, + + // Integrations + Resource::TYPE_PLATFORM, ]; } @@ -221,7 +227,6 @@ public function report(array $resources = [], array $resourceIds = []): array $scope = 'sites.write'; $this->sites->create('', '', Framework::OTHER(), BuildRuntime::STATIC1()); } - } catch (AppwriteException $e) { if ($e->getCode() === 403) { throw new \Exception('Missing scope: ' . $scope, previous: $e); @@ -253,6 +258,7 @@ protected function import(array $resources, callable $callback): void try { $this->database->setPreserveDates(true); + $this->dbForPlatform?->setPreserveDates(true); $responseResource = match ($resource->getGroup()) { Transfer::GROUP_DATABASES => $this->importDatabaseResource($resource, $isLast), @@ -260,6 +266,7 @@ protected function import(array $resources, callable $callback): void Transfer::GROUP_AUTH => $this->importAuthResource($resource), Transfer::GROUP_FUNCTIONS => $this->importFunctionResource($resource), Transfer::GROUP_SITES => $this->importSiteResource($resource), + Transfer::GROUP_INTEGRATIONS => $this->importIntegrationsResource($resource), default => throw new \Exception('Invalid resource group'), }; } catch (\Throwable $e) { @@ -277,6 +284,7 @@ protected function import(array $resources, callable $callback): void $responseResource = $resource; } finally { $this->database->setPreserveDates(false); + $this->dbForPlatform?->setPreserveDates(false); } $this->cache->update($responseResource); @@ -1059,7 +1067,6 @@ protected function createRow(Row $resource, bool $isLast): bool 'database_' . $databaseInternalId . '_collection_' . $tableInternalId, $this->rowBuffer )); - } finally { $this->rowBuffer = []; } @@ -1730,4 +1737,70 @@ private function importSiteDeployment(SiteDeployment $deployment): Resource return $deployment; } + + /** + * @throws \Exception + */ + public function importIntegrationsResource(Resource $resource): Resource + { + if ($this->dbForPlatform === null || $this->projectInternalId === '') { + throw new \Exception('Platform database not available for integrations migration'); + } + + switch ($resource->getName()) { + case Resource::TYPE_PLATFORM: + /** @var Platform $resource */ + $this->createPlatform($resource); + break; + } + + if ($resource->getStatus() !== Resource::STATUS_SKIPPED) { + $resource->setStatus(Resource::STATUS_SUCCESS); + } + + return $resource; + } + + /** + * @throws \Throwable + */ + protected function createPlatform(Platform $resource): bool + { + $existing = $this->dbForPlatform->findOne('platforms', [ + Query::equal('projectId', [$this->project]), + Query::equal('type', [$resource->getType()]), + Query::equal('name', [$resource->getPlatformName()]), + ]); + + if ($existing !== false && !$existing->isEmpty()) { + $resource->setStatus(Resource::STATUS_SKIPPED, 'Platform already exists'); + return false; + } + + $createdAt = $this->normalizeDateTime($resource->getCreatedAt()); + $updatedAt = $this->normalizeDateTime($resource->getUpdatedAt(), $createdAt); + + try { + $this->dbForPlatform->createDocument('platforms', new UtopiaDocument([ + '$id' => ID::unique(), + '$permissions' => $resource->getPermissions(), + 'projectInternalId' => $this->projectInternalId, + 'projectId' => $this->project, + 'type' => $resource->getType(), + 'name' => $resource->getPlatformName(), + 'key' => $resource->getKey(), + 'store' => $resource->getStore(), + 'hostname' => $resource->getHostname(), + '$createdAt' => $createdAt, + '$updatedAt' => $updatedAt, + ])); + } catch (DuplicateException) { + $resource->setStatus(Resource::STATUS_SKIPPED, 'Platform already exists'); + return false; + } + + $this->dbForPlatform->purgeCachedDocument('projects', $this->project); + + return true; + } } diff --git a/src/Migration/Resource.php b/src/Migration/Resource.php index e338385c..f0d275af 100644 --- a/src/Migration/Resource.php +++ b/src/Migration/Resource.php @@ -60,6 +60,9 @@ abstract class Resource implements \JsonSerializable public const TYPE_ENVIRONMENT_VARIABLE = 'environment-variable'; + // Integrations + public const TYPE_PLATFORM = 'platform'; + // legacy terminologies public const TYPE_DOCUMENT = 'document'; public const TYPE_ATTRIBUTE = 'attribute'; @@ -89,6 +92,7 @@ abstract class Resource implements \JsonSerializable self::TYPE_ENVIRONMENT_VARIABLE, self::TYPE_TEAM, self::TYPE_MEMBERSHIP, + self::TYPE_PLATFORM, // legacy self::TYPE_DOCUMENT, diff --git a/src/Migration/Resources/Integrations/Platform.php b/src/Migration/Resources/Integrations/Platform.php new file mode 100644 index 00000000..c81b6f04 --- /dev/null +++ b/src/Migration/Resources/Integrations/Platform.php @@ -0,0 +1,104 @@ +id = $id; + $this->createdAt = $createdAt; + $this->updatedAt = $updatedAt; + } + + /** + * @param array $array + * @return self + */ + public static function fromArray(array $array): self + { + return new self( + $array['id'], + $array['type'], + $array['name'], + $array['key'] ?? '', + $array['store'] ?? '', + $array['hostname'] ?? '', + createdAt: $array['createdAt'] ?? '', + updatedAt: $array['updatedAt'] ?? '', + ); + } + + /** + * @return array + */ + public function jsonSerialize(): array + { + return [ + 'id' => $this->id, + 'type' => $this->type, + 'name' => $this->name, + 'key' => $this->key, + 'store' => $this->store, + 'hostname' => $this->hostname, + 'createdAt' => $this->createdAt, + 'updatedAt' => $this->updatedAt, + ]; + } + + public static function getName(): string + { + return Resource::TYPE_PLATFORM; + } + + public function getGroup(): string + { + return Transfer::GROUP_INTEGRATIONS; + } + + public function getType(): string + { + return $this->type; + } + + public function getPlatformName(): string + { + return $this->name; + } + + public function getKey(): string + { + return $this->key; + } + + public function getStore(): string + { + return $this->store; + } + + public function getHostname(): string + { + return $this->hostname; + } +} diff --git a/src/Migration/Source.php b/src/Migration/Source.php index a6b154a1..81f61c16 100644 --- a/src/Migration/Source.php +++ b/src/Migration/Source.php @@ -41,6 +41,11 @@ public function getSitesBatchSize(): int return static::$defaultBatchSize; } + public function getIntegrationsBatchSize(): int + { + return static::$defaultBatchSize; + } + /** * @param array $resources * @return void @@ -95,6 +100,7 @@ public function exportResources(array $resources): void Transfer::GROUP_STORAGE => Transfer::GROUP_STORAGE_RESOURCES, Transfer::GROUP_FUNCTIONS => Transfer::GROUP_FUNCTIONS_RESOURCES, Transfer::GROUP_SITES => Transfer::GROUP_SITES_RESOURCES, + Transfer::GROUP_INTEGRATIONS => Transfer::GROUP_INTEGRATIONS_RESOURCES, ]; foreach ($mapping as $group => $resources) { @@ -126,6 +132,9 @@ public function exportResources(array $resources): void case Transfer::GROUP_SITES: $this->exportGroupSites($this->getSitesBatchSize(), $resources); break; + case Transfer::GROUP_INTEGRATIONS: + $this->exportGroupIntegrations($this->getIntegrationsBatchSize(), $resources); + break; } } } @@ -169,4 +178,12 @@ abstract protected function exportGroupFunctions(int $batchSize, array $resource * @param array $resources Resources to export */ abstract protected function exportGroupSites(int $batchSize, array $resources): void; + + /** + * Export Integrations Group + * + * @param int $batchSize + * @param array $resources Resources to export + */ + abstract protected function exportGroupIntegrations(int $batchSize, array $resources): void; } diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php index 47a03461..aef0ab21 100644 --- a/src/Migration/Sources/Appwrite.php +++ b/src/Migration/Sources/Appwrite.php @@ -44,6 +44,7 @@ use Utopia\Migration\Resources\Functions\Deployment; use Utopia\Migration\Resources\Functions\EnvVar; use Utopia\Migration\Resources\Functions\Func; +use Utopia\Migration\Resources\Integrations\Platform; use Utopia\Migration\Resources\Sites\Deployment as SiteDeployment; use Utopia\Migration\Resources\Sites\EnvVar as SiteEnvVar; use Utopia\Migration\Resources\Sites\Site; @@ -76,6 +77,10 @@ class Appwrite extends Source private Reader $database; + private bool $consoleKeyFetched = false; + + private ?string $consoleKey = null; + /** * @throws \Exception */ @@ -116,6 +121,38 @@ public function __construct( } } + public function setConsoleKey(string $key): void + { + $this->consoleKey = $key; + $this->consoleKeyFetched = true; + } + + /** + * @return array|null + */ + protected function getConsoleHeaders(): ?array + { + if (!$this->consoleKeyFetched) { + $this->consoleKeyFetched = true; + + try { + $response = $this->call('GET', '/migrations/appwrite/console-key'); + $this->consoleKey = $response['key'] ?? null; + } catch (\Throwable) { + $this->consoleKey = null; + } + } + + if ($this->consoleKey === null) { + return null; + } + + return [ + 'x-appwrite-project' => 'console', + 'x-appwrite-key' => $this->consoleKey, + ]; + } + public static function getName(): string { return 'Appwrite'; @@ -158,7 +195,8 @@ public static function getSupportedResources(): array Resource::TYPE_SITE_DEPLOYMENT, Resource::TYPE_SITE_VARIABLE, - // Settings + // Integrations + Resource::TYPE_PLATFORM, ]; } @@ -196,6 +234,7 @@ public function report(array $resources = [], array $resourceIds = []): array $this->reportStorage($resources, $report, $resourceIds); $this->reportFunctions($resources, $report, $resourceIds); $this->reportSites($resources, $report, $resourceIds); + $this->reportIntegrations($resources, $report, $resourceIds); $report['version'] = $this->call( 'GET', @@ -1996,6 +2035,99 @@ private function exportSiteDeploymentData(Site $site, array $deployment): void } } + /** + * @param array $resources + * @param array $report + * @param array> $resourceIds + */ + private function reportIntegrations(array $resources, array &$report, array $resourceIds = []): void + { + if (\in_array(Resource::TYPE_PLATFORM, $resources)) { + $consoleHeaders = $this->getConsoleHeaders(); + + if ($consoleHeaders === null) { + return; + } + + try { + $response = $this->call('GET', '/projects/' . $this->project . '/platforms', $consoleHeaders); + $report[Resource::TYPE_PLATFORM] = $response['total'] ?? 0; + } catch (\Throwable) { + $report[Resource::TYPE_PLATFORM] = 0; + } + } + } + + /** + * @param int $batchSize + * @param array $resources + */ + protected function exportGroupIntegrations(int $batchSize, array $resources): void + { + if (\in_array(Resource::TYPE_PLATFORM, $resources)) { + $this->exportWithConsoleHeaders( + Resource::TYPE_PLATFORM, + Transfer::GROUP_INTEGRATIONS, + $this->exportPlatforms(...) + ); + } + } + + protected function exportWithConsoleHeaders(string $resourceType, string $group, callable $callback): void + { + $consoleHeaders = $this->getConsoleHeaders(); + + if ($consoleHeaders === null) { + $this->addError(new Exception( + $resourceType, + $group, + message: 'Console key unavailable for source instance', + )); + return; + } + + try { + $callback($consoleHeaders); + } catch (\Throwable $e) { + $this->addError(new Exception( + $resourceType, + $group, + message: $e->getMessage(), + code: $e->getCode(), + previous: $e + )); + } + } + + /** + * @throws AppwriteException + */ + private function exportPlatforms(array $consoleHeaders): void + { + $response = $this->call('GET', '/projects/' . $this->project . '/platforms', $consoleHeaders); + + if (empty($response['platforms'])) { + return; + } + + $platforms = []; + + foreach ($response['platforms'] as $platform) { + $platforms[] = new Platform( + $platform['$id'] ?? '', + $platform['type'] ?? '', + $platform['name'] ?? '', + $platform['key'] ?? '', + $platform['store'] ?? '', + $platform['hostname'] ?? '', + createdAt: $platform['$createdAt'] ?? '', + updatedAt: $platform['$updatedAt'] ?? '', + ); + } + + $this->callback($platforms); + } + /** * Build queries with optional filtering by resource IDs */ diff --git a/src/Migration/Sources/CSV.php b/src/Migration/Sources/CSV.php index 3cd227c5..7b8e479f 100644 --- a/src/Migration/Sources/CSV.php +++ b/src/Migration/Sources/CSV.php @@ -380,6 +380,11 @@ protected function exportGroupSites(int $batchSize, array $resources): void throw new \Exception('Not Implemented'); } + protected function exportGroupIntegrations(int $batchSize, array $resources): void + { + throw new \Exception('Not Implemented'); + } + /** * @param callable(resource $stream, string $delimiter): void $callback * @return void diff --git a/src/Migration/Sources/Firebase.php b/src/Migration/Sources/Firebase.php index b1ef5b72..efe7f006 100644 --- a/src/Migration/Sources/Firebase.php +++ b/src/Migration/Sources/Firebase.php @@ -667,7 +667,6 @@ protected function exportGroupStorage(int $batchSize, array $resources): void previous: $e )); } - } private function exportBuckets(int $batchsize): void @@ -813,4 +812,9 @@ protected function exportGroupSites(int $batchSize, array $resources): void { throw new \Exception('Not implemented'); } + + protected function exportGroupIntegrations(int $batchSize, array $resources): void + { + throw new \Exception('Not implemented'); + } } diff --git a/src/Migration/Sources/JSON.php b/src/Migration/Sources/JSON.php index 8abf63d7..944824dc 100644 --- a/src/Migration/Sources/JSON.php +++ b/src/Migration/Sources/JSON.php @@ -209,6 +209,11 @@ protected function exportGroupSites(int $batchSize, array $resources): void throw new \Exception('Not Implemented'); } + protected function exportGroupIntegrations(int $batchSize, array $resources): void + { + throw new \Exception('Not Implemented'); + } + /** * @param callable(Items): void $callback * @throws \Exception|JsonMachineException diff --git a/src/Migration/Sources/NHost.php b/src/Migration/Sources/NHost.php index 5c563248..c0829704 100644 --- a/src/Migration/Sources/NHost.php +++ b/src/Migration/Sources/NHost.php @@ -853,4 +853,9 @@ protected function exportGroupSites(int $batchSize, array $resources): void { throw new \Exception('Not Implemented'); } + + protected function exportGroupIntegrations(int $batchSize, array $resources): void + { + throw new \Exception('Not Implemented'); + } } diff --git a/src/Migration/Transfer.php b/src/Migration/Transfer.php index b4da5007..04dc01fc 100644 --- a/src/Migration/Transfer.php +++ b/src/Migration/Transfer.php @@ -16,7 +16,7 @@ class Transfer public const GROUP_DATABASES = 'databases'; - public const GROUP_SETTINGS = 'settings'; + public const GROUP_INTEGRATIONS = 'integrations'; public const GROUP_AUTH_RESOURCES = [ Resource::TYPE_USER, @@ -50,7 +50,9 @@ class Transfer Resource::TYPE_ROW, ]; - public const GROUP_SETTINGS_RESOURCES = []; + public const GROUP_INTEGRATIONS_RESOURCES = [ + Resource::TYPE_PLATFORM, + ]; public const ALL_PUBLIC_RESOURCES = [ Resource::TYPE_USER, @@ -70,6 +72,9 @@ class Transfer Resource::TYPE_COLUMN, Resource::TYPE_ROW, + // Integrations + Resource::TYPE_PLATFORM, + // legacy Resource::TYPE_DOCUMENT, Resource::TYPE_ATTRIBUTE, @@ -83,6 +88,7 @@ class Transfer Resource::TYPE_SITE, Resource::TYPE_USER, Resource::TYPE_TEAM, + Resource::TYPE_PLATFORM, ]; public const STORAGE_MAX_CHUNK_SIZE = 1024 * 1024 * 5; // 5MB @@ -342,7 +348,7 @@ public static function extractServices(array $services): array self::GROUP_GENERAL => array_merge($resources, []), self::GROUP_AUTH => array_merge($resources, self::GROUP_AUTH_RESOURCES), self::GROUP_DATABASES => array_merge($resources, self::GROUP_DATABASES_RESOURCES), - self::GROUP_SETTINGS => array_merge($resources, self::GROUP_SETTINGS_RESOURCES), + self::GROUP_INTEGRATIONS => array_merge($resources, self::GROUP_INTEGRATIONS_RESOURCES), default => throw new \Exception('No service group found'), }; } diff --git a/tests/Migration/Unit/Adapters/MockDestination.php b/tests/Migration/Unit/Adapters/MockDestination.php index d8258b3e..333a3b70 100644 --- a/tests/Migration/Unit/Adapters/MockDestination.php +++ b/tests/Migration/Unit/Adapters/MockDestination.php @@ -51,6 +51,7 @@ public static function getSupportedResources(): array Resource::TYPE_ENVIRONMENT_VARIABLE, Resource::TYPE_TEAM, Resource::TYPE_MEMBERSHIP, + Resource::TYPE_PLATFORM, ]; } diff --git a/tests/Migration/Unit/Adapters/MockSource.php b/tests/Migration/Unit/Adapters/MockSource.php index 64e5640f..0353219f 100644 --- a/tests/Migration/Unit/Adapters/MockSource.php +++ b/tests/Migration/Unit/Adapters/MockSource.php @@ -80,6 +80,7 @@ public static function getSupportedResources(): array Resource::TYPE_ENVIRONMENT_VARIABLE, Resource::TYPE_TEAM, Resource::TYPE_MEMBERSHIP, + Resource::TYPE_PLATFORM, // legacy Resource::TYPE_DOCUMENT, @@ -177,4 +178,21 @@ protected function exportGroupSites(int $batchSize, array $resources): void $this->handleResourceTransfer(Transfer::GROUP_SITES, $resource); } } + + /** + * Export Integrations Group + * + * @param int $batchSize Max 100 + * @param string[] $resources Resources to export + */ + protected function exportGroupIntegrations(int $batchSize, array $resources): void + { + foreach (Transfer::GROUP_INTEGRATIONS_RESOURCES as $resource) { + if (!\in_array($resource, $resources)) { + continue; + } + + $this->handleResourceTransfer(Transfer::GROUP_INTEGRATIONS, $resource); + } + } } From 666f015e94789202429d67eb8a8f85943dfb4415 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Tue, 3 Mar 2026 20:32:56 +0000 Subject: [PATCH 2/4] Change console-key endpoint call from GET to POST --- src/Migration/Sources/Appwrite.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php index aef0ab21..791a7e0e 100644 --- a/src/Migration/Sources/Appwrite.php +++ b/src/Migration/Sources/Appwrite.php @@ -136,7 +136,7 @@ protected function getConsoleHeaders(): ?array $this->consoleKeyFetched = true; try { - $response = $this->call('GET', '/migrations/appwrite/console-key'); + $response = $this->call('POST', '/migrations/appwrite/console-key'); $this->consoleKey = $response['key'] ?? null; } catch (\Throwable) { $this->consoleKey = null; From 12a4d8eb1d40e292c6592b917679a59b160b6374 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Sat, 14 Mar 2026 22:37:16 +0000 Subject: [PATCH 3/4] Resolve merge conflicts with main branch --- src/Migration/Resource.php | 6 ------ src/Migration/Sources/Appwrite.php | 12 ------------ src/Migration/Transfer.php | 10 ---------- tests/Migration/Unit/Adapters/MockDestination.php | 3 --- tests/Migration/Unit/Adapters/MockSource.php | 3 --- 5 files changed, 34 deletions(-) diff --git a/src/Migration/Resource.php b/src/Migration/Resource.php index 165b111d..e624fe2c 100644 --- a/src/Migration/Resource.php +++ b/src/Migration/Resource.php @@ -71,14 +71,11 @@ abstract class Resource implements \JsonSerializable public const TYPE_ENVIRONMENT_VARIABLE = 'environment-variable'; -<<<<<<< HEAD // Integrations public const TYPE_PLATFORM = 'platform'; -======= public const TYPE_SUBSCRIBER = 'subscriber'; public const TYPE_MESSAGE = 'message'; ->>>>>>> origin/main // legacy terminologies public const TYPE_DOCUMENT = 'document'; @@ -111,14 +108,11 @@ abstract class Resource implements \JsonSerializable self::TYPE_ENVIRONMENT_VARIABLE, self::TYPE_TEAM, self::TYPE_MEMBERSHIP, -<<<<<<< HEAD self::TYPE_PLATFORM, -======= self::TYPE_PROVIDER, self::TYPE_TOPIC, self::TYPE_SUBSCRIBER, self::TYPE_MESSAGE, ->>>>>>> origin/main // legacy self::TYPE_DOCUMENT, diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php index a1e0ca5b..7fed217d 100644 --- a/src/Migration/Sources/Appwrite.php +++ b/src/Migration/Sources/Appwrite.php @@ -53,14 +53,11 @@ use Utopia\Migration\Resources\Functions\Deployment; use Utopia\Migration\Resources\Functions\EnvVar; use Utopia\Migration\Resources\Functions\Func; -<<<<<<< HEAD use Utopia\Migration\Resources\Integrations\Platform; -======= use Utopia\Migration\Resources\Messaging\Message; use Utopia\Migration\Resources\Messaging\Provider; use Utopia\Migration\Resources\Messaging\Subscriber; use Utopia\Migration\Resources\Messaging\Topic; ->>>>>>> origin/main use Utopia\Migration\Resources\Sites\Deployment as SiteDeployment; use Utopia\Migration\Resources\Sites\EnvVar as SiteEnvVar; use Utopia\Migration\Resources\Sites\Site; @@ -2231,7 +2228,6 @@ private function exportSiteDeploymentData(Site $site, array $deployment): void } /** -<<<<<<< HEAD * @param array $resources * @param array $report * @param array> $resourceIds @@ -2251,7 +2247,6 @@ private function reportIntegrations(array $resources, array &$report, array $res } catch (\Throwable) { $report[Resource::TYPE_PLATFORM] = 0; } -======= * @param string $databaseType * @param array $database { * id: string, @@ -2272,12 +2267,10 @@ public static function getDatabase(string $databaseType, array $database): Resou return VectorsDB::fromArray($database); default: return Database::fromArray($database); ->>>>>>> origin/main } } /** -<<<<<<< HEAD * @param int $batchSize * @param array $resources */ @@ -2315,7 +2308,6 @@ protected function exportWithConsoleHeaders(string $resourceType, string $group, code: $e->getCode(), previous: $e )); -======= * eg., tables,collections * @param string $databaseType * @param array{ @@ -2342,12 +2334,10 @@ public static function getEntity(string $databaseType, array $entity): Resource return Collection::fromArray($entity); default: return Table::fromArray($entity); ->>>>>>> origin/main } } /** -<<<<<<< HEAD * @throws AppwriteException */ private function exportPlatforms(array $consoleHeaders): void @@ -2374,7 +2364,6 @@ private function exportPlatforms(array $consoleHeaders): void } $this->callback($platforms); -======= * eg.,documents/attributes * @param string $databaseType * @param array{ @@ -2639,7 +2628,6 @@ public static function getAttribute(Collection $collection, mixed $attribute): A // Use getColumn() to create the Column resource, then convert to Attribute // This eliminates duplication - all type-specific logic is in getColumn() return self::getColumn($collection, $attribute)->getAttribute(); ->>>>>>> origin/main } /** diff --git a/src/Migration/Transfer.php b/src/Migration/Transfer.php index 9561e517..59ed486c 100644 --- a/src/Migration/Transfer.php +++ b/src/Migration/Transfer.php @@ -58,11 +58,9 @@ class Transfer Resource::TYPE_ROW, ]; -<<<<<<< HEAD public const GROUP_INTEGRATIONS_RESOURCES = [ Resource::TYPE_PLATFORM, ]; -======= public const GROUP_DOCUMENTSDB_RESOURCES = [ Resource::TYPE_DATABASE_DOCUMENTSDB, Resource::TYPE_COLLECTION, @@ -92,7 +90,6 @@ class Transfer ]; public const GROUP_SETTINGS_RESOURCES = []; ->>>>>>> origin/main public const GROUP_MESSAGING_RESOURCES = [ Resource::TYPE_PROVIDER, @@ -141,13 +138,10 @@ class Transfer Resource::TYPE_SITE, Resource::TYPE_USER, Resource::TYPE_TEAM, -<<<<<<< HEAD Resource::TYPE_PLATFORM, -======= Resource::TYPE_PROVIDER, Resource::TYPE_TOPIC, Resource::TYPE_MESSAGE, ->>>>>>> origin/main ]; public const STORAGE_MAX_CHUNK_SIZE = 1024 * 1024 * 5; // 5MB @@ -407,15 +401,11 @@ public static function extractServices(array $services): array self::GROUP_GENERAL => array_merge($resources, []), self::GROUP_AUTH => array_merge($resources, self::GROUP_AUTH_RESOURCES), self::GROUP_DATABASES => array_merge($resources, self::GROUP_DATABASES_RESOURCES), -<<<<<<< HEAD self::GROUP_INTEGRATIONS => array_merge($resources, self::GROUP_INTEGRATIONS_RESOURCES), -======= self::GROUP_DATABASES_TABLES_DB => array_merge($resources, self::GROUP_TABLESDB_RESOURCES), self::GROUP_DATABASES_DOCUMENTS_DB => array_merge($resources, self::GROUP_DOCUMENTSDB_RESOURCES), self::GROUP_DATABASES_VECTOR_DB => array_merge($resources, self::GROUP_VECTORSDB_RESOURCES), - self::GROUP_SETTINGS => array_merge($resources, self::GROUP_SETTINGS_RESOURCES), self::GROUP_MESSAGING => array_merge($resources, self::GROUP_MESSAGING_RESOURCES), ->>>>>>> origin/main default => throw new \Exception('No service group found'), }; } diff --git a/tests/Migration/Unit/Adapters/MockDestination.php b/tests/Migration/Unit/Adapters/MockDestination.php index 8886c080..2aa528a8 100644 --- a/tests/Migration/Unit/Adapters/MockDestination.php +++ b/tests/Migration/Unit/Adapters/MockDestination.php @@ -51,14 +51,11 @@ public static function getSupportedResources(): array Resource::TYPE_ENVIRONMENT_VARIABLE, Resource::TYPE_TEAM, Resource::TYPE_MEMBERSHIP, -<<<<<<< HEAD Resource::TYPE_PLATFORM, -======= Resource::TYPE_PROVIDER, Resource::TYPE_TOPIC, Resource::TYPE_SUBSCRIBER, Resource::TYPE_MESSAGE, ->>>>>>> origin/main ]; } diff --git a/tests/Migration/Unit/Adapters/MockSource.php b/tests/Migration/Unit/Adapters/MockSource.php index ac7f2e93..1524dea8 100644 --- a/tests/Migration/Unit/Adapters/MockSource.php +++ b/tests/Migration/Unit/Adapters/MockSource.php @@ -80,14 +80,11 @@ public static function getSupportedResources(): array Resource::TYPE_ENVIRONMENT_VARIABLE, Resource::TYPE_TEAM, Resource::TYPE_MEMBERSHIP, -<<<<<<< HEAD Resource::TYPE_PLATFORM, -======= Resource::TYPE_PROVIDER, Resource::TYPE_TOPIC, Resource::TYPE_SUBSCRIBER, Resource::TYPE_MESSAGE, ->>>>>>> origin/main // legacy Resource::TYPE_DOCUMENT, From 86843355dced5e4ad763b19764a766a3821fb6b2 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Sat, 14 Mar 2026 23:10:53 +0000 Subject: [PATCH 4/4] Fix syntax errors and add projectInternalId constructor param --- src/Migration/Destinations/Appwrite.php | 5 ++++- src/Migration/Sources/Appwrite.php | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Migration/Destinations/Appwrite.php b/src/Migration/Destinations/Appwrite.php index b974e177..32de9758 100644 --- a/src/Migration/Destinations/Appwrite.php +++ b/src/Migration/Destinations/Appwrite.php @@ -102,6 +102,7 @@ public function __construct( callable $getDatabasesDB, protected array $collectionStructure, protected UtopiaDatabase $dbForPlatform, + protected string $projectInternalId, ) { $this->project = $project; $this->endpoint = $endpoint; @@ -2237,7 +2238,7 @@ protected function createPlatform(Platform $resource): bool $this->dbForPlatform->createDocument('platforms', new UtopiaDocument([ '$id' => ID::unique(), '$permissions' => $resource->getPermissions(), - 'projectInternalId' => $this->dbForPlatform->getDocument('projects', $this->project)->getInternalId(), + 'projectInternalId' => $this->projectInternalId, 'projectId' => $this->project, 'type' => $resource->getType(), 'name' => $resource->getPlatformName(), @@ -2255,6 +2256,8 @@ protected function createPlatform(Platform $resource): bool $this->dbForPlatform->purgeCachedDocument('projects', $this->project); return true; + } + private function validateFieldsForIndexes(Index $resource, UtopiaDocument $table, array &$lengths) { /** diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php index 7fed217d..1f51fa6b 100644 --- a/src/Migration/Sources/Appwrite.php +++ b/src/Migration/Sources/Appwrite.php @@ -2247,6 +2247,10 @@ private function reportIntegrations(array $resources, array &$report, array $res } catch (\Throwable) { $report[Resource::TYPE_PLATFORM] = 0; } + } + } + + /** * @param string $databaseType * @param array $database { * id: string, @@ -2308,6 +2312,10 @@ protected function exportWithConsoleHeaders(string $resourceType, string $group, code: $e->getCode(), previous: $e )); + } + } + + /** * eg., tables,collections * @param string $databaseType * @param array{ @@ -2364,6 +2372,9 @@ private function exportPlatforms(array $consoleHeaders): void } $this->callback($platforms); + } + + /** * eg.,documents/attributes * @param string $databaseType * @param array{