diff --git a/.env b/.env index 1947ddff1a..ad973f24f9 100644 --- a/.env +++ b/.env @@ -130,3 +130,4 @@ _APP_PROJECT_REGIONS=default _APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000 _APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main _APP_TRUSTED_HEADERS=x-forwarded-for +_APP_POOL_ADAPTER=stack \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index ac8cff0884..e848b6f0b5 100755 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ --no-plugins --no-scripts --prefer-dist \ `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` -FROM appwrite/base:0.10.6 AS base +FROM appwrite/base:0.11.5 AS base LABEL maintainer="team@appwrite.io" diff --git a/app/config/templates/function.php b/app/config/templates/function.php index e10cd4648c..6bdfb5ab80 100644 --- a/app/config/templates/function.php +++ b/app/config/templates/function.php @@ -20,6 +20,34 @@ function getRuntimes($runtimes, $commands, $entrypoint, $providerRootDirectory, })); } + +class FunctionUseCases +{ + public const STARTER = 'starter'; + public const DATABASES = 'databases'; + public const AI = 'ai'; + public const MESSAGING = 'messaging'; + public const UTILITIES = 'utilities'; + public const DEV_TOOLS = 'dev-tools'; + public const AUTH = 'auth'; + + /** + * @var array + */ + public static function getAll(): array + { + return [ + self::STARTER, + self::DATABASES, + self::AI, + self::MESSAGING, + self::UTILITIES, + self::DEV_TOOLS, + self::AUTH, + ]; + } +} + return [ [ 'icon' => 'icon-lightning-bolt', @@ -32,7 +60,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['starter'], + 'useCases' => [FunctionUseCases::STARTER], 'runtimes' => [ ...getRuntimes($templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/starter', $allowList), ...getRuntimes( @@ -73,7 +101,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['databases'], + 'useCases' => [FunctionUseCases::DATABASES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -119,7 +147,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['databases'], + 'useCases' => [FunctionUseCases::DATABASES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -164,7 +192,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['databases'], + 'useCases' => [FunctionUseCases::DATABASES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -218,7 +246,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['databases'], + 'useCases' => [FunctionUseCases::DATABASES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -257,7 +285,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['databases'], + 'useCases' => [FunctionUseCases::DATABASES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -326,7 +354,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -392,7 +420,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['messaging'], + 'useCases' => [FunctionUseCases::MESSAGING], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -459,7 +487,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -497,7 +525,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -548,7 +576,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['utilities'], + 'useCases' => [FunctionUseCases::UTILITIES], 'runtimes' => [ ...getRuntimes($templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/generate-pdf', $allowList) ], @@ -571,7 +599,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['dev-tools'], + 'useCases' => [FunctionUseCases::DEV_TOOLS], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -616,7 +644,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['utilities'], + 'useCases' => [FunctionUseCases::UTILITIES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -669,7 +697,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['databases'], + 'useCases' => [FunctionUseCases::DATABASES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -754,7 +782,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['databases'], + 'useCases' => [FunctionUseCases::DATABASES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -853,7 +881,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['messaging'], + 'useCases' => [FunctionUseCases::MESSAGING], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -946,7 +974,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['messaging'], + 'useCases' => [FunctionUseCases::MESSAGING], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1004,7 +1032,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['utilities'], + 'useCases' => [FunctionUseCases::UTILITIES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1091,7 +1119,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['utilities'], + 'useCases' => [FunctionUseCases::UTILITIES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1134,7 +1162,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['utilities'], + 'useCases' => [FunctionUseCases::UTILITIES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1193,7 +1221,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 30, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1229,7 +1257,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 30, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1265,7 +1293,7 @@ return [ 'events' => ['buckets.*.files.*.create'], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1325,7 +1353,7 @@ return [ 'events' => ['buckets.*.files.*.create'], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1385,7 +1413,7 @@ return [ 'events' => ['buckets.*.files.*.create'], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1448,7 +1476,7 @@ return [ ], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1508,7 +1536,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 300, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1545,7 +1573,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 300, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1589,7 +1617,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1632,7 +1660,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 300, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1669,7 +1697,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 30, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1734,7 +1762,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 30, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1799,7 +1827,7 @@ return [ 'cron' => '', 'events' => [], 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1856,7 +1884,7 @@ return [ 'cron' => '', 'events' => [], 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1899,7 +1927,7 @@ return [ 'cron' => '', 'events' => [], 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1942,7 +1970,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -1986,7 +2014,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 300, - 'useCases' => ['ai'], + 'useCases' => [FunctionUseCases::AI], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -2023,7 +2051,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['utilities'], + 'useCases' => [FunctionUseCases::UTILITIES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -2080,7 +2108,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['utilities'], + 'useCases' => [FunctionUseCases::UTILITIES], 'runtimes' => [ ...getRuntimes( $templateRuntimes['NODE'], @@ -2153,7 +2181,7 @@ return [ 'events' => [], 'cron' => '', 'timeout' => 15, - 'useCases' => ['auth'], + 'useCases' => [FunctionUseCases::AUTH], 'runtimes' => [ ...getRuntimes($templateRuntimes['DART'], 'dart pub get', 'lib/main.dart', 'dart/sign_in_with_apple', $allowList) ], diff --git a/app/config/templates/site.php b/app/config/templates/site.php index e330979597..50a9fb8d5d 100644 --- a/app/config/templates/site.php +++ b/app/config/templates/site.php @@ -13,7 +13,7 @@ $hostname = $platform['consoleHostname'] ?? ''; $url = $protocol . '://' . $hostname; -class UseCases +class SiteUseCases { public const PORTFOLIO = 'portfolio'; public const STARTER = 'starter'; @@ -21,9 +21,27 @@ class UseCases public const ECOMMERCE = 'ecommerce'; public const DOCUMENTATION = 'documentation'; public const BLOG = 'blog'; - public const AI = 'artificial intelligence'; + public const AI = 'ai'; public const FORMS = 'forms'; public const DASHBOARD = 'dashboard'; + + /** + * @var array + */ + public static function getAll(): array + { + return [ + self::PORTFOLIO, + self::STARTER, + self::EVENTS, + self::ECOMMERCE, + self::DOCUMENTATION, + self::BLOG, + self::AI, + self::FORMS, + self::DASHBOARD, + ]; + } } const TEMPLATE_FRAMEWORKS = [ @@ -188,7 +206,7 @@ return [ 'name' => 'Documentation template', 'tagline' => 'Modern site to store your knowledge with a clean design, full-text search, dark mode, and more.', 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::DOCUMENTATION], + 'useCases' => [SiteUseCases::DOCUMENTATION], 'screenshotDark' => $url . '/images/sites/templates/template-for-documentation-dark.png', 'screenshotLight' => $url . '/images/sites/templates/template-for-documentation-light.png', 'frameworks' => [ @@ -209,7 +227,7 @@ return [ // When we add Lynx with Appwrite SDK, use following tagline for it: // 'tagline' => 'Sample application built with Lynx, a cross-platform framework focused on performance.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-lynx-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-lynx-light.png', 'frameworks' => [ @@ -220,7 +238,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -228,7 +246,7 @@ return [ 'name' => 'Vitepress', 'tagline' => 'Platform for documentation and knowledge sharing powered by Vite.', 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::DOCUMENTATION], + 'useCases' => [SiteUseCases::DOCUMENTATION], 'screenshotDark' => $url . '/images/sites/templates/vitepress-dark.png', 'screenshotLight' => $url . '/images/sites/templates/vitepress-light.png', 'frameworks' => [ @@ -243,7 +261,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -251,7 +269,7 @@ return [ 'name' => 'Vuepress', 'tagline' => 'Platform for documentation and knowledge sharing powered by Vue.', 'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::DOCUMENTATION], + 'useCases' => [SiteUseCases::DOCUMENTATION], 'screenshotDark' => $url . '/images/sites/templates/vuepress-dark.png', 'screenshotLight' => $url . '/images/sites/templates/vuepress-light.png', 'frameworks' => [ @@ -266,7 +284,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -274,7 +292,7 @@ return [ 'name' => 'Docusaurus', 'tagline' => 'Platform for documentation and knowledge sharing powered by React.', 'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::DOCUMENTATION], + 'useCases' => [SiteUseCases::DOCUMENTATION], 'screenshotDark' => $url . '/images/sites/templates/docusaurus-dark.png', 'screenshotLight' => $url . '/images/sites/templates/docusaurus-light.png', 'frameworks' => [ @@ -289,7 +307,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -297,7 +315,7 @@ return [ 'name' => 'Nxt Lnk', 'tagline' => 'Personal website for creators to merge all URLs to social profiles.', 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::PORTFOLIO], + 'useCases' => [SiteUseCases::PORTFOLIO], 'screenshotDark' => $url . '/images/sites/templates/nxt-lnk-dark.png', 'screenshotLight' => $url . '/images/sites/templates/nxt-lnk-light.png', 'frameworks' => [ @@ -308,7 +326,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -316,7 +334,7 @@ return [ 'name' => 'Magic Portfolio', 'tagline' => 'Complex personal website to showcase your projects, articles, and more.', 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::PORTFOLIO], + 'useCases' => [SiteUseCases::PORTFOLIO], 'screenshotDark' => $url . '/images/sites/templates/magic-portfolio-dark.png', 'screenshotLight' => $url . '/images/sites/templates/magic-portfolio-light.png', 'frameworks' => [ @@ -327,7 +345,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -335,7 +353,7 @@ return [ 'name' => 'LittleLink', 'tagline' => 'Personal website for creators to merge all URLs to social profiles.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::PORTFOLIO], + 'useCases' => [SiteUseCases::PORTFOLIO], 'screenshotDark' => $url . '/images/sites/templates/littlelink-dark.png', 'screenshotLight' => $url . '/images/sites/templates/littlelink-light.png', 'frameworks' => [ @@ -346,7 +364,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -354,7 +372,7 @@ return [ 'name' => 'Logspot', 'tagline' => 'Website to publish changelogs of your application.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::BLOG], + 'useCases' => [SiteUseCases::BLOG], 'screenshotDark' => $url . '/images/sites/templates/logspot-dark.png', 'screenshotLight' => $url . '/images/sites/templates/logspot-light.png', 'frameworks' => [ @@ -368,7 +386,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -376,7 +394,7 @@ return [ 'name' => 'Astro Nano', 'tagline' => 'Minimal personal website to showcase your projects, articles, and more.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::PORTFOLIO], + 'useCases' => [SiteUseCases::PORTFOLIO], 'screenshotDark' => $url . '/images/sites/templates/astro-nano-dark.png', 'screenshotLight' => $url . '/images/sites/templates/astro-nano-light.png', 'frameworks' => [ @@ -389,7 +407,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -397,7 +415,7 @@ return [ 'name' => 'Astro Starlight', 'tagline' => 'Platform for documentation and knowledge sharing powered by Astro.', 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::DOCUMENTATION], + 'useCases' => [SiteUseCases::DOCUMENTATION], 'screenshotDark' => $url . '/images/sites/templates/astro-starlight-dark.png', 'screenshotLight' => $url . '/images/sites/templates/astro-starlight-light.png', 'frameworks' => [ @@ -410,7 +428,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -418,7 +436,7 @@ return [ 'name' => 'Astro Sphere', 'tagline' => 'Modern personal website to showcase your projects, articles, and more.', 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::PORTFOLIO], + 'useCases' => [SiteUseCases::PORTFOLIO], 'screenshotDark' => $url . '/images/sites/templates/astro-sphere-dark.png', 'screenshotLight' => $url . '/images/sites/templates/astro-sphere-light.png', 'frameworks' => [ @@ -431,7 +449,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -439,7 +457,7 @@ return [ 'name' => 'Astro Starlog', 'tagline' => 'Platform for publishing written content and media powered by Astro.', 'score' => 5, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::BLOG], + 'useCases' => [SiteUseCases::BLOG], 'screenshotDark' => $url . '/images/sites/templates/astro-starlog-dark.png', 'screenshotLight' => $url . '/images/sites/templates/astro-starlog-light.png', 'frameworks' => [ @@ -452,7 +470,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -460,7 +478,7 @@ return [ 'name' => 'Onelink', 'tagline' => 'Personal website for creators to merge all URLs to social profiles.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::PORTFOLIO], + 'useCases' => [SiteUseCases::PORTFOLIO], 'screenshotDark' => $url . '/images/sites/templates/onelink-dark.png', 'screenshotLight' => $url . '/images/sites/templates/onelink-light.png', 'frameworks' => [ @@ -474,13 +492,13 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ 'key' => 'starter-for-flutter', 'name' => 'Flutter starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Flutter application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-flutter-dark.png', @@ -525,7 +543,7 @@ return [ [ 'key' => 'starter-for-js', 'name' => 'JavaScript starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple JavaScript application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-js-dark.png', @@ -569,7 +587,7 @@ return [ [ 'key' => 'starter-for-angular', 'name' => 'Angular starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Angular application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-angular-dark.png', @@ -615,7 +633,7 @@ return [ [ 'key' => 'starter-for-astro', 'name' => 'Astro starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Astro application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-astro-dark.png', @@ -660,7 +678,7 @@ return [ [ 'key' => 'starter-for-analog', 'name' => 'Analog starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Analog application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-analog-dark.png', @@ -704,7 +722,7 @@ return [ [ 'key' => 'starter-for-remix', 'name' => 'Remix starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Remix application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-remix-dark.png', @@ -748,7 +766,7 @@ return [ [ 'key' => 'starter-for-svelte', 'name' => 'Svelte starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Svelte application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-svelte-dark.png', @@ -792,7 +810,7 @@ return [ [ 'key' => 'starter-for-react', 'name' => 'React starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple React application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-react-dark.png', @@ -836,7 +854,7 @@ return [ [ 'key' => 'starter-for-vue', 'name' => 'Vue starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Vue application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-vue-dark.png', @@ -880,7 +898,7 @@ return [ [ 'key' => 'starter-for-react-native', 'name' => 'React Native starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple React Native application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-react-native-dark.png', @@ -924,7 +942,7 @@ return [ [ 'key' => 'starter-for-nextjs', 'name' => 'Next.js starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Next.js application integrated with Appwrite SDK.', 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-nextjs-dark.png', @@ -968,7 +986,7 @@ return [ [ 'key' => 'starter-for-tanstack-start', 'name' => 'TanStack Start starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple TanStack Start application integrated with Appwrite SDK.', 'score' => 9, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-tanstack-start-dark.png', @@ -1012,7 +1030,7 @@ return [ [ 'key' => 'starter-for-nuxt', 'name' => 'Nuxt starter', - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'tagline' => 'Simple Nuxt application integrated with Appwrite SDK.', 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) 'screenshotDark' => $url . '/images/sites/templates/starter-for-nuxt-dark.png', @@ -1058,7 +1076,7 @@ return [ 'name' => 'Event template', 'tagline' => 'Hackathon landing page with support for project submissions.', 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::EVENTS], + 'useCases' => [SiteUseCases::EVENTS], 'screenshotDark' => $url . '/images/sites/templates/template-for-event-dark.png', 'screenshotLight' => $url . '/images/sites/templates/template-for-event-light.png', 'frameworks' => [ @@ -1096,7 +1114,7 @@ return [ 'name' => 'Portfolio template', 'tagline' => 'Simple personal website to showcase your projects, articles, and more.', 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::PORTFOLIO], + 'useCases' => [SiteUseCases::PORTFOLIO], 'screenshotDark' => $url . '/images/sites/templates/template-for-portfolio-dark.png', 'screenshotLight' => $url . '/images/sites/templates/template-for-portfolio-light.png', 'frameworks' => [ @@ -1115,7 +1133,7 @@ return [ 'name' => 'Store template', 'tagline' => 'E-commerce platform for selling products with Stripe integration.', 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::ECOMMERCE], + 'useCases' => [SiteUseCases::ECOMMERCE], 'screenshotDark' => $url . '/images/sites/templates/template-for-store-dark.png', 'screenshotLight' => $url . '/images/sites/templates/template-for-store-light.png', 'frameworks' => [ @@ -1159,7 +1177,7 @@ return [ 'name' => 'Blog template', 'tagline' => 'Platform for publishing written content and media.', 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::BLOG], + 'useCases' => [SiteUseCases::BLOG], 'screenshotDark' => $url . '/images/sites/templates/template-for-blog-dark.png', 'screenshotLight' => $url . '/images/sites/templates/template-for-blog-light.png', 'frameworks' => [ @@ -1178,7 +1196,7 @@ return [ 'name' => 'Astro playground', 'tagline' => 'A basic Astro website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-astro-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-astro-light.png', 'frameworks' => [ @@ -1189,7 +1207,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1197,7 +1215,7 @@ return [ 'name' => 'Remix playground', 'tagline' => 'A basic Remix website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-remix-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-remix-light.png', 'frameworks' => [ @@ -1208,7 +1226,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1216,7 +1234,7 @@ return [ 'name' => 'Next.js playground', 'tagline' => 'A basic Next.js website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-nextjs-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-nextjs-light.png', 'frameworks' => [ @@ -1227,7 +1245,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1235,7 +1253,7 @@ return [ 'name' => 'Flutter playground', 'tagline' => 'A basic Flutter website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-flutter-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-flutter-light.png', 'frameworks' => [ @@ -1246,7 +1264,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1254,7 +1272,7 @@ return [ 'name' => 'Vite playground', 'tagline' => 'A basic Vite website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-vite-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-vite-light.png', 'frameworks' => [ @@ -1265,7 +1283,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1273,7 +1291,7 @@ return [ 'name' => 'Angular playground', 'tagline' => 'A basic Angular website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-angular-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-angular-light.png', 'frameworks' => [ @@ -1285,7 +1303,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1293,7 +1311,7 @@ return [ 'name' => 'Analog playground', 'tagline' => 'A basic Analog website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-analog-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-analog-light.png', 'frameworks' => [ @@ -1304,7 +1322,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1312,7 +1330,7 @@ return [ 'name' => 'Svelte playground', 'tagline' => 'A basic Svelte website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-svelte-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-svelte-light.png', 'frameworks' => [ @@ -1323,7 +1341,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], @@ -1332,7 +1350,7 @@ return [ 'name' => 'React playground', 'tagline' => 'A basic React website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-react-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-react-light.png', 'frameworks' => [ @@ -1344,7 +1362,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], @@ -1353,7 +1371,7 @@ return [ 'name' => 'Vue playground', 'tagline' => 'A basic Vue website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-vue-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-vue-light.png', 'frameworks' => [ @@ -1364,7 +1382,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1372,7 +1390,7 @@ return [ 'name' => 'Nuxt playground', 'tagline' => 'A basic Nuxt website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-nuxt-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-nuxt-light.png', 'frameworks' => [ @@ -1383,7 +1401,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1391,7 +1409,7 @@ return [ 'name' => 'TanStack Start playground', 'tagline' => 'A basic TanStack Start website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-tanstack-start-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-tanstack-start-light.png', 'frameworks' => [ @@ -1402,7 +1420,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.5.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1410,7 +1428,7 @@ return [ 'name' => 'React Native playground', 'tagline' => 'A basic React Native website without Appwrite SDK integration.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/playground-for-react-native-dark.png', 'screenshotLight' => $url . '/images/sites/templates/playground-for-react-native-light.png', 'frameworks' => [ @@ -1421,7 +1439,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [], ], [ @@ -1429,7 +1447,7 @@ return [ 'name' => 'Lynx gallery', 'tagline' => 'A Lynx website showcasing gallery with smooth animations.', 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::STARTER], + 'useCases' => [SiteUseCases::STARTER], 'screenshotDark' => $url . '/images/sites/templates/gallery-for-lynx-dark.png', 'screenshotLight' => $url . '/images/sites/templates/gallery-for-lynx-light.png', 'frameworks' => [ @@ -1440,7 +1458,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.3.*', + 'providerVersion' => '0.7.*', 'variables' => [] ], [ @@ -1448,7 +1466,7 @@ return [ 'name' => 'Text-to-speech with ElevenLabs', 'tagline' => 'Next.js app that transforms text into natural, human-like speech using ElevenLabs', 'score' => 10, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::AI], + 'useCases' => [SiteUseCases::AI], 'screenshotDark' => $url . '/images/sites/templates/text-to-speech-dark.png', 'screenshotLight' => $url . '/images/sites/templates/text-to-speech-light.png', 'frameworks' => [ @@ -1459,7 +1477,7 @@ return [ 'vcsProvider' => 'github', 'providerRepositoryId' => 'templates-for-sites', 'providerOwner' => 'appwrite', - 'providerVersion' => '0.6.*', + 'providerVersion' => '0.7.*', 'variables' => [ [ 'name' => 'ELEVENLABS_API_KEY', @@ -1476,7 +1494,7 @@ return [ 'name' => 'CRM dashboard with React Admin', 'tagline' => 'A React-based admin dashboard template with CRM features.', 'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::DASHBOARD], + 'useCases' => [SiteUseCases::DASHBOARD], 'screenshotDark' => $url . '/images/sites/templates/crm-dashboard-react-admin-dark.png', 'screenshotLight' => $url . '/images/sites/templates/crm-dashboard-react-admin-light.png', 'frameworks' => [ @@ -1579,7 +1597,7 @@ return [ 'name' => 'Job applications form with Formspree', 'tagline' => 'A simple form submission template using Formspree.', 'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) - 'useCases' => [UseCases::FORMS], + 'useCases' => [SiteUseCases::FORMS], 'screenshotDark' => $url . '/images/sites/templates/job-applications-formspree-dark.png', 'screenshotLight' => $url . '/images/sites/templates/job-applications-formspree-light.png', 'frameworks' => [ diff --git a/app/init/registers.php b/app/init/registers.php index 9799c56914..8c596aae8e 100644 --- a/app/init/registers.php +++ b/app/init/registers.php @@ -23,6 +23,8 @@ use Utopia\Logger\Adapter\LogOwl; use Utopia\Logger\Adapter\Raygun; use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Logger; +use Utopia\Pools\Adapter\Stack as StackPool; +use Utopia\Pools\Adapter\Swoole as SwoolePool; use Utopia\Pools\Group; use Utopia\Pools\Pool; use Utopia\Queue; @@ -285,7 +287,9 @@ $register->set('pools', function () { default => throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'), }; - $pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) { + $poolAdapter = System::getEnv('_APP_POOL_ADAPTER', default: 'stack') === 'swoole' ? new SwoolePool() : new StackPool(); + + $pool = new Pool($poolAdapter, $name, $poolSize, function () use ($type, $resource, $dsn) { // Get Adapter switch ($type) { case 'database': diff --git a/composer.json b/composer.json index f5bab03697..4d9e779c94 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "ext-yaml": "*", "ext-dom": "*", "ext-redis": "*", - "ext-swoole": "*", + "ext-swoole": "6.*", "ext-pdo": "*", "ext-openssl": "*", "ext-zlib": "*", @@ -67,7 +67,7 @@ "utopia-php/migration": "1.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", - "utopia-php/pools": "0.8.*", + "utopia-php/pools": "1.*", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.15.*", "utopia-php/registry": "0.5.*", @@ -91,7 +91,7 @@ "ext-fileinfo": "*", "appwrite/sdk-generator": "*", "phpunit/phpunit": "9.*", - "swoole/ide-helper": "5.1.2", + "swoole/ide-helper": "6.*", "phpstan/phpstan": "1.8.*", "textalk/websocket": "1.5.*", "laravel/pint": "1.*", diff --git a/composer.lock b/composer.lock index fa86a0953f..cd6ded8a3f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "33da844fdf5648d1d1a027dfb6ae42bc", + "content-hash": "2aca1c8eeaa9fa338e389e3527cb6bd6", "packages": [ { "name": "adhocore/jwt", @@ -3719,16 +3719,16 @@ }, { "name": "utopia-php/cache", - "version": "0.13.2", + "version": "0.13.3", "source": { "type": "git", "url": "https://github.com/utopia-php/cache.git", - "reference": "5768498c9f451482f0bf3eede4d6452ddcd4a0f6" + "reference": "355707ab2c0090435059216165db86976b68a126" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cache/zipball/5768498c9f451482f0bf3eede4d6452ddcd4a0f6", - "reference": "5768498c9f451482f0bf3eede4d6452ddcd4a0f6", + "url": "https://api.github.com/repos/utopia-php/cache/zipball/355707ab2c0090435059216165db86976b68a126", + "reference": "355707ab2c0090435059216165db86976b68a126", "shasum": "" }, "require": { @@ -3736,7 +3736,7 @@ "ext-memcached": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/pools": "0.8.*", + "utopia-php/pools": "1.*", "utopia-php/telemetry": "*" }, "require-dev": { @@ -3765,9 +3765,9 @@ ], "support": { "issues": "https://github.com/utopia-php/cache/issues", - "source": "https://github.com/utopia-php/cache/tree/0.13.2" + "source": "https://github.com/utopia-php/cache/tree/0.13.3" }, - "time": "2025-12-17T08:55:43+00:00" + "time": "2026-01-16T07:54:34+00:00" }, { "name": "utopia-php/cli", @@ -3981,7 +3981,7 @@ "utopia-php/cache": "0.13.*", "utopia-php/framework": "0.33.*", "utopia-php/mongo": "0.11.*", - "utopia-php/pools": "0.8.*" + "utopia-php/pools": "1.*" }, "require-dev": { "fakerphp/faker": "1.23.*", @@ -4796,16 +4796,16 @@ }, { "name": "utopia-php/pools", - "version": "0.8.3", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "ad7d6ba946376e81c603204285ce9a674b6502b8" + "reference": "b7d8dd00306cdd8bf3ff6f1dc90caeaf27dabeb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/ad7d6ba946376e81c603204285ce9a674b6502b8", - "reference": "ad7d6ba946376e81c603204285ce9a674b6502b8", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/b7d8dd00306cdd8bf3ff6f1dc90caeaf27dabeb1", + "reference": "b7d8dd00306cdd8bf3ff6f1dc90caeaf27dabeb1", "shasum": "" }, "require": { @@ -4815,7 +4815,8 @@ "require-dev": { "laravel/pint": "1.*", "phpstan/phpstan": "1.*", - "phpunit/phpunit": "11.*" + "phpunit/phpunit": "11.*", + "swoole/ide-helper": "6.*" }, "type": "library", "autoload": { @@ -4842,9 +4843,9 @@ ], "support": { "issues": "https://github.com/utopia-php/pools/issues", - "source": "https://github.com/utopia-php/pools/tree/0.8.3" + "source": "https://github.com/utopia-php/pools/tree/1.0.2" }, - "time": "2025-12-17T09:35:18+00:00" + "time": "2026-01-28T13:12:36+00:00" }, { "name": "utopia-php/preloader", @@ -4901,16 +4902,16 @@ }, { "name": "utopia-php/queue", - "version": "0.15.0", + "version": "0.15.1", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "6abb268ba7ec00dea4e5201b007776ea1bce9242" + "reference": "e551606385990ec7901d222017c4cfc2749a518c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/6abb268ba7ec00dea4e5201b007776ea1bce9242", - "reference": "6abb268ba7ec00dea4e5201b007776ea1bce9242", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/e551606385990ec7901d222017c4cfc2749a518c", + "reference": "e551606385990ec7901d222017c4cfc2749a518c", "shasum": "" }, "require": { @@ -4919,7 +4920,7 @@ "utopia-php/console": "0.0.*", "utopia-php/fetch": "0.5.*", "utopia-php/framework": "0.33.*", - "utopia-php/pools": "0.8.*", + "utopia-php/pools": "1.*", "utopia-php/telemetry": "*" }, "require-dev": { @@ -4961,9 +4962,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.15.0" + "source": "https://github.com/utopia-php/queue/tree/0.15.1" }, - "time": "2026-01-06T12:41:51+00:00" + "time": "2026-01-16T07:54:54+00:00" }, { "name": "utopia-php/registry", @@ -8007,16 +8008,16 @@ }, { "name": "swoole/ide-helper", - "version": "5.1.2", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/swoole/ide-helper.git", - "reference": "33ec7af9111b76d06a70dd31191cc74793551112" + "reference": "6f12243dce071714c5febe059578d909698f9a52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swoole/ide-helper/zipball/33ec7af9111b76d06a70dd31191cc74793551112", - "reference": "33ec7af9111b76d06a70dd31191cc74793551112", + "url": "https://api.github.com/repos/swoole/ide-helper/zipball/6f12243dce071714c5febe059578d909698f9a52", + "reference": "6f12243dce071714c5febe059578d909698f9a52", "shasum": "" }, "type": "library", @@ -8033,9 +8034,9 @@ "description": "IDE help files for Swoole.", "support": { "issues": "https://github.com/swoole/ide-helper/issues", - "source": "https://github.com/swoole/ide-helper/tree/5.1.2" + "source": "https://github.com/swoole/ide-helper/tree/6.0.2" }, - "time": "2024-02-01T22:28:11+00:00" + "time": "2025-03-23T07:31:41+00:00" }, { "name": "symfony/console", @@ -9063,7 +9064,7 @@ "ext-yaml": "*", "ext-dom": "*", "ext-redis": "*", - "ext-swoole": "*", + "ext-swoole": "6.*", "ext-pdo": "*", "ext-openssl": "*", "ext-zlib": "*", diff --git a/docker-compose.yml b/docker-compose.yml index b32c41f802..0eee94a999 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -112,6 +112,7 @@ services: - _APP_ENV - _APP_EDITION - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_LOCALE - _APP_COMPRESSION_ENABLED - _APP_COMPRESSION_MIN_SIZE_BYTES @@ -301,6 +302,7 @@ services: - _APP_LOGGING_CONFIG - _APP_LOGGING_CONFIG_REALTIME - _APP_DATABASE_SHARED_TABLES + - _APP_POOL_ADAPTER=swoole appwrite-worker-audits: entrypoint: worker-audits @@ -318,6 +320,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -349,6 +352,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_EMAIL_SECURITY - _APP_DB_HOST @@ -386,6 +390,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -443,6 +448,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -477,6 +483,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_EXECUTOR_SECRET - _APP_EXECUTOR_HOST @@ -550,6 +557,7 @@ services: # Basic - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_LOGGING_CONFIG # Database - _APP_OPENSSL_KEY_V1 @@ -607,6 +615,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - _APP_DOMAIN_TARGET_CNAME @@ -649,6 +658,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - _APP_OPTIONS_FORCE_HTTPS @@ -692,6 +702,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_SYSTEM_EMAIL_NAME - _APP_SYSTEM_EMAIL_ADDRESS @@ -726,6 +737,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -783,6 +795,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - _APP_DOMAIN_TARGET_CNAME @@ -822,6 +835,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_DOMAIN - _APP_DOMAIN_TARGET_CNAME - _APP_DOMAIN_TARGET_AAAA @@ -866,6 +880,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_DOMAIN - _APP_DOMAIN_TARGET_CNAME - _APP_DOMAIN_TARGET_AAAA @@ -904,6 +919,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_DB_HOST - _APP_DB_PORT @@ -935,6 +951,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_DB_HOST - _APP_DB_PORT @@ -966,6 +983,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_DB_HOST - _APP_DB_PORT @@ -997,6 +1015,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -1025,6 +1044,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -1052,6 +1072,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_POOL_ADAPTER - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php index 26b85c8065..91cb787b70 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php @@ -7,6 +7,7 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; +use FunctionUseCases; use Utopia\Config\Config; use Utopia\Database\Document; use Utopia\Platform\Action; @@ -50,7 +51,7 @@ class XList extends Base ] )) ->param('runtimes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('runtimes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of runtimes allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' runtimes are allowed.', true) - ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools','starter','databases','ai','messaging','utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) + ->param('useCases', [], new ArrayList(new WhiteList(FunctionUseCases::getAll()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php index 4fe00f3edf..4dea0908cf 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php @@ -7,6 +7,7 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; +use SiteUseCases; use Utopia\Config\Config; use Utopia\Database\Document; use Utopia\Platform\Action; @@ -49,7 +50,7 @@ class XList extends Base ] )) ->param('frameworks', [], new ArrayList(new WhiteList(\array_keys(Config::getParam('frameworks')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of frameworks allowed for filtering site templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' frameworks are allowed.', true) - ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools', 'starter', 'databases', 'ai', 'messaging', 'utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering site templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) + ->param('useCases', [], new ArrayList(new WhiteList(SiteUseCases::getAll()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering site templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) ->inject('response') diff --git a/src/Appwrite/Platform/Tasks/Screenshot.php b/src/Appwrite/Platform/Tasks/Screenshot.php index 4df3ab91df..71adb285c7 100644 --- a/src/Appwrite/Platform/Tasks/Screenshot.php +++ b/src/Appwrite/Platform/Tasks/Screenshot.php @@ -26,7 +26,7 @@ class Screenshot extends Action $this ->desc('Create Site template screenshot') ->param('templateId', '', new Text(128), 'Template ID.') - ->param('variables', '', new Text(16384), 'JSON of env variables to use when setting up the site.') + ->param('variables', '', new Text(16384), 'JSON of env variables to use when setting up the site.', true) ->callback($this->action(...)); } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 4cc4c39de3..ee25f81d18 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -1870,7 +1870,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(1, count($sessions)); $this->assertEquals($sessionId2, $sessions[0]['$id']); - }); + }, 120_000, 300); /** * Reset Limit diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index bd746f69f8..7e63fcfcd7 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -4,6 +4,7 @@ namespace Tests\E2E\Services\Realtime; use CURLFile; use Exception; +use Swoole\Coroutine; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; @@ -3122,4 +3123,153 @@ class RealtimeCustomClientTest extends Scope $client->close(); } + + /** + * Simulate concurrent realtime traffic using Swoole coroutines. + * Opens multiple websocket clients concurrently, then performs create/update/delete ops. + */ + public function testConcurrentRealtimeTrafficCoroutines() + { + if (!class_exists(\Swoole\Coroutine::class)) { + $this->markTestSkipped('Swoole Coroutine not available in this environment.'); + } + + $user = $this->getUser(); + $session = $user['session'] ?? ''; + $projectId = $this->getProject()['$id']; + + Coroutine\run(function () use ($session, $projectId) { + $headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $projectId . '=' . $session + ]; + + $clientCount = 5; + $clients = []; + for ($i = 0; $i < $clientCount; $i++) { + $clients[] = $this->getWebsocket(['documents', 'collections'], $headers); + } + + foreach ($clients as $client) { + $response = json_decode($client->receive(), true); + $this->assertEquals('connected', $response['type']); + } + + // Setup DB/collection/attribute + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'Concurrent DB', + ]); + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'Concurrent Collection', + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + 'documentSecurity' => true, + ]); + $collectionId = $collection['body']['$id']; + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 64, + 'required' => true, + ]); + + Coroutine::sleep(1); + + $creates = [ + ['name' => 'Doc A'], + ['name' => 'Doc B'], + ['name' => 'Doc C'], + ['name' => 'Doc D'], + ['name' => 'Doc E'], + ['name' => 'Doc F'], + ]; + + $expectedEvents = count($creates); + + // Per-client receipts + $receivedEvents = array_fill(0, $clientCount, []); + + // Launch receiver coroutines (one per client) + foreach ($clients as $idx => $client) { + Coroutine::create(function () use ($client, &$receivedEvents, $expectedEvents, $idx) { + $local = []; + for ($i = 0; $i < $expectedEvents; $i++) { + $event = json_decode($client->receive(), true); + $local[] = $event; + } + $receivedEvents[$idx] = $local; + }); + } + + // Create docs + foreach ($creates as $payload) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => ID::unique(), + 'data' => $payload, + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + } + + // Wait for receivers to collect; timeout ~10s + $deadline = microtime(true) + 10; + while (microtime(true) < $deadline) { + $done = true; + foreach ($receivedEvents as $events) { + if (count($events) < $expectedEvents) { + $done = false; + break; + } + } + if ($done) { + break; + } + Coroutine::sleep(0.1); + } + + $expectedNames = array_column($creates, 'name'); + + for ($c = 0; $c < $clientCount; $c++) { + $events = $receivedEvents[$c]; + $this->assertCount($expectedEvents, $events, 'Unexpected event count on client '.$c); + $seen = []; + foreach ($events as $event) { + $this->assertEquals('event', $event['type']); + $this->assertArrayHasKey('payload', $event['data']); + $seen[] = $event['data']['payload']['name'] ?? ''; + } + foreach ($expectedNames as $name) { + $this->assertContains($name, $seen); + } + } + + foreach ($clients as $client) { + $client->close(); + } + }); + } } diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 22a33fbf4d..ff4d8dd5e1 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -2409,7 +2409,8 @@ class SitesCustomServerTest extends Scope $this->assertEquals(301, $response['headers']['status-code']); $this->assertArrayHasKey('set-cookie', $response['headers']); $this->assertStringContainsString('a_jwt_console=', $response['headers']['set-cookie']); - $this->assertStringContainsString('httponly', $response['headers']['set-cookie']); + // due to swoole update; no more httponly + $this->assertStringContainsString('HttpOnly', $response['headers']['set-cookie']); $this->assertStringContainsString('domain=' . $domain, $response['headers']['set-cookie']); $this->assertStringContainsString('path=/', $response['headers']['set-cookie']); $this->assertNotEmpty($response['cookies']['a_jwt_console']);