Skip to content

Commit 334f4a8

Browse files
Merge remote-tracking branch 'origin/main' into multitype-db
2 parents fe91feb + 35df40d commit 334f4a8

17 files changed

Lines changed: 1012 additions & 8 deletions

File tree

src/Migration/Cache.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Utopia\Migration\Resources\Database\Row;
88
use Utopia\Migration\Resources\Database\Table;
99
use Utopia\Migration\Resources\Functions\Deployment;
10+
use Utopia\Migration\Resources\Sites\Deployment as SiteDeployment;
1011
use Utopia\Migration\Resources\Storage\File;
1112

1213
/**
@@ -70,6 +71,11 @@ public function resolveResourceCacheKey(Resource $resource): string
7071
$keys[] = $resource->getFunction()->getSequence();
7172
break;
7273

74+
case Resource::TYPE_SITE_DEPLOYMENT:
75+
/** @var SiteDeployment $resource */
76+
$keys[] = $resource->getSite()->getSequence();
77+
break;
78+
7379
default:
7480
break;
7581
}
@@ -100,8 +106,8 @@ public function add(Resource $resource): void
100106
return;
101107
}
102108

103-
if ($resource->getName() == Resource::TYPE_FILE || $resource->getName() == Resource::TYPE_DEPLOYMENT) {
104-
/** @var File|Deployment $resource */
109+
if ($resource->getName() == Resource::TYPE_FILE || $resource->getName() == Resource::TYPE_DEPLOYMENT || $resource->getName() == Resource::TYPE_SITE_DEPLOYMENT) {
110+
/** @var File|Deployment|SiteDeployment $resource */
105111
$resource->setData(''); // Prevent Memory Leak
106112
}
107113

src/Migration/Destinations/Appwrite.php

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44

55
use Appwrite\AppwriteException;
66
use Appwrite\Client;
7+
use Appwrite\Enums\Adapter;
8+
use Appwrite\Enums\BuildRuntime;
79
use Appwrite\Enums\Compression;
10+
use Appwrite\Enums\Framework;
811
use Appwrite\Enums\PasswordHash;
912
use Appwrite\Enums\Runtime;
1013
use Appwrite\InputFile;
1114
use Appwrite\Services\Functions;
15+
use Appwrite\Services\Sites;
1216
use Appwrite\Services\Storage;
1317
use Appwrite\Services\Teams;
1418
use Appwrite\Services\Users;
@@ -43,6 +47,9 @@
4347
use Utopia\Migration\Resources\Functions\Deployment;
4448
use Utopia\Migration\Resources\Functions\EnvVar;
4549
use Utopia\Migration\Resources\Functions\Func;
50+
use Utopia\Migration\Resources\Sites\Deployment as SiteDeployment;
51+
use Utopia\Migration\Resources\Sites\EnvVar as SiteEnvVar;
52+
use Utopia\Migration\Resources\Sites\Site;
4653
use Utopia\Migration\Resources\Storage\Bucket;
4754
use Utopia\Migration\Resources\Storage\File;
4855
use Utopia\Migration\Transfer;
@@ -55,6 +62,7 @@ class Appwrite extends Destination
5562
protected string $key;
5663

5764
private Functions $functions;
65+
private Sites $sites;
5866
private Storage $storage;
5967
private Teams $teams;
6068
private Users $users;
@@ -102,6 +110,7 @@ public function __construct(
102110
->setKey($key);
103111

104112
$this->functions = new Functions($this->client);
113+
$this->sites = new Sites($this->client);
105114
$this->storage = new Storage($this->client);
106115
$this->teams = new Teams($this->client);
107116
$this->users = new Users($this->client);
@@ -148,6 +157,11 @@ public static function getSupportedResources(): array
148157
Resource::TYPE_FUNCTION,
149158
Resource::TYPE_DEPLOYMENT,
150159
Resource::TYPE_ENVIRONMENT_VARIABLE,
160+
161+
// Sites
162+
Resource::TYPE_SITE,
163+
Resource::TYPE_SITE_DEPLOYMENT,
164+
Resource::TYPE_SITE_VARIABLE,
151165
];
152166
}
153167

@@ -219,6 +233,15 @@ public function report(array $resources = [], array $resourceIds = []): array
219233
$this->functions->create('', '', Runtime::NODE180());
220234
}
221235

236+
// Sites
237+
if (\in_array(Resource::TYPE_SITE, $resources)) {
238+
$scope = 'sites.read';
239+
$this->sites->list();
240+
241+
$scope = 'sites.write';
242+
$this->sites->create('', '', Framework::OTHER(), BuildRuntime::STATIC1());
243+
}
244+
222245
} catch (AppwriteException $e) {
223246
if ($e->getCode() === 403) {
224247
throw new \Exception('Missing scope: ' . $scope, previous: $e);
@@ -256,6 +279,7 @@ protected function import(array $resources, callable $callback): void
256279
Transfer::GROUP_STORAGE => $this->importFileResource($resource),
257280
Transfer::GROUP_AUTH => $this->importAuthResource($resource),
258281
Transfer::GROUP_FUNCTIONS => $this->importFunctionResource($resource),
282+
Transfer::GROUP_SITES => $this->importSiteResource($resource),
259283
default => throw new \Exception('Invalid resource group'),
260284
};
261285
} catch (\Throwable $e) {
@@ -1465,6 +1489,207 @@ private function importDeployment(Deployment $deployment): Resource
14651489
return $deployment;
14661490
}
14671491

1492+
/**
1493+
* @throws AppwriteException
1494+
*/
1495+
public function importSiteResource(Resource $resource): Resource
1496+
{
1497+
switch ($resource->getName()) {
1498+
case Resource::TYPE_SITE:
1499+
/** @var Site $resource */
1500+
1501+
$buildRuntime = match ($resource->getBuildRuntime()) {
1502+
'node-14.5' => BuildRuntime::NODE145(),
1503+
'node-16.0' => BuildRuntime::NODE160(),
1504+
'node-18.0' => BuildRuntime::NODE180(),
1505+
'node-19.0' => BuildRuntime::NODE190(),
1506+
'node-20.0' => BuildRuntime::NODE200(),
1507+
'node-21.0' => BuildRuntime::NODE210(),
1508+
'node-22' => BuildRuntime::NODE22(),
1509+
'php-8.0' => BuildRuntime::PHP80(),
1510+
'php-8.1' => BuildRuntime::PHP81(),
1511+
'php-8.2' => BuildRuntime::PHP82(),
1512+
'php-8.3' => BuildRuntime::PHP83(),
1513+
'ruby-3.0' => BuildRuntime::RUBY30(),
1514+
'ruby-3.1' => BuildRuntime::RUBY31(),
1515+
'ruby-3.2' => BuildRuntime::RUBY32(),
1516+
'ruby-3.3' => BuildRuntime::RUBY33(),
1517+
'python-3.8' => BuildRuntime::PYTHON38(),
1518+
'python-3.9' => BuildRuntime::PYTHON39(),
1519+
'python-3.10' => BuildRuntime::PYTHON310(),
1520+
'python-3.11' => BuildRuntime::PYTHON311(),
1521+
'python-3.12' => BuildRuntime::PYTHON312(),
1522+
'python-ml-3.11' => BuildRuntime::PYTHONML311(),
1523+
'python-ml-3.12' => BuildRuntime::PYTHONML312(),
1524+
'dart-3.0' => BuildRuntime::DART30(),
1525+
'dart-3.1' => BuildRuntime::DART31(),
1526+
'dart-3.3' => BuildRuntime::DART33(),
1527+
'dart-3.5' => BuildRuntime::DART35(),
1528+
'dart-3.8' => BuildRuntime::DART38(),
1529+
'dart-3.9' => BuildRuntime::DART39(),
1530+
'dart-2.15' => BuildRuntime::DART215(),
1531+
'dart-2.16' => BuildRuntime::DART216(),
1532+
'dart-2.17' => BuildRuntime::DART217(),
1533+
'dart-2.18' => BuildRuntime::DART218(),
1534+
'dart-2.19' => BuildRuntime::DART219(),
1535+
'deno-1.21' => BuildRuntime::DENO121(),
1536+
'deno-1.24' => BuildRuntime::DENO124(),
1537+
'deno-1.35' => BuildRuntime::DENO135(),
1538+
'deno-1.40' => BuildRuntime::DENO140(),
1539+
'deno-1.46' => BuildRuntime::DENO146(),
1540+
'deno-2.0' => BuildRuntime::DENO20(),
1541+
'dotnet-6.0' => BuildRuntime::DOTNET60(),
1542+
'dotnet-7.0' => BuildRuntime::DOTNET70(),
1543+
'dotnet-8.0' => BuildRuntime::DOTNET80(),
1544+
'java-8.0' => BuildRuntime::JAVA80(),
1545+
'java-11.0' => BuildRuntime::JAVA110(),
1546+
'java-17.0' => BuildRuntime::JAVA170(),
1547+
'java-18.0' => BuildRuntime::JAVA180(),
1548+
'java-21.0' => BuildRuntime::JAVA210(),
1549+
'java-22' => BuildRuntime::JAVA22(),
1550+
'swift-5.5' => BuildRuntime::SWIFT55(),
1551+
'swift-5.8' => BuildRuntime::SWIFT58(),
1552+
'swift-5.9' => BuildRuntime::SWIFT59(),
1553+
'swift-5.10' => BuildRuntime::SWIFT510(),
1554+
'kotlin-1.6' => BuildRuntime::KOTLIN16(),
1555+
'kotlin-1.8' => BuildRuntime::KOTLIN18(),
1556+
'kotlin-1.9' => BuildRuntime::KOTLIN19(),
1557+
'kotlin-2.0' => BuildRuntime::KOTLIN20(),
1558+
'cpp-17' => BuildRuntime::CPP17(),
1559+
'cpp-20' => BuildRuntime::CPP20(),
1560+
'bun-1.0' => BuildRuntime::BUN10(),
1561+
'bun-1.1' => BuildRuntime::BUN11(),
1562+
'go-1.23' => BuildRuntime::GO123(),
1563+
'static-1' => BuildRuntime::STATIC1(),
1564+
'flutter-3.24' => BuildRuntime::FLUTTER324(),
1565+
'flutter-3.27' => BuildRuntime::FLUTTER327(),
1566+
'flutter-3.29' => BuildRuntime::FLUTTER329(),
1567+
'flutter-3.32' => BuildRuntime::FLUTTER332(),
1568+
'flutter-3.35' => BuildRuntime::FLUTTER335(),
1569+
default => throw new \Exception('Invalid Build Runtime: ' . $resource->getBuildRuntime()),
1570+
};
1571+
1572+
$framework = match ($resource->getFramework()) {
1573+
'analog' => Framework::ANALOG(),
1574+
'angular' => Framework::ANGULAR(),
1575+
'astro' => Framework::ASTRO(),
1576+
'flutter', 'flutter-web' => Framework::FLUTTER(),
1577+
'lynx' => Framework::LYNX(),
1578+
'nextjs' => Framework::NEXTJS(),
1579+
'nuxt' => Framework::NUXT(),
1580+
'react' => Framework::REACT(),
1581+
'react-native' => Framework::REACTNATIVE(),
1582+
'remix' => Framework::REMIX(),
1583+
'svelte-kit' => Framework::SVELTEKIT(),
1584+
'tanstack-start' => Framework::TANSTACKSTART(),
1585+
'vite' => Framework::VITE(),
1586+
'vue' => Framework::VUE(),
1587+
default => Framework::OTHER(),
1588+
};
1589+
1590+
$adapter = match ($resource->getAdapter()) {
1591+
'static' => Adapter::STATIC(),
1592+
'ssr' => Adapter::SSR(),
1593+
default => null,
1594+
};
1595+
1596+
$this->sites->create(
1597+
$resource->getId(),
1598+
$resource->getSiteName(),
1599+
$framework,
1600+
$buildRuntime,
1601+
$resource->getEnabled(),
1602+
$resource->getLogging(),
1603+
$resource->getTimeout(),
1604+
$resource->getInstallCommand(),
1605+
$resource->getBuildCommand(),
1606+
$resource->getOutputDirectory(),
1607+
$adapter,
1608+
fallbackFile: $resource->getFallbackFile(),
1609+
specification: $resource->getSpecification(),
1610+
);
1611+
break;
1612+
case Resource::TYPE_SITE_VARIABLE:
1613+
/** @var SiteEnvVar $resource */
1614+
$this->sites->createVariable(
1615+
$resource->getSite()->getId(),
1616+
$resource->getKey(),
1617+
$resource->getValue()
1618+
);
1619+
break;
1620+
case Resource::TYPE_SITE_DEPLOYMENT:
1621+
/** @var SiteDeployment $resource */
1622+
return $this->importSiteDeployment($resource);
1623+
}
1624+
1625+
$resource->setStatus(Resource::STATUS_SUCCESS);
1626+
1627+
return $resource;
1628+
}
1629+
1630+
/**
1631+
* @throws AppwriteException
1632+
* @throws \Exception
1633+
*/
1634+
private function importSiteDeployment(SiteDeployment $deployment): Resource
1635+
{
1636+
$siteId = $deployment->getSite()->getId();
1637+
1638+
if ($deployment->getSize() <= Transfer::STORAGE_MAX_CHUNK_SIZE) {
1639+
$response = $this->client->call(
1640+
'POST',
1641+
"/sites/{$siteId}/deployments",
1642+
[
1643+
'content-type' => 'multipart/form-data',
1644+
],
1645+
[
1646+
'siteId' => $siteId,
1647+
'code' => new \CURLFile('data://application/gzip;base64,' . base64_encode($deployment->getData()), 'application/gzip', 'deployment.tar.gz'),
1648+
'activate' => $deployment->getActivated(),
1649+
]
1650+
);
1651+
1652+
if (!\is_array($response) || !isset($response['$id'])) {
1653+
throw new \Exception('Site deployment creation failed');
1654+
}
1655+
1656+
$deployment->setStatus(Resource::STATUS_SUCCESS);
1657+
1658+
return $deployment;
1659+
}
1660+
1661+
$response = $this->client->call(
1662+
'POST',
1663+
"/sites/{$siteId}/deployments",
1664+
[
1665+
'content-type' => 'multipart/form-data',
1666+
'content-range' => 'bytes ' . ($deployment->getStart()) . '-' . ($deployment->getEnd() == ($deployment->getSize() - 1) ? $deployment->getSize() : $deployment->getEnd()) . '/' . $deployment->getSize(),
1667+
'x-appwrite-id' => $deployment->getId(),
1668+
],
1669+
[
1670+
'siteId' => $siteId,
1671+
'code' => new \CURLFile('data://application/gzip;base64,' . base64_encode($deployment->getData()), 'application/gzip', 'deployment.tar.gz'),
1672+
'activate' => $deployment->getActivated(),
1673+
]
1674+
);
1675+
1676+
if (!\is_array($response) || !isset($response['$id'])) {
1677+
throw new \Exception('Site deployment creation failed');
1678+
}
1679+
1680+
if ($deployment->getStart() === 0) {
1681+
$deployment->setId($response['$id']);
1682+
}
1683+
1684+
if ($deployment->getEnd() == ($deployment->getSize() - 1)) {
1685+
$deployment->setStatus(Resource::STATUS_SUCCESS);
1686+
} else {
1687+
$deployment->setStatus(Resource::STATUS_PENDING);
1688+
}
1689+
1690+
return $deployment;
1691+
}
1692+
14681693
private function validateFieldsForIndexes(Index $resource, UtopiaDocument $table, array &$lengths)
14691694
{
14701695
/**

src/Migration/Destinations/CSV.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
namespace Utopia\Migration\Destinations;
44

5-
use Utopia\Console;
65
use Utopia\Database\Exception\Authorization;
76
use Utopia\Database\Exception\Conflict;
87
use Utopia\Database\Exception\Structure;
98
use Utopia\Migration\Destination;
109
use Utopia\Migration\Resource as UtopiaResource;
1110
use Utopia\Migration\Resources\Database\Row;
1211
use Utopia\Migration\Transfer;
12+
use Utopia\Migration\Warning;
1313
use Utopia\Storage\Device;
1414
use Utopia\Storage\Device\Local;
1515

@@ -185,7 +185,12 @@ public function shutdown(): void
185185
} finally {
186186
// Clean up the temporary directory
187187
if (!$this->local->deletePath('') || $this->local->exists($this->local->getRoot())) {
188-
Console::error('Error cleaning up: ' . $this->local->getRoot());
188+
$this->addWarning(new Warning(
189+
UtopiaResource::TYPE_ROW,
190+
Transfer::GROUP_DATABASES,
191+
'Error cleaning up: ' . $this->local->getRoot(),
192+
$this->resourceId
193+
));
189194
}
190195
}
191196
}

src/Migration/Destinations/JSON.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Utopia\Migration\Destinations;
44

55
use Exception;
6-
use Utopia\Console;
76
use Utopia\Database\Exception\Authorization;
87
use Utopia\Database\Exception\Conflict;
98
use Utopia\Database\Exception\Structure;
@@ -12,6 +11,7 @@
1211
use Utopia\Migration\Resource as UtopiaResource;
1312
use Utopia\Migration\Resources\Database\Row;
1413
use Utopia\Migration\Transfer;
14+
use Utopia\Migration\Warning;
1515
use Utopia\Storage\Device;
1616
use Utopia\Storage\Device\Local;
1717

@@ -212,7 +212,12 @@ public function shutdown(): void
212212
} finally {
213213
// Clean up the temporary directory
214214
if (!$this->local->deletePath('') || $this->local->exists($this->local->getRoot())) {
215-
Console::error('Error cleaning up: ' . $this->local->getRoot());
215+
$this->addWarning(new Warning(
216+
UtopiaResource::TYPE_ROW,
217+
Transfer::GROUP_DATABASES,
218+
'Error cleaning up: ' . $this->local->getRoot(),
219+
$this->resourceId
220+
));
216221
}
217222
}
218223
}

0 commit comments

Comments
 (0)