Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions app/config/frameworks.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,31 @@ function getVersions(array $versions, string $prefix)
]
]
],
'tanstack-start' => [
'key' => 'tanstack-start',
'name' => 'TanStack Start',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'bash /usr/local/server/helpers/tanstack-start/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/tanstack-start/env.sh',
'adapters' => [
'ssr' => [
'key' => 'ssr',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist',
'startCommand' => 'bash helpers/tanstack-start/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist/client',
'startCommand' => 'bash helpers/server.sh',
]
]
],
'remix' => [
'key' => 'remix',
'name' => 'Remix',
Expand Down
78 changes: 78 additions & 0 deletions app/config/templates/site.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https';
$hostname = System::getEnv('_APP_DOMAIN', '');

// Temporary fix until we can set _APP_DOMAIN to "localhost" instead of "traefik"
if (System::getEnv('_APP_ENV', 'development') === 'development') {
$hostname = 'localhost';
}

$url = $protocol . '://' . $hostname;

class UseCases
Expand Down Expand Up @@ -111,6 +116,16 @@ class UseCases
'outputDirectory' => './dist',
'fallbackFile' => '+not-found.html',
],
'TANSTACK_START' => [
'key' => 'tanstack-start',
'name' => 'TanStack Start',
'installCommand' => 'npm install',
'buildCommand' => 'npm run build',
'outputDirectory' => './dist',
'buildRuntime' => 'node-22',
'adapter' => 'ssr',
'fallbackFile' => '',
],
'ANGULAR' => [
'key' => 'angular',
'name' => 'Angular',
Expand Down Expand Up @@ -950,6 +965,50 @@ function getFramework(string $frameworkEnum, array $overrides)
],
]
],
[
'key' => 'starter-for-tanstack-start',
'name' => 'TanStack Start starter',
'useCases' => [UseCases::STARTER],
'tagline' => 'Simple TanStack Start 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-tanstack-start-dark.png',
'screenshotLight' => $url . '/images/sites/templates/starter-for-tanstack-start-light.png',
'frameworks' => [
getFramework('TANSTACK_START', [
'providerRootDirectory' => './',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'starter-for-tanstack-start',
'providerOwner' => 'appwrite',
'providerVersion' => '0.1.*',
'variables' => [
[
'name' => 'VITE_APPWRITE_ENDPOINT',
'description' => 'Endpoint of Appwrite server',
'value' => '{apiEndpoint}',
'placeholder' => '{apiEndpoint}',
'required' => true,
'type' => 'text'
],
[
'name' => 'VITE_APPWRITE_PROJECT_ID',
'description' => 'Your Appwrite project ID',
'value' => '{projectId}',
'placeholder' => '{projectId}',
'required' => true,
'type' => 'text'
],
[
'name' => 'VITE_APPWRITE_PROJECT_NAME',
'description' => 'Your Appwrite project name',
'value' => '{projectName}',
'placeholder' => '{projectName}',
'required' => true,
'type' => 'text'
],
]
],
[
'key' => 'starter-for-nuxt',
'name' => 'Nuxt starter',
Expand Down Expand Up @@ -1327,6 +1386,25 @@ function getFramework(string $frameworkEnum, array $overrides)
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-tanstack-start',
'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],
'screenshotDark' => $url . '/images/sites/templates/playground-for-tanstack-start-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-tanstack-start-light.png',
'frameworks' => [
getFramework('TANSTACK_START', [
'providerRootDirectory' => './tanstack-start/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.5.*',
'variables' => [],
],
[
'key' => 'playground-for-react-native',
'name' => 'React Native playground',
Expand Down
101 changes: 89 additions & 12 deletions app/controllers/api/vcs.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,20 @@
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Query\Cursor;
use Utopia\Detector\Detection\Framework\Analog;
use Utopia\Detector\Detection\Framework\Angular;
use Utopia\Detector\Detection\Framework\Astro;
use Utopia\Detector\Detection\Framework\Flutter;
use Utopia\Detector\Detection\Framework\Lynx;
use Utopia\Detector\Detection\Framework\NextJs;
use Utopia\Detector\Detection\Framework\Nuxt;
use Utopia\Detector\Detection\Framework\React;
use Utopia\Detector\Detection\Framework\ReactNative;
use Utopia\Detector\Detection\Framework\Remix;
use Utopia\Detector\Detection\Framework\Svelte;
use Utopia\Detector\Detection\Framework\SvelteKit;
use Utopia\Detector\Detection\Framework\TanStackStart;
use Utopia\Detector\Detection\Framework\Vue;
use Utopia\Detector\Detection\Packager\NPM;
use Utopia\Detector\Detection\Packager\PNPM;
use Utopia\Detector\Detection\Packager\Yarn;
Expand All @@ -58,6 +66,7 @@
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
use Utopia\VCS\Adapter\Git\GitHub;
use Utopia\VCS\Exception\FileNotFound;
use Utopia\VCS\Exception\RepositoryNotFound;

use function Swoole\Coroutine\batch;
Expand Down Expand Up @@ -818,7 +827,10 @@
$files = \array_column($files, 'name');
$languages = $github->listRepositoryLanguages($owner, $repositoryName);

$detector = new Packager($files);
$detector = new Packager();
foreach ($files as $file) {
$detector->addInput($file);
}
$detector
->addOption(new Yarn())
->addOption(new PNPM())
Expand All @@ -828,21 +840,42 @@
$packager = !\is_null($detection) ? $detection->getName() : 'npm';

if ($type === 'framework') {
$packages = '';
try {
$contentResponse = $github->getRepositoryContent($owner, $repositoryName, \rtrim($providerRootDirectory, '/') . '/package.json');
$packages = $contentResponse['content'] ?? '';
} catch (FileNotFound $e) {
// Continue detection without package.json
}

$output = new Document([
'framework' => '',
'installCommand' => '',
'buildCommand' => '',
'outputDirectory' => '',
]);

$detector = new Framework($files, $packager);
$detector = new Framework($packager);
$detector->addInput($packages, Framework::INPUT_PACKAGES);
foreach ($files as $file) {
$detector->addInput($file, Framework::INPUT_FILE);
}

$detector
->addOption(new Analog())
->addOption(new Angular())
->addOption(new Astro())
->addOption(new Flutter())
->addOption(new Lynx())
->addOption(new NextJs())
->addOption(new Nuxt())
->addOption(new Astro())
->addOption(new React())
->addOption(new ReactNative())
->addOption(new Remix())
->addOption(new Svelte())
->addOption(new SvelteKit())
->addOption(new NextJs())
->addOption(new Remix());
->addOption(new TanStackStart())
->addOption(new Vue());

$framework = $detector->detect();

Expand Down Expand Up @@ -877,7 +910,18 @@
];

foreach ($strategies as $strategy) {
$detector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager);
$detector = new Runtime($strategy, $packager);

if ($strategy === Strategy::LANGUAGES) {
foreach ($languages as $language) {
$detector->addInput($language);
}
} else {
foreach ($files as $file) {
$detector->addInput($file);
}
}

$detector
->addOption(new Node())
->addOption(new Bun())
Expand Down Expand Up @@ -984,7 +1028,10 @@
$files = $github->listRepositoryContents($repo['organization'], $repo['name'], '');
$files = \array_column($files, 'name');

$detector = new Packager($files);
$detector = new Packager();
foreach ($files as $file) {
$detector->addInput($file);
}
$detector
->addOption(new Yarn())
->addOption(new PNPM())
Expand All @@ -994,14 +1041,35 @@
$packager = !\is_null($detection) ? $detection->getName() : 'npm';

if ($type === 'framework') {
$frameworkDetector = new Framework($files, $packager);
$packages = '';
try {
$contentResponse = $github->getRepositoryContent($repo['organization'], $repo['name'], 'package.json');
$packages = $contentResponse['content'] ?? '';
} catch (FileNotFound $e) {
// Continue detection without package.json
}

$frameworkDetector = new Framework($packager);
$frameworkDetector->addInput($packages, Framework::INPUT_PACKAGES);
foreach ($files as $file) {
$frameworkDetector->addInput($file, Framework::INPUT_FILE);
}

$frameworkDetector
->addOption(new Analog())
->addOption(new Angular())
->addOption(new Astro())
->addOption(new Flutter())
->addOption(new Lynx())
->addOption(new NextJs())
->addOption(new Nuxt())
->addOption(new Astro())
->addOption(new React())
->addOption(new ReactNative())
->addOption(new Remix())
->addOption(new Svelte())
->addOption(new SvelteKit())
->addOption(new NextJs())
->addOption(new Remix());
->addOption(new TanStackStart())
->addOption(new Vue());

$detectedFramework = $frameworkDetector->detect();

Expand All @@ -1026,7 +1094,16 @@
];

foreach ($strategies as $strategy) {
$detector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager);
$detector = new Runtime($strategy, $packager);
if ($strategy === Strategy::LANGUAGES) {
foreach ($languages as $language) {
$detector->addInput($language);
}
} else {
foreach ($files as $file) {
$detector->addInput($file);
}
}
$detector
->addOption(new Node())
->addOption(new Bun())
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "3.*",
"utopia-php/detector": "0.1.*",
"utopia-php/detector": "0.2.*",
"utopia-php/domains": "0.9.*",
"utopia-php/dns": "0.3.*",
"utopia-php/dsn": "0.2.1",
Expand All @@ -74,7 +74,7 @@
"utopia-php/swoole": "0.8.*",
"utopia-php/system": "0.9.*",
"utopia-php/telemetry": "0.1.*",
"utopia-php/vcs": "0.11.*",
"utopia-php/vcs": "0.12.*",
"utopia-php/websocket": "0.3.*",
"matomo/device-detector": "6.4.*",
"dragonmantank/cron-expression": "3.4.*",
Expand Down
Loading