2022-07-13 07:02:55 +00:00
< ? php
2022-07-14 02:04:31 +00:00
2022-11-14 10:01:41 +00:00
namespace Appwrite\Platform\Tasks ;
2022-07-13 07:02:55 +00:00
2022-10-27 21:06:09 +00:00
use Appwrite\SDK\Language\Android ;
2024-03-06 17:34:21 +00:00
use Appwrite\SDK\Language\Apple ;
2022-07-13 07:02:55 +00:00
use Appwrite\SDK\Language\CLI ;
use Appwrite\SDK\Language\Dart ;
use Appwrite\SDK\Language\Deno ;
use Appwrite\SDK\Language\DotNet ;
use Appwrite\SDK\Language\Flutter ;
use Appwrite\SDK\Language\Go ;
2022-10-27 21:06:09 +00:00
use Appwrite\SDK\Language\GraphQL ;
2022-07-13 07:02:55 +00:00
use Appwrite\SDK\Language\Kotlin ;
2022-10-27 21:06:09 +00:00
use Appwrite\SDK\Language\Node ;
use Appwrite\SDK\Language\PHP ;
use Appwrite\SDK\Language\Python ;
2024-03-10 03:57:54 +00:00
use Appwrite\SDK\Language\ReactNative ;
2022-10-27 21:06:09 +00:00
use Appwrite\SDK\Language\REST ;
use Appwrite\SDK\Language\Ruby ;
2022-07-13 07:02:55 +00:00
use Appwrite\SDK\Language\Swift ;
2022-10-27 21:06:09 +00:00
use Appwrite\SDK\Language\Web ;
use Appwrite\SDK\SDK ;
use Appwrite\Spec\Swagger2 ;
use Utopia\CLI\Console ;
use Utopia\Config\Config ;
2024-03-06 17:34:21 +00:00
use Utopia\Platform\Action ;
2024-11-15 12:27:46 +00:00
use Utopia\Validator\Nullable ;
use Utopia\Validator\Text ;
use Utopia\Validator\WhiteList ;
2022-07-13 07:02:55 +00:00
2022-07-14 02:04:31 +00:00
class SDKs extends Action
{
2022-08-02 01:58:36 +00:00
public static function getName () : string
{
return 'sdks' ;
}
2022-07-14 02:04:31 +00:00
2022-07-13 07:02:55 +00:00
public function __construct ()
{
$this
2022-08-02 01:58:36 +00:00
-> desc ( 'Generate Appwrite SDKs' )
2024-11-15 12:27:46 +00:00
-> param ( 'platform' , null , new Nullable ( new Text ( 256 )), 'Selected Platform' , optional : true )
2024-12-11 06:14:10 +00:00
-> param ( 'sdk' , null , new Nullable ( new Text ( 256 )), 'Selected SDK' , optional : true )
-> param ( 'version' , null , new Nullable ( new Text ( 256 )), 'Selected SDK' , optional : true )
2024-11-15 12:27:46 +00:00
-> param ( 'git' , null , new Nullable ( new WhiteList ([ 'yes' , 'no' ])), 'Should we use git push?' , optional : true )
2024-12-11 06:14:10 +00:00
-> param ( 'production' , null , new Nullable ( new WhiteList ([ 'yes' , 'no' ])), 'Should we push to production?' , optional : true )
-> param ( 'message' , null , new Nullable ( new Text ( 256 )), 'Commit Message' , optional : true )
2025-06-04 08:37:43 +00:00
-> callback ( $this -> action ( ... ));
2022-07-13 07:02:55 +00:00
}
2024-12-11 06:14:10 +00:00
public function action ( ? string $selectedPlatform , ? string $selectedSDK , ? string $version , ? string $git , ? string $production , ? string $message ) : void
2022-07-13 07:02:55 +00:00
{
2024-11-15 12:27:46 +00:00
$selectedPlatform ? ? = Console :: confirm ( 'Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):' );
$selectedSDK ? ? = \strtolower ( Console :: confirm ( 'Choose SDK ("*" for all):' ));
$version ? ? = Console :: confirm ( 'Choose an Appwrite version' );
$git ? ? = Console :: confirm ( 'Should we use git push? (yes/no)' );
$git = $git === 'yes' ;
if ( $git ) {
$production ? ? = Console :: confirm ( 'Type "Appwrite" to push code to production git repos' );
$production = $production === 'Appwrite' ;
$message ? ? = Console :: confirm ( 'Please enter your commit message:' );
2025-09-08 08:13:44 +00:00
$createPr = Console :: confirm ( 'Should we create pull request automatically? (yes/no)' );
$createPr = $createPr === 'yes' ;
2024-11-15 12:27:46 +00:00
}
2022-07-13 07:02:55 +00:00
2025-07-18 09:38:35 +00:00
if ( ! \in_array ( $version , [
'0.6.x' ,
'0.7.x' ,
'0.8.x' ,
'0.9.x' ,
'0.10.x' ,
'0.11.x' ,
'0.12.x' ,
'0.13.x' ,
'0.14.x' ,
'0.15.x' ,
'1.0.x' ,
'1.1.x' ,
'1.2.x' ,
'1.3.x' ,
'1.4.x' ,
'1.5.x' ,
'1.6.x' ,
'1.7.x' ,
'1.8.x' ,
'latest'
])) {
2024-03-22 00:25:57 +00:00
throw new \Exception ( 'Unknown version given' );
2022-07-13 07:02:55 +00:00
}
2024-11-15 12:27:46 +00:00
$platforms = Config :: getParam ( 'platforms' );
2022-07-13 07:02:55 +00:00
foreach ( $platforms as $key => $platform ) {
2023-01-13 12:29:22 +00:00
if ( $selectedPlatform !== $key && $selectedPlatform !== '*' ) {
continue ;
}
foreach ( $platform [ 'sdks' ] as $language ) {
if ( $selectedSDK !== $language [ 'key' ] && $selectedSDK !== '*' ) {
2022-07-13 07:02:55 +00:00
continue ;
}
if ( ! $language [ 'enabled' ]) {
Console :: warning ( $language [ 'name' ] . ' for ' . $platform [ 'name' ] . ' is disabled' );
continue ;
}
Console :: info ( 'Fetching API Spec for ' . $language [ 'name' ] . ' for ' . $platform [ 'name' ] . ' (version: ' . $version . ')' );
2023-02-08 16:34:22 +00:00
$spec = file_get_contents ( __DIR__ . '/../../../../app/config/specs/swagger2-' . $version . '-' . $language [ 'family' ] . '.json' );
2022-07-13 07:02:55 +00:00
2024-03-03 02:34:36 +00:00
$cover = 'https://github.com/appwrite/appwrite/raw/main/public/images/github.png' ;
2023-02-08 16:34:22 +00:00
$result = \realpath ( __DIR__ . '/../../../../app' ) . '/sdks/' . $key . '-' . $language [ 'key' ];
$resultExamples = \realpath ( __DIR__ . '/../../../..' ) . '/docs/examples/' . $version . '/' . $key . '-' . $language [ 'key' ];
$target = \realpath ( __DIR__ . '/../../../../app' ) . '/sdks/git/' . $language [ 'key' ] . '/' ;
$readme = \realpath ( __DIR__ . '/../../../../docs/sdks/' . $language [ 'key' ] . '/README.md' );
2022-07-13 07:02:55 +00:00
$readme = ( $readme ) ? \file_get_contents ( $readme ) : '' ;
2023-02-08 16:34:22 +00:00
$gettingStarted = \realpath ( __DIR__ . '/../../../../docs/sdks/' . $language [ 'key' ] . '/GETTING_STARTED.md' );
2022-07-13 07:02:55 +00:00
$gettingStarted = ( $gettingStarted ) ? \file_get_contents ( $gettingStarted ) : '' ;
2023-02-08 16:34:22 +00:00
$examples = \realpath ( __DIR__ . '/../../../../docs/sdks/' . $language [ 'key' ] . '/EXAMPLES.md' );
2022-07-13 07:02:55 +00:00
$examples = ( $examples ) ? \file_get_contents ( $examples ) : '' ;
2025-07-30 08:02:56 +00:00
$changelog = $language [ 'changelog' ] ? ? '' ;
2022-07-13 07:02:55 +00:00
$changelog = ( $changelog ) ? \file_get_contents ( $changelog ) : '# Change Log' ;
$warning = '**This SDK is compatible with Appwrite server version ' . $version . '. For older versions, please check [previous releases](' . $language [ 'url' ] . '/releases).**' ;
$license = 'BSD-3-Clause' ;
$licenseContent = 'Copyright (c) ' . date ( 'Y' ) . ' Appwrite ( https :// appwrite . io ) and individual contributors .
All rights reserved .
Redistribution and use in source and binary forms , with or without modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice , this list of conditions and the following disclaimer in the documentation and / or other materials provided with the distribution .
2022-10-12 16:53:46 +00:00
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission .
2022-07-13 07:02:55 +00:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE . ' ;
switch ( $language [ 'key' ]) {
case 'web' :
$config = new Web ();
2023-02-28 08:35:40 +00:00
if ( $platform [ 'key' ] === APP_PLATFORM_CONSOLE ) {
$config -> setNPMPackage ( '@appwrite.io/console' );
$config -> setBowerPackage ( '@appwrite.io/console' );
} else {
$config -> setNPMPackage ( 'appwrite' );
$config -> setBowerPackage ( 'appwrite' );
}
2022-07-13 07:02:55 +00:00
break ;
case 'cli' :
$config = new CLI ();
$config -> setNPMPackage ( 'appwrite-cli' );
$config -> setExecutableName ( 'appwrite' );
$config -> setLogo ( json_encode ( "
2024-03-08 16:25:10 +00:00
_ _ _ ___ __ _____
2022-07-13 07:02:55 +00:00
/ _\ _ __ _ ____ ___ __ ( _ ) | _ ___ / __\ / / \_ \
//_\\\| '_ \| '_ \ \ /\ / / '__| | __/ _ \ / / / / / /\/
2024-03-08 16:25:10 +00:00
/ _ \ | _ ) | | _ ) \ V V /| | | | || __ / / / ___ / / ___ / \ / / _
\_ / \_ / . __ /| . __ / \_ / \_ / | _ | | _ | \__\___ | \____ / \____ / \____ /
| _ | | _ |
2022-07-13 07:02:55 +00:00
" ));
$config -> setLogoUnescaped ( "
2024-03-08 16:25:10 +00:00
_ _ _ ___ __ _____
2022-07-13 07:02:55 +00:00
/ _\ _ __ _ ____ ___ __ ( _ ) | _ ___ / __\ / / \_ \
//_\\\| '_ \| '_ \ \ /\ / / '__| | __/ _ \ / / / / / /\/
2024-03-08 16:25:10 +00:00
/ _ \ | _ ) | | _ ) \ V V /| | | | || __ / / / ___ / / ___ / \ / / _
\_ / \_ / . __ /| . __ / \_ / \_ / | _ | | _ | \__\___ | \____ / \____ / \____ /
2022-07-13 07:02:55 +00:00
| _ | | _ | " );
break ;
case 'php' :
$config = new PHP ();
$config -> setComposerVendor ( 'appwrite' );
$config -> setComposerPackage ( 'appwrite' );
break ;
case 'nodejs' :
$config = new Node ();
$config -> setNPMPackage ( 'node-appwrite' );
$config -> setBowerPackage ( 'appwrite' );
$warning = $warning . " \n \n > This is the Node.js SDK for integrating with Appwrite from your Node.js server-side code.
If you ' re looking to integrate from the browser , you should check [ appwrite / sdk - for - web ]( https :// github . com / appwrite / sdk - for - web ) " ;
break ;
case 'deno' :
$config = new Deno ();
break ;
case 'python' :
$config = new Python ();
$config -> setPipPackage ( 'appwrite' );
$license = 'BSD License' ; // license edited due to classifiers in pypi
break ;
case 'ruby' :
$config = new Ruby ();
$config -> setGemPackage ( 'appwrite' );
break ;
case 'flutter' :
$config = new Flutter ();
$config -> setPackageName ( 'appwrite' );
break ;
2024-03-10 02:49:45 +00:00
case 'react-native' :
$config = new ReactNative ();
$config -> setNPMPackage ( 'react-native-appwrite' );
break ;
2022-07-13 07:02:55 +00:00
case 'flutter-dev' :
$config = new Flutter ();
$config -> setPackageName ( 'appwrite_dev' );
break ;
case 'dart' :
$config = new Dart ();
$config -> setPackageName ( 'dart_appwrite' );
$warning = $warning . " \n \n > This is the Dart SDK for integrating with Appwrite from your Dart server-side code. If you're looking for the Flutter SDK you should check [appwrite/sdk-for-flutter](https://github.com/appwrite/sdk-for-flutter) " ;
break ;
case 'go' :
$config = new Go ();
break ;
case 'swift' :
$config = new Swift ();
$warning = $warning . " \n \n > This is the Swift SDK for integrating with Appwrite from your Swift server-side code. If you're looking for the Apple SDK you should check [appwrite/sdk-for-apple](https://github.com/appwrite/sdk-for-apple) " ;
break ;
case 'apple' :
2022-12-19 06:05:35 +00:00
$config = new Apple ();
2022-07-13 07:02:55 +00:00
break ;
case 'dotnet' :
$cover = '' ;
$config = new DotNet ();
break ;
case 'android' :
$config = new Android ();
break ;
case 'kotlin' :
$config = new Kotlin ();
$warning = $warning . " \n \n > This is the Kotlin SDK for integrating with Appwrite from your Kotlin server-side code. If you're looking for the Android SDK you should check [appwrite/sdk-for-android](https://github.com/appwrite/sdk-for-android) " ;
break ;
2022-10-20 03:21:16 +00:00
case 'graphql' :
$config = new GraphQL ();
break ;
2022-10-26 03:19:30 +00:00
case 'rest' :
$config = new REST ();
break ;
2022-07-13 07:02:55 +00:00
default :
2024-03-22 00:25:57 +00:00
throw new \Exception ( 'Language "' . $language [ 'key' ] . '" not supported' );
2022-07-13 07:02:55 +00:00
}
Console :: info ( " Generating { $language [ 'name' ] } SDK... " );
$sdk = new SDK ( $config , new Swagger2 ( $spec ));
$sdk
-> setName ( $language [ 'name' ])
-> setNamespace ( 'io appwrite' )
-> setDescription ( " Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the { $language [ 'name' ] } SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs) " )
-> setShortDescription ( 'Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API' )
-> setLicense ( $license )
-> setLicenseContent ( $licenseContent )
-> setVersion ( $language [ 'version' ])
2022-08-10 13:00:57 +00:00
-> setPlatform ( $key )
2022-07-13 07:02:55 +00:00
-> setGitURL ( $language [ 'url' ])
-> setGitRepo ( $language [ 'gitUrl' ])
-> setGitRepoName ( $language [ 'gitRepoName' ])
-> setGitUserName ( $language [ 'gitUserName' ])
-> setLogo ( $cover )
-> setURL ( 'https://appwrite.io' )
-> setShareText ( 'Appwrite is a backend as a service for building web or mobile apps' )
-> setShareURL ( 'http://appwrite.io' )
-> setShareTags ( 'JS,javascript,reactjs,angular,ios,android,serverless' )
-> setShareVia ( 'appwrite' )
-> setWarning ( $warning )
-> setReadme ( $readme )
-> setGettingStarted ( $gettingStarted )
-> setChangelog ( $changelog )
-> setExamples ( $examples )
-> setTwitter ( APP_SOCIAL_TWITTER_HANDLE )
-> setDiscord ( APP_SOCIAL_DISCORD_CHANNEL , APP_SOCIAL_DISCORD )
-> setDefaultHeaders ([
2025-07-21 13:45:29 +00:00
'X-Appwrite-Response-Format' => '1.8.0' ,
2025-06-10 12:38:48 +00:00
])
-> setExclude ( $language [ 'exclude' ] ? ? []);
2022-07-13 07:02:55 +00:00
2023-11-16 08:50:39 +00:00
// Make sure we have a clean slate.
// Otherwise, all files in this dir will be pushed,
// regardless of whether they were just generated or not.
\exec ( 'rm -rf ' . $result );
2022-07-13 07:02:55 +00:00
try {
$sdk -> generate ( $result );
2024-02-08 01:17:54 +00:00
} catch ( \Throwable $exception ) {
2022-07-13 07:02:55 +00:00
Console :: error ( $exception -> getMessage ());
}
$gitUrl = $language [ 'gitUrl' ];
$gitBranch = $language [ 'gitBranch' ];
if ( ! $production ) {
$gitUrl = 'git@github.com:aw-tests/' . $language [ 'gitRepoName' ] . '.git' ;
}
2025-07-18 11:46:01 +00:00
$repoBranch = $language [ 'repoBranch' ] ? ? 'main' ;
2022-07-13 07:02:55 +00:00
if ( $git && ! empty ( $gitUrl )) {
2023-11-01 08:02:42 +00:00
\exec ( 'rm -rf ' . $target . ' && \
mkdir - p ' . $target . ' && \
cd ' . $target . ' && \
2024-12-11 06:14:10 +00:00
git init && \
2023-11-01 08:02:42 +00:00
git remote add origin ' . $gitUrl . ' && \
2024-12-11 06:14:10 +00:00
git fetch origin && \
2025-07-18 11:46:01 +00:00
git checkout ' . $repoBranch . ' || git checkout - b ' . $repoBranch . ' && \
git pull origin ' . $repoBranch . ' && \
2024-12-11 06:14:10 +00:00
git checkout ' . $gitBranch . ' || git checkout - b ' . $gitBranch . ' && \
git fetch origin ' . $gitBranch . ' || git push - u origin ' . $gitBranch . ' && \
2023-11-01 08:02:42 +00:00
git pull origin ' . $gitBranch . ' && \
rm - rf ' . $target . ' /* && \
2024-02-23 05:32:15 +00:00
cp - r ' . $result . ' /. ' . $target . ' / && \
2023-11-01 08:02:42 +00:00
git add . && \
git commit - m " ' . $message . ' " && \
git push - u origin ' . $gitBranch . '
' );
2022-07-13 07:02:55 +00:00
Console :: success ( " Pushed { $language [ 'name' ] } SDK to { $gitUrl } " );
2025-09-08 08:13:44 +00:00
if ( $createPr ) {
2025-09-08 08:21:34 +00:00
$prTitle = " feat: { $language [ 'name' ] } SDK update for version { $language [ 'version' ] } " ;
$prBody = " This PR contains updates to the { $language [ 'name' ] } SDK for version { $language [ 'version' ] } . " ;
2025-09-08 08:13:44 +00:00
$repoName = $language [ 'gitRepoName' ];
if ( ! $production ) {
$repoName = 'aw-tests/' . $language [ 'gitRepoName' ];
} else {
$repoName = $language [ 'gitUserName' ] . '/' . $language [ 'gitRepoName' ];
}
Console :: info ( " Creating pull request for { $language [ 'name' ] } SDK... " );
$prCommand = 'cd ' . $target . ' && \
gh pr create \
-- repo " ' . $repoName . ' " \
-- title " ' . $prTitle . ' " \
-- body " ' . $prBody . ' " \
-- base " ' . $repoBranch . ' " \
-- head " ' . $gitBranch . ' " \
2 >& 1 ' ;
$prOutput = [];
$prReturnCode = 0 ;
\exec ( $prCommand , $prOutput , $prReturnCode );
if ( $prReturnCode === 0 ) {
Console :: success ( " Successfully created pull request for { $language [ 'name' ] } SDK " );
if ( ! empty ( $prOutput )) {
Console :: info ( " PR URL: " . end ( $prOutput ));
}
} else {
$errorMessage = implode ( " \n " , $prOutput );
if ( strpos ( $errorMessage , 'already exists' ) !== false ) {
Console :: warning ( " Pull request already exists for { $language [ 'name' ] } SDK " );
} else {
Console :: error ( " Failed to create pull request for { $language [ 'name' ] } SDK: " . $errorMessage );
}
}
}
2022-07-13 07:02:55 +00:00
\exec ( 'rm -rf ' . $target );
Console :: success ( " Remove temp directory ' { $target } ' for { $language [ 'name' ] } SDK " );
}
$docDirectories = $language [ 'docDirectories' ] ? ? [ '' ];
if ( $version === 'latest' ) {
continue ;
}
foreach ( $docDirectories as $languageTitle => $path ) {
$languagePath = strtolower ( $languageTitle !== 0 ? '/' . $languageTitle : '' );
\exec (
'mkdir -p ' . $resultExamples . $languagePath . ' && \
cp - r ' . $result . ' / docs / examples ' . $languagePath . ' ' . $resultExamples
);
Console :: success ( " Copied code examples for { $language [ 'name' ] } SDK to: { $resultExamples } " );
}
}
}
}
2022-07-14 02:04:31 +00:00
}