From f9ed35ed8aee72306e085bc30aa3c56ed61f9f73 Mon Sep 17 00:00:00 2001 From: eldadfux Date: Thu, 19 Feb 2026 20:28:29 +0100 Subject: [PATCH 1/7] Enhance error handling for project database configuration * Added checks to ensure project references a valid database and throws exceptions if not configured. * Improved error messaging for non-existent projects in VCS controller. --- app/controllers/api/vcs.php | 3 +++ app/init/resources.php | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 67cd8d8ea8..6dd18ed0f3 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -36,6 +36,9 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $projectId = $repository->getAttribute('projectId'); $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND, 'Repository references non-existent project'); + } $dbForProject = $getProjectDB($project); $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; diff --git a/app/init/resources.php b/app/init/resources.php index 0bb5b17ce6..295e6125ae 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -565,11 +565,16 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor return $dbForPlatform; } + $database = $project->getAttribute('database'); + if ($database === null || $database === '') { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Project database is not configured'); + } + try { - $dsn = new DSN($project->getAttribute('database')); + $dsn = new DSN($database); } catch (\InvalidArgumentException) { // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); + $dsn = new DSN('mysql://' . $database); } $adapter = new DatabasePool($pools->get($dsn->getHost())); @@ -829,11 +834,16 @@ Http::setResource('getProjectDB', function (Group $pools, Database $dbForPlatfor return $dbForPlatform; } + $database = $project->getAttribute('database'); + if ($database === null || $database === '') { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Project database is not configured'); + } + try { - $dsn = new DSN($project->getAttribute('database')); + $dsn = new DSN($database); } catch (\InvalidArgumentException) { // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); + $dsn = new DSN('mysql://' . $database); } $configure = (function (Database $database) use ($project, $dsn, $authorization) { From a9d2fed1baa597994623606f98fcad0b44ffdd61 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 20 Feb 2026 14:02:16 +0530 Subject: [PATCH 2/7] chore: split sdk release artifacts from automation --- app/config/sdks.php | 14 +++++++------- .../examples/projects/create-schedule.md | 7 +++++++ .../console-cli/examples/projects/get-schedule.md | 5 +++++ .../examples/projects/list-schedules.md | 4 ++++ docs/sdks/android/CHANGELOG.md | 6 ++++++ docs/sdks/apple/CHANGELOG.md | 6 ++++++ docs/sdks/cli/CHANGELOG.md | 5 +++++ docs/sdks/flutter/CHANGELOG.md | 9 +++++++++ docs/sdks/react-native/CHANGELOG.md | 4 ++++ docs/sdks/web/CHANGELOG.md | 6 ++++++ 10 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 docs/examples/1.8.x/console-cli/examples/projects/create-schedule.md create mode 100644 docs/examples/1.8.x/console-cli/examples/projects/get-schedule.md create mode 100644 docs/examples/1.8.x/console-cli/examples/projects/list-schedules.md diff --git a/app/config/sdks.php b/app/config/sdks.php index 1bf2725785..cb5b14fe62 100644 --- a/app/config/sdks.php +++ b/app/config/sdks.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '22.3.1', + 'version' => '22.4.0', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -60,7 +60,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '21.1.0', + 'version' => '21.4.0', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -79,7 +79,7 @@ return [ [ 'key' => 'apple', 'name' => 'Apple', - 'version' => '14.1.0', + 'version' => '14.3.0', 'url' => 'https://github.com/appwrite/sdk-for-apple', 'package' => 'https://github.com/appwrite/sdk-for-apple', 'enabled' => true, @@ -117,7 +117,7 @@ return [ 'key' => 'android', 'name' => 'Android', 'namespace' => 'io.appwrite', - 'version' => '12.1.0', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-android', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android', 'enabled' => true, @@ -140,7 +140,7 @@ return [ [ 'key' => 'react-native', 'name' => 'React Native', - 'version' => '0.23.1', + 'version' => '0.24.0', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, @@ -208,7 +208,7 @@ return [ [ 'key' => 'web', 'name' => 'Console', - 'version' => '0.3.0', + 'version' => '22.4.0', 'url' => '', 'package' => '', 'enabled' => true, @@ -227,7 +227,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '13.4.0', + 'version' => '13.5.0', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/docs/examples/1.8.x/console-cli/examples/projects/create-schedule.md b/docs/examples/1.8.x/console-cli/examples/projects/create-schedule.md new file mode 100644 index 0000000000..8eb8fd2c55 --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/projects/create-schedule.md @@ -0,0 +1,7 @@ +```bash +appwrite projects create-schedule \ + --project-id \ + --resource-type function \ + --resource-id \ + --schedule '' +``` diff --git a/docs/examples/1.8.x/console-cli/examples/projects/get-schedule.md b/docs/examples/1.8.x/console-cli/examples/projects/get-schedule.md new file mode 100644 index 0000000000..45f8e0429f --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/projects/get-schedule.md @@ -0,0 +1,5 @@ +```bash +appwrite projects get-schedule \ + --project-id \ + --schedule-id +``` diff --git a/docs/examples/1.8.x/console-cli/examples/projects/list-schedules.md b/docs/examples/1.8.x/console-cli/examples/projects/list-schedules.md new file mode 100644 index 0000000000..f2b04e9f6b --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/projects/list-schedules.md @@ -0,0 +1,4 @@ +```bash +appwrite projects list-schedules \ + --project-id +``` diff --git a/docs/sdks/android/CHANGELOG.md b/docs/sdks/android/CHANGELOG.md index 8b3298ebca..95b2f3423e 100644 --- a/docs/sdks/android/CHANGELOG.md +++ b/docs/sdks/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 12.2.0 + +* Added Channel<_Document>.upsert() and Channel<_Row>.upsert() API methods to upsert documents and rows in channels. +* Added new query filters: containsAny(attribute, List) and containsAll(attribute, List) for advanced matching on array/relationship attributes. +* Realtime improvements: improved WebSocket lifecycle and connection handling. Introduced generation-based checks to avoid processing messages from stale sockets and ensure sequential socket recreation on reconnects. + ## 12.1.0 * Add `queries` parameter to Realtime subscriptions for filtering events diff --git a/docs/sdks/apple/CHANGELOG.md b/docs/sdks/apple/CHANGELOG.md index 13779f095e..e25680b6c3 100644 --- a/docs/sdks/apple/CHANGELOG.md +++ b/docs/sdks/apple/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 14.3.0 + +* Added upsert() support for RealtimeChannel on both Document and Row variants to perform upsert operations over real-time channels. +* Introduced new Query filter methods: contains(_:, value:), containsAny(_:, value: [Any]), containsAll(_:, value: [Any]) for enhanced querying capabilities (substring and multi-value containment). +* Documentation and packaging updates to align with the new release: README dependency example updated from 14.2.0 to 14.1.0, and server compatibility note updated to indicate Appwrite server version 1.8.x compatibility. + ## 14.1.0 * Add `queries` parameter to Realtime subscriptions for filtering events diff --git a/docs/sdks/cli/CHANGELOG.md b/docs/sdks/cli/CHANGELOG.md index 9d83abe9c1..f5afc2e5d2 100644 --- a/docs/sdks/cli/CHANGELOG.md +++ b/docs/sdks/cli/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 13.5.0 + +* New: Added CLI commands under projects: `list-schedules`, `create-schedule`, and `get-schedule` for managing project schedules. +* Packaging/build: Updated packaging to support explicit ESM/CJS outputs with exports. main now points to dist/index.cjs, module to dist/index.js, and exports include type and entry-point mappings. This enables better compatibility for both ESM and CommonJS users. + ## 13.4.0 * Add `--queries` option to `list-keys` command diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index d6b62f2453..db327d3d9c 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## 21.4.0 + +* Added upsert() to DocumentChannel and RowChannel to support upsert operations on documents and rows. +* Added Query.contains, Query.containsAny, and Query.containsAll for enhanced filtering capabilities. + +## 21.3.0 + +* Added memberships realtime channel helper + ## 21.1.0 * Add `queries` parameter to Realtime subscriptions for filtering events diff --git a/docs/sdks/react-native/CHANGELOG.md b/docs/sdks/react-native/CHANGELOG.md index 332b27ada4..9a2e91a9e5 100644 --- a/docs/sdks/react-native/CHANGELOG.md +++ b/docs/sdks/react-native/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log +## 0.24.0 + +* Added Query.contains, Query.containsAny, and Query.containsAll for enhanced filtering capabilities. + ## 0.23.1 * Add `upsert` method to Realtime `Channels` helper class diff --git a/docs/sdks/web/CHANGELOG.md b/docs/sdks/web/CHANGELOG.md index a91f186fc4..cfdb85af7e 100644 --- a/docs/sdks/web/CHANGELOG.md +++ b/docs/sdks/web/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 22.4.0 + +* Added Query.containsAny(attribute, value[]) to filter resources where the attribute contains any of the given values. +* Added Query.containsAll(attribute, value[]) to filter resources where the attribute contains all of the given values. +* Updated Query.contains documentation to clarify behavior: string attributes are matched by substring, and for array attributes use containsAny/containsAll. + ## 22.3.1 * Add `upsert` method to Realtime `Channels` helper class From 02951064efbdf33c1119666ddc1c8dc0812c42e5 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 20 Feb 2026 14:09:44 +0530 Subject: [PATCH 3/7] bump composer --- composer.lock | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/composer.lock b/composer.lock index f17670f7b1..2d18eea823 100644 --- a/composer.lock +++ b/composer.lock @@ -3797,16 +3797,16 @@ }, { "name": "utopia-php/database", - "version": "5.3.1", + "version": "5.3.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "e3305f6ca64eb5dd715e30212fd32d5d834a3a46" + "reference": "19305fc487df4f7b990350463914c1113cc6dab1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/e3305f6ca64eb5dd715e30212fd32d5d834a3a46", - "reference": "e3305f6ca64eb5dd715e30212fd32d5d834a3a46", + "url": "https://api.github.com/repos/utopia-php/database/zipball/19305fc487df4f7b990350463914c1113cc6dab1", + "reference": "19305fc487df4f7b990350463914c1113cc6dab1", "shasum": "" }, "require": { @@ -3849,22 +3849,22 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/5.3.1" + "source": "https://github.com/utopia-php/database/tree/5.3.2" }, - "time": "2026-02-18T07:15:40+00:00" + "time": "2026-02-18T11:59:15+00:00" }, { "name": "utopia-php/detector", - "version": "0.2.3", + "version": "0.2.4", "source": { "type": "git", "url": "https://github.com/utopia-php/detector.git", - "reference": "c1f49b3e82250c3256ffba48aa9737d6c17a243a" + "reference": "a564381108518ce6d18b6ab441f1448bd8355afd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/detector/zipball/c1f49b3e82250c3256ffba48aa9737d6c17a243a", - "reference": "c1f49b3e82250c3256ffba48aa9737d6c17a243a", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/a564381108518ce6d18b6ab441f1448bd8355afd", + "reference": "a564381108518ce6d18b6ab441f1448bd8355afd", "shasum": "" }, "require": { @@ -3894,9 +3894,9 @@ ], "support": { "issues": "https://github.com/utopia-php/detector/issues", - "source": "https://github.com/utopia-php/detector/tree/0.2.3" + "source": "https://github.com/utopia-php/detector/tree/0.2.4" }, - "time": "2025-11-24T15:52:51+00:00" + "time": "2026-02-17T11:26:34+00:00" }, { "name": "utopia-php/di", @@ -3948,16 +3948,16 @@ }, { "name": "utopia-php/dns", - "version": "1.6.3", + "version": "1.6.5", "source": { "type": "git", "url": "https://github.com/utopia-php/dns.git", - "reference": "c46a13c42bc19365985264a6fdaaaf7d8e736d3e" + "reference": "574327f0f5fabefa7048030c5634cde33ad10640" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/dns/zipball/c46a13c42bc19365985264a6fdaaaf7d8e736d3e", - "reference": "c46a13c42bc19365985264a6fdaaaf7d8e736d3e", + "url": "https://api.github.com/repos/utopia-php/dns/zipball/574327f0f5fabefa7048030c5634cde33ad10640", + "reference": "574327f0f5fabefa7048030c5634cde33ad10640", "shasum": "" }, "require": { @@ -3999,9 +3999,9 @@ ], "support": { "issues": "https://github.com/utopia-php/dns/issues", - "source": "https://github.com/utopia-php/dns/tree/1.6.3" + "source": "https://github.com/utopia-php/dns/tree/1.6.5" }, - "time": "2026-02-17T10:45:46+00:00" + "time": "2026-02-19T16:06:46+00:00" }, { "name": "utopia-php/domains", @@ -4214,16 +4214,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.39", + "version": "0.33.40", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "409a258814d664d3a50fa2f48b6695679334d30b" + "reference": "0ba25e1282c6a2f849053f7ccf28d567c2c321b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/409a258814d664d3a50fa2f48b6695679334d30b", - "reference": "409a258814d664d3a50fa2f48b6695679334d30b", + "url": "https://api.github.com/repos/utopia-php/http/zipball/0ba25e1282c6a2f849053f7ccf28d567c2c321b1", + "reference": "0ba25e1282c6a2f849053f7ccf28d567c2c321b1", "shasum": "" }, "require": { @@ -4257,9 +4257,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.39" + "source": "https://github.com/utopia-php/http/tree/0.33.40" }, - "time": "2026-02-11T06:33:42+00:00" + "time": "2026-02-19T13:00:08+00:00" }, { "name": "utopia-php/image", @@ -5385,16 +5385,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.9.3", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "5a8a304e404c84539f3ac6562c736f8c7ef2bef2" + "reference": "fd08ddfefc7b07870b0fa8616c6d13714b2481c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5a8a304e404c84539f3ac6562c736f8c7ef2bef2", - "reference": "5a8a304e404c84539f3ac6562c736f8c7ef2bef2", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/fd08ddfefc7b07870b0fa8616c6d13714b2481c8", + "reference": "fd08ddfefc7b07870b0fa8616c6d13714b2481c8", "shasum": "" }, "require": { @@ -5430,9 +5430,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.9.3" + "source": "https://github.com/appwrite/sdk-generator/tree/1.10.1" }, - "time": "2026-02-17T11:48:05+00:00" + "time": "2026-02-20T07:22:19+00:00" }, { "name": "doctrine/annotations", @@ -8885,7 +8885,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 8e4fddddbc91e02a9a53621f5e6511184a5859cb Mon Sep 17 00:00:00 2001 From: "Eldad A. Fux" Date: Fri, 20 Feb 2026 11:24:42 +0100 Subject: [PATCH 4/7] Update app/init/resources.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matej Bačo --- app/init/resources.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index 295e6125ae..ef43ab2e09 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -565,8 +565,12 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor return $dbForPlatform; } - $database = $project->getAttribute('database'); - if ($database === null || $database === '') { + if ($project->isEmpty()) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Project is not configured'); + } + + $database = $project->getAttribute('database', ''); + if (empty($database)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Project database is not configured'); } From 92439ef0c41a162468931a2f14227d2653656534 Mon Sep 17 00:00:00 2001 From: eldadfux Date: Fri, 20 Feb 2026 11:39:28 +0100 Subject: [PATCH 5/7] format --- app/init/resources.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index ef43ab2e09..cb8dcd91eb 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -565,10 +565,6 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor return $dbForPlatform; } - if ($project->isEmpty()) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Project is not configured'); - } - $database = $project->getAttribute('database', ''); if (empty($database)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Project database is not configured'); From 0f3ea91d5d909de3086ae62c4bcb1cc017dc226e Mon Sep 17 00:00:00 2001 From: "Eldad A. Fux" Date: Fri, 20 Feb 2026 11:41:09 +0100 Subject: [PATCH 6/7] Update app/init/resources.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matej Bačo --- app/init/resources.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index cb8dcd91eb..157b5e5f64 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -834,8 +834,8 @@ Http::setResource('getProjectDB', function (Group $pools, Database $dbForPlatfor return $dbForPlatform; } - $database = $project->getAttribute('database'); - if ($database === null || $database === '') { + $database = $project->getAttribute('database', ''); + if (empty($database)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Project database is not configured'); } From 15b5202c16a769f360b3adb5ee1fefeab8ad877a Mon Sep 17 00:00:00 2001 From: Hemachandar <132386067+hmacr@users.noreply.github.com> Date: Fri, 20 Feb 2026 17:37:12 +0530 Subject: [PATCH 7/7] Check project access only when user is present (#11370) --- app/controllers/shared/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 2afcd77a6f..f7b4613022 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -343,7 +343,7 @@ Http::init() * But, for actions on resources (sites, functions, etc.) in a non-console project, we explicitly check * whether the admin user has necessary permission on the project (sites, functions, etc. don't have permissions associated to them). */ - if (empty($apiKey) && $project->getId() !== 'console' && $mode === APP_MODE_ADMIN) { + if (empty($apiKey) && !$user->isEmpty() && $project->getId() !== 'console' && $mode === APP_MODE_ADMIN) { $input = new Input(Database::PERMISSION_READ, $project->getPermissionsByType(Database::PERMISSION_READ)); $initialStatus = $authorization->getStatus(); $authorization->enable();