mirror of
https://github.com/appwrite/appwrite
synced 2026-05-24 01:18:37 +00:00
Resolve merge conflicts
This commit is contained in:
commit
ace7a6baa1
25 changed files with 389 additions and 124 deletions
|
|
@ -837,7 +837,7 @@ return [
|
||||||
Exception::RULE_VERIFICATION_FAILED => [
|
Exception::RULE_VERIFICATION_FAILED => [
|
||||||
'name' => Exception::RULE_VERIFICATION_FAILED,
|
'name' => Exception::RULE_VERIFICATION_FAILED,
|
||||||
'description' => 'Domain verification failed. Please check if your DNS records are correct and try again.',
|
'description' => 'Domain verification failed. Please check if your DNS records are correct and try again.',
|
||||||
'code' => 401,
|
'code' => 400,
|
||||||
'publish' => true
|
'publish' => true
|
||||||
],
|
],
|
||||||
Exception::PROJECT_SMTP_CONFIG_INVALID => [
|
Exception::PROJECT_SMTP_CONFIG_INVALID => [
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ return [
|
||||||
'vue' => [
|
'vue' => [
|
||||||
'key' => 'vue',
|
'key' => 'vue',
|
||||||
'name' => 'Vue.js',
|
'name' => 'Vue.js',
|
||||||
'screenshotSleep' => 3000,
|
'screenshotSleep' => 5000,
|
||||||
'buildRuntime' => 'node-22',
|
'buildRuntime' => 'node-22',
|
||||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||||
'adapters' => [
|
'adapters' => [
|
||||||
|
|
@ -227,6 +227,23 @@ return [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
'lynx' => [
|
||||||
|
'key' => 'lynx',
|
||||||
|
'name' => 'Lynx',
|
||||||
|
'screenshotSleep' => 5000,
|
||||||
|
'buildRuntime' => 'node-22',
|
||||||
|
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||||
|
'adapters' => [
|
||||||
|
'static' => [
|
||||||
|
'key' => 'static',
|
||||||
|
'buildCommand' => 'npm run build',
|
||||||
|
'installCommand' => 'npm install',
|
||||||
|
'outputDirectory' => './dist',
|
||||||
|
'startCommand' => 'bash helpers/server.sh',
|
||||||
|
'fallbackFile' => 'index.html'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
'flutter' => [
|
'flutter' => [
|
||||||
'key' => 'flutter',
|
'key' => 'flutter',
|
||||||
'name' => 'Flutter',
|
'name' => 'Flutter',
|
||||||
|
|
|
||||||
|
|
@ -24718,6 +24718,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
@ -25353,6 +25354,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
@ -37040,6 +37042,11 @@
|
||||||
"description": "Site Template Name.",
|
"description": "Site Template Name.",
|
||||||
"x-example": "Starter site"
|
"x-example": "Starter site"
|
||||||
},
|
},
|
||||||
|
"tagline": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Short description of template",
|
||||||
|
"x-example": "Minimal web app integrating with Appwrite."
|
||||||
|
},
|
||||||
"demoUrl": {
|
"demoUrl": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "URL hosting a template demo.",
|
"description": "URL hosting a template demo.",
|
||||||
|
|
@ -37103,6 +37110,7 @@
|
||||||
"required": [
|
"required": [
|
||||||
"key",
|
"key",
|
||||||
"name",
|
"name",
|
||||||
|
"tagline",
|
||||||
"demoUrl",
|
"demoUrl",
|
||||||
"screenshotDark",
|
"screenshotDark",
|
||||||
"screenshotLight",
|
"screenshotLight",
|
||||||
|
|
|
||||||
|
|
@ -16816,6 +16816,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
@ -17226,6 +17227,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
|
||||||
|
|
@ -25221,6 +25221,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
@ -25871,6 +25872,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
@ -37623,6 +37625,11 @@
|
||||||
"description": "Site Template Name.",
|
"description": "Site Template Name.",
|
||||||
"x-example": "Starter site"
|
"x-example": "Starter site"
|
||||||
},
|
},
|
||||||
|
"tagline": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Short description of template",
|
||||||
|
"x-example": "Minimal web app integrating with Appwrite."
|
||||||
|
},
|
||||||
"demoUrl": {
|
"demoUrl": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "URL hosting a template demo.",
|
"description": "URL hosting a template demo.",
|
||||||
|
|
@ -37688,6 +37695,7 @@
|
||||||
"required": [
|
"required": [
|
||||||
"key",
|
"key",
|
||||||
"name",
|
"name",
|
||||||
|
"tagline",
|
||||||
"demoUrl",
|
"demoUrl",
|
||||||
"screenshotDark",
|
"screenshotDark",
|
||||||
"screenshotLight",
|
"screenshotLight",
|
||||||
|
|
|
||||||
|
|
@ -17285,6 +17285,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
@ -17714,6 +17715,7 @@
|
||||||
"sveltekit",
|
"sveltekit",
|
||||||
"astro",
|
"astro",
|
||||||
"remix",
|
"remix",
|
||||||
|
"lynx",
|
||||||
"flutter",
|
"flutter",
|
||||||
"vite",
|
"vite",
|
||||||
"other"
|
"other"
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ return [
|
||||||
'icon' => 'icon-lightning-bolt',
|
'icon' => 'icon-lightning-bolt',
|
||||||
'id' => 'starter',
|
'id' => 'starter',
|
||||||
'name' => 'Starter function',
|
'name' => 'Starter function',
|
||||||
|
'score' => 5,
|
||||||
'tagline' =>
|
'tagline' =>
|
||||||
'A simple function to get started. Edit this function to explore endless possibilities with Appwrite Functions.',
|
'A simple function to get started. Edit this function to explore endless possibilities with Appwrite Functions.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
|
|
@ -62,6 +63,7 @@ return [
|
||||||
'icon' => 'icon-upstash',
|
'icon' => 'icon-upstash',
|
||||||
'id' => 'query-upstash-vector',
|
'id' => 'query-upstash-vector',
|
||||||
'name' => 'Query Upstash Vector',
|
'name' => 'Query Upstash Vector',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => 'Vector database that stores text embeddings and context retrieval for LLMs',
|
'tagline' => 'Vector database that stores text embeddings and context retrieval for LLMs',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -106,6 +108,7 @@ return [
|
||||||
'icon' => 'icon-redis',
|
'icon' => 'icon-redis',
|
||||||
'id' => 'query-redis-labs',
|
'id' => 'query-redis-labs',
|
||||||
'name' => 'Query Redis Labs',
|
'name' => 'Query Redis Labs',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => 'Key-value database with advanced caching capabilities.',
|
'tagline' => 'Key-value database with advanced caching capabilities.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -149,6 +152,7 @@ return [
|
||||||
'icon' => 'icon-neo4j',
|
'icon' => 'icon-neo4j',
|
||||||
'id' => 'query-neo4j-auradb',
|
'id' => 'query-neo4j-auradb',
|
||||||
'name' => 'Query Neo4j AuraDB',
|
'name' => 'Query Neo4j AuraDB',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => 'Graph database with focus on relations between data.',
|
'tagline' => 'Graph database with focus on relations between data.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -200,6 +204,7 @@ return [
|
||||||
'icon' => 'icon-mongodb',
|
'icon' => 'icon-mongodb',
|
||||||
'id' => 'query-mongo-atlas',
|
'id' => 'query-mongo-atlas',
|
||||||
'name' => 'Query MongoDB Atlas',
|
'name' => 'Query MongoDB Atlas',
|
||||||
|
'score' => 4,
|
||||||
'tagline' =>
|
'tagline' =>
|
||||||
'Realtime NoSQL document database with geospecial, graph, search, and vector suport.',
|
'Realtime NoSQL document database with geospecial, graph, search, and vector suport.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
|
|
@ -237,6 +242,7 @@ return [
|
||||||
'icon' => 'icon-neon',
|
'icon' => 'icon-neon',
|
||||||
'id' => 'query-neon-postgres',
|
'id' => 'query-neon-postgres',
|
||||||
'name' => 'Query Neon Postgres',
|
'name' => 'Query Neon Postgres',
|
||||||
|
'score' => 4,
|
||||||
'tagline' =>
|
'tagline' =>
|
||||||
'Reliable SQL database with replication, point-in-time recovery, and pgvector support.',
|
'Reliable SQL database with replication, point-in-time recovery, and pgvector support.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
|
|
@ -305,6 +311,7 @@ return [
|
||||||
'icon' => 'icon-open-ai',
|
'icon' => 'icon-open-ai',
|
||||||
'id' => 'prompt-chatgpt',
|
'id' => 'prompt-chatgpt',
|
||||||
'name' => 'Prompt ChatGPT',
|
'name' => 'Prompt ChatGPT',
|
||||||
|
'score' => 7,
|
||||||
'tagline' => 'Ask questions and let OpenAI GPT-3.5-turbo answer.',
|
'tagline' => 'Ask questions and let OpenAI GPT-3.5-turbo answer.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -366,6 +373,7 @@ return [
|
||||||
'icon' => 'icon-discord',
|
'icon' => 'icon-discord',
|
||||||
'id' => 'discord-command-bot',
|
'id' => 'discord-command-bot',
|
||||||
'name' => 'Discord Command Bot',
|
'name' => 'Discord Command Bot',
|
||||||
|
'score' => 6,
|
||||||
'tagline' => 'Simple command using Discord Interactions.',
|
'tagline' => 'Simple command using Discord Interactions.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -429,6 +437,7 @@ return [
|
||||||
'icon' => 'icon-perspective-api',
|
'icon' => 'icon-perspective-api',
|
||||||
'id' => 'analyze-with-perspectiveapi',
|
'id' => 'analyze-with-perspectiveapi',
|
||||||
'name' => 'Analyze with PerspectiveAPI',
|
'name' => 'Analyze with PerspectiveAPI',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Automate moderation by getting toxicity of messages.',
|
'tagline' => 'Automate moderation by getting toxicity of messages.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -464,6 +473,7 @@ return [
|
||||||
'icon' => 'icon-pangea',
|
'icon' => 'icon-pangea',
|
||||||
'id' => 'censor-with-redact',
|
'id' => 'censor-with-redact',
|
||||||
'name' => 'Censor with Redact',
|
'name' => 'Censor with Redact',
|
||||||
|
'score' => 5,
|
||||||
'tagline' =>
|
'tagline' =>
|
||||||
'Censor sensitive information from a provided text string using Redact API by Pangea.',
|
'Censor sensitive information from a provided text string using Redact API by Pangea.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
|
|
@ -512,6 +522,7 @@ return [
|
||||||
'icon' => 'icon-document',
|
'icon' => 'icon-document',
|
||||||
'id' => 'generate-pdf',
|
'id' => 'generate-pdf',
|
||||||
'name' => 'Generate PDF',
|
'name' => 'Generate PDF',
|
||||||
|
'score' => 7,
|
||||||
'tagline' => 'Document containing sample invoice in PDF format.',
|
'tagline' => 'Document containing sample invoice in PDF format.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -533,6 +544,7 @@ return [
|
||||||
'icon' => 'icon-github',
|
'icon' => 'icon-github',
|
||||||
'id' => 'github-issue-bot',
|
'id' => 'github-issue-bot',
|
||||||
'name' => 'GitHub issue bot',
|
'name' => 'GitHub issue bot',
|
||||||
|
'score' => 4,
|
||||||
'tagline' =>
|
'tagline' =>
|
||||||
'Automate the process of responding to newly opened issues in a GitHub repository.',
|
'Automate the process of responding to newly opened issues in a GitHub repository.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
|
|
@ -577,6 +589,7 @@ return [
|
||||||
'icon' => 'icon-bookmark',
|
'icon' => 'icon-bookmark',
|
||||||
'id' => 'url-shortener',
|
'id' => 'url-shortener',
|
||||||
'name' => 'URL shortener',
|
'name' => 'URL shortener',
|
||||||
|
'score' => 3,
|
||||||
'tagline' => 'Generate URL with short ID and redirect to the original URL when visited.',
|
'tagline' => 'Generate URL with short ID and redirect to the original URL when visited.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -628,6 +641,7 @@ return [
|
||||||
'icon' => 'icon-algolia',
|
'icon' => 'icon-algolia',
|
||||||
'id' => 'sync-with-algolia',
|
'id' => 'sync-with-algolia',
|
||||||
'name' => 'Sync with Algolia',
|
'name' => 'Sync with Algolia',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
|
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -709,6 +723,7 @@ return [
|
||||||
'icon' => 'icon-meilisearch',
|
'icon' => 'icon-meilisearch',
|
||||||
'id' => 'sync-with-meilisearch',
|
'id' => 'sync-with-meilisearch',
|
||||||
'name' => 'Sync with Meilisearch',
|
'name' => 'Sync with Meilisearch',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
|
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -802,6 +817,7 @@ return [
|
||||||
'icon' => 'icon-vonage',
|
'icon' => 'icon-vonage',
|
||||||
'id' => 'whatsapp-with-vonage',
|
'id' => 'whatsapp-with-vonage',
|
||||||
'name' => 'WhatsApp with Vonage',
|
'name' => 'WhatsApp with Vonage',
|
||||||
|
'score' => 6,
|
||||||
'tagline' => 'Simple bot to answer WhatsApp messages.',
|
'tagline' => 'Simple bot to answer WhatsApp messages.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -888,6 +904,7 @@ return [
|
||||||
'icon' => 'icon-bell',
|
'icon' => 'icon-bell',
|
||||||
'id' => 'push-notification-with-fcm',
|
'id' => 'push-notification-with-fcm',
|
||||||
'name' => 'Push notification with FCM',
|
'name' => 'Push notification with FCM',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => 'Send push notifications to your users using Firebase Cloud Messaging (FCM).',
|
'tagline' => 'Send push notifications to your users using Firebase Cloud Messaging (FCM).',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -944,6 +961,7 @@ return [
|
||||||
'icon' => 'icon-mail',
|
'icon' => 'icon-mail',
|
||||||
'id' => 'email-contact-form',
|
'id' => 'email-contact-form',
|
||||||
'name' => 'Email contact form',
|
'name' => 'Email contact form',
|
||||||
|
'score' => 7,
|
||||||
'tagline' => 'Sends an email with the contents of a HTML form.',
|
'tagline' => 'Sends an email with the contents of a HTML form.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1027,6 +1045,7 @@ return [
|
||||||
'icon' => 'icon-stripe',
|
'icon' => 'icon-stripe',
|
||||||
'id' => 'subscriptions-with-stripe',
|
'id' => 'subscriptions-with-stripe',
|
||||||
'name' => 'Subscriptions with Stripe',
|
'name' => 'Subscriptions with Stripe',
|
||||||
|
'score' => 6,
|
||||||
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
|
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1068,6 +1087,7 @@ return [
|
||||||
'icon' => 'icon-stripe',
|
'icon' => 'icon-stripe',
|
||||||
'id' => 'payments-with-stripe',
|
'id' => 'payments-with-stripe',
|
||||||
'name' => 'Payments with Stripe',
|
'name' => 'Payments with Stripe',
|
||||||
|
'score' => 8,
|
||||||
'tagline' => 'Receive card payments and store paid orders.',
|
'tagline' => 'Receive card payments and store paid orders.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1125,6 +1145,7 @@ return [
|
||||||
'icon' => 'icon-chat',
|
'icon' => 'icon-chat',
|
||||||
'id' => 'text-generation-with-huggingface',
|
'id' => 'text-generation-with-huggingface',
|
||||||
'name' => 'Text generation',
|
'name' => 'Text generation',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Generate text using the Hugging Face inference API.',
|
'tagline' => 'Generate text using the Hugging Face inference API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1159,6 +1180,7 @@ return [
|
||||||
'icon' => 'icon-translate',
|
'icon' => 'icon-translate',
|
||||||
'id' => 'language-translation-with-huggingface',
|
'id' => 'language-translation-with-huggingface',
|
||||||
'name' => 'Language translation',
|
'name' => 'Language translation',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Translate text using the Hugging Face inference API.',
|
'tagline' => 'Translate text using the Hugging Face inference API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1193,6 +1215,7 @@ return [
|
||||||
'icon' => 'icon-eye',
|
'icon' => 'icon-eye',
|
||||||
'id' => 'image-classification-with-huggingface',
|
'id' => 'image-classification-with-huggingface',
|
||||||
'name' => 'Image classification',
|
'name' => 'Image classification',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Classify images using the Hugging Face inference API.',
|
'tagline' => 'Classify images using the Hugging Face inference API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => ['buckets.*.files.*.create'],
|
'events' => ['buckets.*.files.*.create'],
|
||||||
|
|
@ -1251,6 +1274,7 @@ return [
|
||||||
'icon' => 'icon-eye',
|
'icon' => 'icon-eye',
|
||||||
'id' => 'object-detection-with-huggingface',
|
'id' => 'object-detection-with-huggingface',
|
||||||
'name' => 'Object detection',
|
'name' => 'Object detection',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Detect objects in images using the Hugging Face inference API.',
|
'tagline' => 'Detect objects in images using the Hugging Face inference API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => ['buckets.*.files.*.create'],
|
'events' => ['buckets.*.files.*.create'],
|
||||||
|
|
@ -1309,6 +1333,7 @@ return [
|
||||||
'icon' => 'icon-text',
|
'icon' => 'icon-text',
|
||||||
'id' => 'speech-recognition-with-huggingface',
|
'id' => 'speech-recognition-with-huggingface',
|
||||||
'name' => 'Speech recognition',
|
'name' => 'Speech recognition',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Transcribe audio to text using the Hugging Face inference API.',
|
'tagline' => 'Transcribe audio to text using the Hugging Face inference API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => ['buckets.*.files.*.create'],
|
'events' => ['buckets.*.files.*.create'],
|
||||||
|
|
@ -1367,6 +1392,7 @@ return [
|
||||||
'icon' => 'icon-chat',
|
'icon' => 'icon-chat',
|
||||||
'id' => 'text-to-speech-with-huggingface',
|
'id' => 'text-to-speech-with-huggingface',
|
||||||
'name' => 'Text to speech',
|
'name' => 'Text to speech',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Convert text to speech using the Hugging Face inference API.',
|
'tagline' => 'Convert text to speech using the Hugging Face inference API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => ['databases.*.collections.*.documents.*.create'],
|
'events' => ['databases.*.collections.*.documents.*.create'],
|
||||||
|
|
@ -1425,6 +1451,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'generate-with-replicate',
|
'id' => 'generate-with-replicate',
|
||||||
'name' => 'Generate with Replicate',
|
'name' => 'Generate with Replicate',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => "Generate text, audio and images using Replicate's API.",
|
'tagline' => "Generate text, audio and images using Replicate's API.",
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1460,6 +1487,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'generate-with-together-ai',
|
'id' => 'generate-with-together-ai',
|
||||||
'name' => 'Generate with Together AI',
|
'name' => 'Generate with Together AI',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => "Generate text and images using Together AI's API.",
|
'tagline' => "Generate text and images using Together AI's API.",
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1502,6 +1530,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'chat-with-perplexity-ai',
|
'id' => 'chat-with-perplexity-ai',
|
||||||
'name' => 'Chat with Perplexity AI',
|
'name' => 'Chat with Perplexity AI',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Create a chatbot using the Perplexity AI API.',
|
'tagline' => 'Create a chatbot using the Perplexity AI API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1543,6 +1572,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'generate-with-replicate',
|
'id' => 'generate-with-replicate',
|
||||||
'name' => 'Generate with Replicate',
|
'name' => 'Generate with Replicate',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => "Generate text, audio and images using Replicate's API.",
|
'tagline' => "Generate text, audio and images using Replicate's API.",
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1578,6 +1608,7 @@ return [
|
||||||
'icon' => 'icon-document-search',
|
'icon' => 'icon-document-search',
|
||||||
'id' => 'sync-with-pinecone',
|
'id' => 'sync-with-pinecone',
|
||||||
'name' => 'Sync with Pinecone',
|
'name' => 'Sync with Pinecone',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => "Sync your Appwrite database with Pinecone's vector database.",
|
'tagline' => "Sync your Appwrite database with Pinecone's vector database.",
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1641,6 +1672,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'rag-with-langchain',
|
'id' => 'rag-with-langchain',
|
||||||
'name' => 'RAG with LangChain',
|
'name' => 'RAG with LangChain',
|
||||||
|
'score' => 6,
|
||||||
'tagline' => 'Generate text using a LangChain RAG model',
|
'tagline' => 'Generate text using a LangChain RAG model',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1704,6 +1736,7 @@ return [
|
||||||
'icon' => 'icon-chat',
|
'icon' => 'icon-chat',
|
||||||
'id' => 'speak-with-elevenlabs',
|
'id' => 'speak-with-elevenlabs',
|
||||||
'name' => 'Speak with ElevenLabs',
|
'name' => 'Speak with ElevenLabs',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Convert text to speech using the ElevenLabs API.',
|
'tagline' => 'Convert text to speech using the ElevenLabs API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'cron' => '',
|
'cron' => '',
|
||||||
|
|
@ -1759,6 +1792,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'speak-with-lmnt',
|
'id' => 'speak-with-lmnt',
|
||||||
'name' => 'Speak with LMNT',
|
'name' => 'Speak with LMNT',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Convert text to speech using the LMNT API.',
|
'tagline' => 'Convert text to speech using the LMNT API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'cron' => '',
|
'cron' => '',
|
||||||
|
|
@ -1800,6 +1834,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'chat-with-anyscale',
|
'id' => 'chat-with-anyscale',
|
||||||
'name' => 'Chat with AnyScale',
|
'name' => 'Chat with AnyScale',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => 'Create a chatbot using the AnyScale API.',
|
'tagline' => 'Create a chatbot using the AnyScale API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'cron' => '',
|
'cron' => '',
|
||||||
|
|
@ -1841,6 +1876,7 @@ return [
|
||||||
'icon' => 'icon-music-note',
|
'icon' => 'icon-music-note',
|
||||||
'id' => 'music-generation-with-huggingface',
|
'id' => 'music-generation-with-huggingface',
|
||||||
'name' => 'Music generation',
|
'name' => 'Music generation',
|
||||||
|
'score' => 4,
|
||||||
'tagline' => 'Generate music from a text prompt using the Hugging Face inference API.',
|
'tagline' => 'Generate music from a text prompt using the Hugging Face inference API.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1883,6 +1919,7 @@ return [
|
||||||
'icon' => 'icon-chip',
|
'icon' => 'icon-chip',
|
||||||
'id' => 'generate-with-fal-ai',
|
'id' => 'generate-with-fal-ai',
|
||||||
'name' => 'Generate with fal.ai',
|
'name' => 'Generate with fal.ai',
|
||||||
|
'score' => 5,
|
||||||
'tagline' => "Generate images using fal.ai's API.",
|
'tagline' => "Generate images using fal.ai's API.",
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1918,6 +1955,7 @@ return [
|
||||||
'icon' => 'icon-currency-dollar',
|
'icon' => 'icon-currency-dollar',
|
||||||
'id' => 'subscriptions-with-lemon-squeezy',
|
'id' => 'subscriptions-with-lemon-squeezy',
|
||||||
'name' => 'Subscriptions with Lemon Squeezy',
|
'name' => 'Subscriptions with Lemon Squeezy',
|
||||||
|
'score' => 6,
|
||||||
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
|
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
@ -1973,6 +2011,7 @@ return [
|
||||||
'icon' => 'icon-currency-dollar',
|
'icon' => 'icon-currency-dollar',
|
||||||
'id' => 'payments-with-lemon-squeezy',
|
'id' => 'payments-with-lemon-squeezy',
|
||||||
'name' => 'Payments with Lemon Squeezy',
|
'name' => 'Payments with Lemon Squeezy',
|
||||||
|
'score' => 6,
|
||||||
'tagline' => 'Receive card payments and store paid orders.',
|
'tagline' => 'Receive card payments and store paid orders.',
|
||||||
'permissions' => ['any'],
|
'permissions' => ['any'],
|
||||||
'events' => [],
|
'events' => [],
|
||||||
|
|
|
||||||
|
|
@ -87,15 +87,6 @@ const TEMPLATE_FRAMEWORKS = [
|
||||||
'adapter' => 'static',
|
'adapter' => 'static',
|
||||||
'fallbackFile' => '',
|
'fallbackFile' => '',
|
||||||
],
|
],
|
||||||
'OTHER' => [
|
|
||||||
'key' => 'other',
|
|
||||||
'name' => 'Other',
|
|
||||||
'installCommand' => 'npm install',
|
|
||||||
'buildCommand' => 'npm run build',
|
|
||||||
'buildRuntime' => 'node-22',
|
|
||||||
'adapter' => 'static',
|
|
||||||
'fallbackFile' => 'index.html',
|
|
||||||
],
|
|
||||||
'VITE' => [
|
'VITE' => [
|
||||||
'key' => 'vite',
|
'key' => 'vite',
|
||||||
'name' => 'Vite',
|
'name' => 'Vite',
|
||||||
|
|
@ -144,6 +135,16 @@ const TEMPLATE_FRAMEWORKS = [
|
||||||
'adapter' => 'static',
|
'adapter' => 'static',
|
||||||
'outputDirectory' => './',
|
'outputDirectory' => './',
|
||||||
],
|
],
|
||||||
|
'LYNX' => [
|
||||||
|
'key' => 'lynx',
|
||||||
|
'name' => 'Lynx',
|
||||||
|
'installCommand' => 'npm install && cd web && npm install && cd ..',
|
||||||
|
'buildCommand' => 'npm run build && cd web && npm run build && cd ..',
|
||||||
|
'buildRuntime' => 'node-22',
|
||||||
|
'adapter' => 'static',
|
||||||
|
'outputDirectory' => './web/dist',
|
||||||
|
'fallbackFile' => 'index.html',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function getFramework(string $frameworkEnum, array $overrides)
|
function getFramework(string $frameworkEnum, array $overrides)
|
||||||
|
|
@ -153,9 +154,30 @@ function getFramework(string $frameworkEnum, array $overrides)
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
[
|
||||||
|
'key' => 'lynx-starter',
|
||||||
|
'name' => 'Lynx Starter',
|
||||||
|
'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],
|
||||||
|
'screenshotDark' => $url . '/images/sites/templates/lynx-starter-dark.png',
|
||||||
|
'screenshotLight' => $url . '/images/sites/templates/lynx-starter-light.png',
|
||||||
|
'frameworks' => [
|
||||||
|
getFramework('LYNX', [
|
||||||
|
'providerRootDirectory' => './lynx/starter',
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
'vcsProvider' => 'github',
|
||||||
|
'providerRepositoryId' => 'templates-for-sites',
|
||||||
|
'providerOwner' => 'appwrite',
|
||||||
|
'providerVersion' => '0.3.*',
|
||||||
|
'variables' => []
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'key' => 'vitepress',
|
'key' => 'vitepress',
|
||||||
'name' => 'Vitepress',
|
'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' => [UseCases::DOCUMENTATION],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/vitepress-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/vitepress-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/vitepress-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/vitepress-light.png',
|
||||||
|
|
@ -177,6 +199,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'vuepress',
|
'key' => 'vuepress',
|
||||||
'name' => 'Vuepress',
|
'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' => [UseCases::DOCUMENTATION],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/vuepress-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/vuepress-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/vuepress-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/vuepress-light.png',
|
||||||
|
|
@ -198,6 +222,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'docusaurus',
|
'key' => 'docusaurus',
|
||||||
'name' => 'Docusaurus',
|
'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' => [UseCases::DOCUMENTATION],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/docusaurus-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/docusaurus-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/docusaurus-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/docusaurus-light.png',
|
||||||
|
|
@ -219,6 +245,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'nxt-lnk',
|
'key' => 'nxt-lnk',
|
||||||
'name' => 'Nxt Lnk',
|
'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' => [UseCases::PORTFOLIO],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/nxt-lnk-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/nxt-lnk-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/nxt-lnk-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/nxt-lnk-light.png',
|
||||||
|
|
@ -236,6 +264,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'magic-portfolio',
|
'key' => 'magic-portfolio',
|
||||||
'name' => 'Magic Portfolio',
|
'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' => [UseCases::PORTFOLIO],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/magic-portfolio-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/magic-portfolio-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/magic-portfolio-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/magic-portfolio-light.png',
|
||||||
|
|
@ -253,6 +283,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'littlelink',
|
'key' => 'littlelink',
|
||||||
'name' => 'LittleLink',
|
'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' => [UseCases::PORTFOLIO],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/littlelink-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/littlelink-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/littlelink-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/littlelink-light.png',
|
||||||
|
|
@ -270,6 +302,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'logspot',
|
'key' => 'logspot',
|
||||||
'name' => 'Logspot',
|
'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' => [UseCases::BLOG],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/logspot-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/logspot-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/logspot-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/logspot-light.png',
|
||||||
|
|
@ -290,6 +324,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'astro-nano',
|
'key' => 'astro-nano',
|
||||||
'name' => 'Astro Nano',
|
'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' => [UseCases::PORTFOLIO],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/astro-nano-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/astro-nano-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/astro-nano-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/astro-nano-light.png',
|
||||||
|
|
@ -309,6 +345,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'astro-starlight',
|
'key' => 'astro-starlight',
|
||||||
'name' => 'Astro Starlight',
|
'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' => [UseCases::DOCUMENTATION],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/astro-starlight-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/astro-starlight-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/astro-starlight-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/astro-starlight-light.png',
|
||||||
|
|
@ -328,6 +366,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'astro-sphere',
|
'key' => 'astro-sphere',
|
||||||
'name' => 'Astro Sphere',
|
'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' => [UseCases::PORTFOLIO],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/astro-sphere-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/astro-sphere-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/astro-sphere-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/astro-sphere-light.png',
|
||||||
|
|
@ -347,6 +387,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'astro-starlog',
|
'key' => 'astro-starlog',
|
||||||
'name' => 'Astro Starlog',
|
'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' => [UseCases::BLOG],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/astro-starlog-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/astro-starlog-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/astro-starlog-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/astro-starlog-light.png',
|
||||||
|
|
@ -366,6 +408,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'onelink',
|
'key' => 'onelink',
|
||||||
'name' => 'Onelink',
|
'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' => [UseCases::PORTFOLIO],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/onelink-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/onelink-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/onelink-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/onelink-light.png',
|
||||||
|
|
@ -387,6 +431,8 @@ return [
|
||||||
'key' => 'starter-for-flutter',
|
'key' => 'starter-for-flutter',
|
||||||
'name' => 'Flutter starter',
|
'name' => 'Flutter starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-flutter-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-flutter-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-flutter-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -430,6 +476,8 @@ return [
|
||||||
'key' => 'starter-for-js',
|
'key' => 'starter-for-js',
|
||||||
'name' => 'JavaScript starter',
|
'name' => 'JavaScript starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-js-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-js-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-js-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -472,6 +520,8 @@ return [
|
||||||
'key' => 'starter-for-angular',
|
'key' => 'starter-for-angular',
|
||||||
'name' => 'Angular starter',
|
'name' => 'Angular starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-angular-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-angular-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-angular-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -516,6 +566,8 @@ return [
|
||||||
'key' => 'starter-for-svelte',
|
'key' => 'starter-for-svelte',
|
||||||
'name' => 'Svelte starter',
|
'name' => 'Svelte starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-svelte-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-svelte-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-svelte-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -558,6 +610,8 @@ return [
|
||||||
'key' => 'starter-for-react',
|
'key' => 'starter-for-react',
|
||||||
'name' => 'React starter',
|
'name' => 'React starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-react-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-react-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-react-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -600,6 +654,8 @@ return [
|
||||||
'key' => 'starter-for-vue',
|
'key' => 'starter-for-vue',
|
||||||
'name' => 'Vue starter',
|
'name' => 'Vue starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-vue-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-vue-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-vue-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -642,6 +698,8 @@ return [
|
||||||
'key' => 'starter-for-react-native',
|
'key' => 'starter-for-react-native',
|
||||||
'name' => 'React Native starter',
|
'name' => 'React Native starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-react-native-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-react-native-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-react-native-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -685,6 +743,8 @@ return [
|
||||||
'key' => 'starter-for-nextjs',
|
'key' => 'starter-for-nextjs',
|
||||||
'name' => 'Next.js starter',
|
'name' => 'Next.js starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-nextjs-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-nextjs-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-nextjs-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -727,6 +787,8 @@ return [
|
||||||
'key' => 'starter-for-nuxt',
|
'key' => 'starter-for-nuxt',
|
||||||
'name' => 'Nuxt starter',
|
'name' => 'Nuxt starter',
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::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',
|
'screenshotDark' => $url . '/images/sites/templates/starter-for-nuxt-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-nuxt-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/starter-for-nuxt-light.png',
|
||||||
'frameworks' => [
|
'frameworks' => [
|
||||||
|
|
@ -768,6 +830,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'template-for-event',
|
'key' => 'template-for-event',
|
||||||
'name' => 'Event template',
|
'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' => [UseCases::EVENTS],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/template-for-event-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/template-for-event-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/template-for-event-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/template-for-event-light.png',
|
||||||
|
|
@ -804,6 +868,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'template-for-portfolio',
|
'key' => 'template-for-portfolio',
|
||||||
'name' => 'Portfolio template',
|
'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' => [UseCases::PORTFOLIO],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/template-for-portfolio-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/template-for-portfolio-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/template-for-portfolio-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/template-for-portfolio-light.png',
|
||||||
|
|
@ -821,6 +887,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'template-for-store',
|
'key' => 'template-for-store',
|
||||||
'name' => 'Store template',
|
'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' => [UseCases::ECOMMERCE],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/template-for-store-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/template-for-store-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/template-for-store-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/template-for-store-light.png',
|
||||||
|
|
@ -863,6 +931,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'template-for-blog',
|
'key' => 'template-for-blog',
|
||||||
'name' => 'Blog template',
|
'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' => [UseCases::BLOG],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/template-for-blog-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/template-for-blog-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/template-for-blog-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/template-for-blog-light.png',
|
||||||
|
|
@ -880,6 +950,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'astro-starter',
|
'key' => 'astro-starter',
|
||||||
'name' => 'Astro starter',
|
'name' => 'Astro starter',
|
||||||
|
'tagline' => 'Sample application built with Astro, a content-driven web framework.',
|
||||||
|
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::STARTER],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/astro-starter-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/astro-starter-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/astro-starter-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/astro-starter-light.png',
|
||||||
|
|
@ -897,6 +969,8 @@ return [
|
||||||
[
|
[
|
||||||
'key' => 'remix-starter',
|
'key' => 'remix-starter',
|
||||||
'name' => 'Remix starter',
|
'name' => 'Remix starter',
|
||||||
|
'tagline' => 'Sample application built with Remix, a React meta-framework.',
|
||||||
|
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||||
'useCases' => [UseCases::STARTER],
|
'useCases' => [UseCases::STARTER],
|
||||||
'screenshotDark' => $url . '/images/sites/templates/remix-starter-dark.png',
|
'screenshotDark' => $url . '/images/sites/templates/remix-starter-dark.png',
|
||||||
'screenshotLight' => $url . '/images/sites/templates/remix-starter-light.png',
|
'screenshotLight' => $url . '/images/sites/templates/remix-starter-light.png',
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||||
throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported');
|
throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($deployment->getAttribute('status') !== 'ready') {
|
$allowAnyStatus = !\is_null($apiKey) && $apiKey->isDeploymentStatusIgnored();
|
||||||
|
if (!$allowAnyStatus && $deployment->getAttribute('status') !== 'ready') {
|
||||||
if ($deployment->getAttribute('status') === 'failed') {
|
if ($deployment->getAttribute('status') === 'failed') {
|
||||||
throw new AppwriteException(AppwriteException::BUILD_FAILED);
|
throw new AppwriteException(AppwriteException::BUILD_FAILED);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
<title>404 Not Found</title>
|
<title>404 Not Found</title>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400);
|
||||||
|
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
@ -36,7 +38,7 @@
|
||||||
background: var(--color-overlay-on-neutral, rgba(0, 0, 0, 0.06));
|
background: var(--color-overlay-on-neutral, rgba(0, 0, 0, 0.06));
|
||||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: var(--font-family-sansSerif, Inter);
|
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||||
font-size: var(--font-size-S, 14px);
|
font-size: var(--font-size-S, 14px);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
@ -47,7 +49,7 @@
|
||||||
h1 {
|
h1 {
|
||||||
color: var(--color-fgColor-neutral-primary, #2D2D31);
|
color: var(--color-fgColor-neutral-primary, #2D2D31);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: var(--font-family-sansSerif, Inter);
|
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||||
font-size: var(--font-size-XXXL, 32px);
|
font-size: var(--font-size-XXXL, 32px);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
@ -59,7 +61,7 @@
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-radius: var(--border-radius-S, 8px);
|
border-radius: var(--border-radius-S, 8px);
|
||||||
font-family: var(--font-family-sansSerif, Inter);
|
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||||
font-size: var(--font-size-S, 14px);
|
font-size: var(--font-size-S, 14px);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
@ -88,7 +90,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand p {
|
.brand p {
|
||||||
font-family: var(--font-family-monospace, "Fira Code");
|
font-family: var(--font-family-monospace, "Fira Code"), monospace;
|
||||||
font-size: var(--font-size-XS, 12px);
|
font-size: var(--font-size-XS, 12px);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
|
||||||
40
composer.lock
generated
40
composer.lock
generated
|
|
@ -709,16 +709,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "google/protobuf",
|
"name": "google/protobuf",
|
||||||
"version": "v4.30.1",
|
"version": "v4.30.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/protocolbuffers/protobuf-php.git",
|
"url": "https://github.com/protocolbuffers/protobuf-php.git",
|
||||||
"reference": "f29ba8a30dfd940efb3a8a75dc44446539101f24"
|
"reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/f29ba8a30dfd940efb3a8a75dc44446539101f24",
|
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/a4c4d8565b40b9f76debc9dfeb221412eacb8ced",
|
||||||
"reference": "f29ba8a30dfd940efb3a8a75dc44446539101f24",
|
"reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -747,9 +747,9 @@
|
||||||
"proto"
|
"proto"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.30.1"
|
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.30.2"
|
||||||
},
|
},
|
||||||
"time": "2025-03-13T21:08:17+00:00"
|
"time": "2025-03-26T18:01:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "jean85/pretty-package-versions",
|
"name": "jean85/pretty-package-versions",
|
||||||
|
|
@ -4700,16 +4700,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/swoole",
|
"name": "utopia-php/swoole",
|
||||||
"version": "0.8.2",
|
"version": "0.8.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/utopia-php/swoole.git",
|
"url": "https://github.com/utopia-php/swoole.git",
|
||||||
"reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4"
|
"reference": "1af73dd3e73987cf729c7db399054e4a70befd99"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4",
|
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/1af73dd3e73987cf729c7db399054e4a70befd99",
|
||||||
"reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4",
|
"reference": "1af73dd3e73987cf729c7db399054e4a70befd99",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -4745,9 +4745,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/utopia-php/swoole/issues",
|
"issues": "https://github.com/utopia-php/swoole/issues",
|
||||||
"source": "https://github.com/utopia-php/swoole/tree/0.8.2"
|
"source": "https://github.com/utopia-php/swoole/tree/0.8.3"
|
||||||
},
|
},
|
||||||
"time": "2024-02-01T14:54:12+00:00"
|
"time": "2025-03-26T10:09:05+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/system",
|
"name": "utopia-php/system",
|
||||||
|
|
@ -5089,16 +5089,16 @@
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "appwrite/sdk-generator",
|
"name": "appwrite/sdk-generator",
|
||||||
"version": "0.40.10",
|
"version": "0.40.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||||
"reference": "054ac96285caf4f77879087b2416a5ddb8263051"
|
"reference": "0ec5f4a60c15e33e208bc3444ba6148b1d0f0027"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/054ac96285caf4f77879087b2416a5ddb8263051",
|
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0ec5f4a60c15e33e208bc3444ba6148b1d0f0027",
|
||||||
"reference": "054ac96285caf4f77879087b2416a5ddb8263051",
|
"reference": "0ec5f4a60c15e33e208bc3444ba6148b1d0f0027",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -5134,9 +5134,9 @@
|
||||||
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.10"
|
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.11"
|
||||||
},
|
},
|
||||||
"time": "2025-03-25T13:44:16+00:00"
|
"time": "2025-03-26T10:53:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/annotations",
|
"name": "doctrine/annotations",
|
||||||
|
|
@ -8507,7 +8507,7 @@
|
||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": [],
|
"stability-flags": {},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
|
|
@ -8531,5 +8531,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "8.3"
|
"php": "8.3"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
public/images/sites/templates/lynx-starter-dark.png
Normal file
BIN
public/images/sites/templates/lynx-starter-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 324 KiB |
BIN
public/images/sites/templates/lynx-starter-light.png
Normal file
BIN
public/images/sites/templates/lynx-starter-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 323 KiB |
|
|
@ -24,6 +24,7 @@ class Key
|
||||||
protected bool $bannerDisabled = false,
|
protected bool $bannerDisabled = false,
|
||||||
protected bool $projectCheckDisabled = false,
|
protected bool $projectCheckDisabled = false,
|
||||||
protected bool $previewAuthDisabled = false,
|
protected bool $previewAuthDisabled = false,
|
||||||
|
protected bool $deploymentStatusIgnored = false,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,6 +80,11 @@ class Key
|
||||||
return $this->previewAuthDisabled;
|
return $this->previewAuthDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isDeploymentStatusIgnored(): bool
|
||||||
|
{
|
||||||
|
return $this->deploymentStatusIgnored;
|
||||||
|
}
|
||||||
|
|
||||||
public function isProjectCheckDisabled(): bool
|
public function isProjectCheckDisabled(): bool
|
||||||
{
|
{
|
||||||
return $this->projectCheckDisabled;
|
return $this->projectCheckDisabled;
|
||||||
|
|
@ -139,6 +145,7 @@ class Key
|
||||||
$bannerDisabled = $payload['bannerDisabled'] ?? false;
|
$bannerDisabled = $payload['bannerDisabled'] ?? false;
|
||||||
$projectCheckDisabled = $payload['projectCheckDisabled'] ?? false;
|
$projectCheckDisabled = $payload['projectCheckDisabled'] ?? false;
|
||||||
$previewAuthDisabled = $payload['previewAuthDisabled'] ?? false;
|
$previewAuthDisabled = $payload['previewAuthDisabled'] ?? false;
|
||||||
|
$deploymentStatusIgnored = $payload['deploymentStatusIgnored'] ?? false;
|
||||||
$scopes = \array_merge($payload['scopes'] ?? [], $scopes);
|
$scopes = \array_merge($payload['scopes'] ?? [], $scopes);
|
||||||
|
|
||||||
if (!$projectCheckDisabled && $projectId !== $project->getId()) {
|
if (!$projectCheckDisabled && $projectId !== $project->getId()) {
|
||||||
|
|
@ -156,7 +163,8 @@ class Key
|
||||||
$hostnameOverride,
|
$hostnameOverride,
|
||||||
$bannerDisabled,
|
$bannerDisabled,
|
||||||
$projectCheckDisabled,
|
$projectCheckDisabled,
|
||||||
$previewAuthDisabled
|
$previewAuthDisabled,
|
||||||
|
$deploymentStatusIgnored
|
||||||
);
|
);
|
||||||
case API_KEY_STANDARD:
|
case API_KEY_STANDARD:
|
||||||
$key = $project->find(
|
$key = $project->find(
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,14 @@ class XList extends Base
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$responseTemplates = \array_slice($templates, $offset, $limit);
|
\usort($templates, function ($a, $b) {
|
||||||
|
return $b['score'] <=> $a['score'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$templates = \array_slice($templates, $offset, $limit);
|
||||||
$response->dynamic(new Document([
|
$response->dynamic(new Document([
|
||||||
'templates' => $responseTemplates,
|
'templates' => $templates,
|
||||||
'total' => \count($responseTemplates),
|
'total' => \count($templates),
|
||||||
]), Response::MODEL_TEMPLATE_FUNCTION_LIST);
|
]), Response::MODEL_TEMPLATE_FUNCTION_LIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ use Utopia\Storage\Device\Local;
|
||||||
use Utopia\System\System;
|
use Utopia\System\System;
|
||||||
use Utopia\VCS\Adapter\Git\GitHub;
|
use Utopia\VCS\Adapter\Git\GitHub;
|
||||||
|
|
||||||
|
use function Swoole\Coroutine\batch;
|
||||||
|
|
||||||
class Builds extends Action
|
class Builds extends Action
|
||||||
{
|
{
|
||||||
public static function getName(): string
|
public static function getName(): string
|
||||||
|
|
@ -783,7 +785,6 @@ class Builds extends Action
|
||||||
$deployment->setAttribute('buildStartAt', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime']))));
|
$deployment->setAttribute('buildStartAt', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime']))));
|
||||||
$deployment->setAttribute('buildEndAt', $endTime);
|
$deployment->setAttribute('buildEndAt', $endTime);
|
||||||
$deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart)));
|
$deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart)));
|
||||||
$deployment->setAttribute('status', 'ready');
|
|
||||||
$deployment->setAttribute('buildPath', $response['path']);
|
$deployment->setAttribute('buildPath', $response['path']);
|
||||||
$deployment->setAttribute('buildSize', $response['size']);
|
$deployment->setAttribute('buildSize', $response['size']);
|
||||||
$deployment->setAttribute('totalSize', $deployment->getAttribute('buildSize', 0) + $deployment->getAttribute('sourceSize', 0));
|
$deployment->setAttribute('totalSize', $deployment->getAttribute('buildSize', 0) + $deployment->getAttribute('sourceSize', 0));
|
||||||
|
|
@ -792,25 +793,16 @@ class Builds extends Action
|
||||||
foreach ($response['output'] as $log) {
|
foreach ($response['output'] as $log) {
|
||||||
$logs .= $log['content'];
|
$logs .= $log['content'];
|
||||||
}
|
}
|
||||||
|
$logs .= "[37mCapturing screenshots ...[0m\n";
|
||||||
$deployment->setAttribute('buildLogs', $logs);
|
$deployment->setAttribute('buildLogs', $logs);
|
||||||
|
|
||||||
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
|
||||||
|
|
||||||
if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) {
|
|
||||||
$resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
|
||||||
$dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
$queueForRealtime
|
$queueForRealtime
|
||||||
->setPayload($deployment->getArrayCopy())
|
->setPayload($deployment->getArrayCopy())
|
||||||
->trigger();
|
->trigger();
|
||||||
|
|
||||||
if ($isVcsEnabled) {
|
/** Screenshot site */
|
||||||
$this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::success("Build id: $deploymentId created");
|
|
||||||
|
|
||||||
if ($resource->getCollection() === 'sites') {
|
if ($resource->getCollection() === 'sites') {
|
||||||
try {
|
try {
|
||||||
$rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [
|
$rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [
|
||||||
|
|
@ -848,72 +840,89 @@ class Builds extends Action
|
||||||
'bannerDisabled' => true,
|
'bannerDisabled' => true,
|
||||||
'projectCheckDisabled' => true,
|
'projectCheckDisabled' => true,
|
||||||
'previewAuthDisabled' => true,
|
'previewAuthDisabled' => true,
|
||||||
|
'deploymentStatusIgnored' => true
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// TODO: @Meldiron if becomes too slow, do concurrently
|
$screenshotError = null;
|
||||||
foreach ($configs as $key => $config) {
|
$screenshots = batch(\array_map(function ($key) use ($configs, $deviceForFiles, $apiKey, $resource, $client, $bucket, $project, $dbForPlatform, &$screenshotError) {
|
||||||
$config['headers'] = \array_merge($config['headers'] ?? [], [
|
return function () use ($key, $configs, $deviceForFiles, $apiKey, $resource, $client, $bucket, $project, $dbForPlatform, &$screenshotError) {
|
||||||
'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey
|
try {
|
||||||
]);
|
$config = $configs[$key];
|
||||||
|
|
||||||
$config['sleep'] = 3000;
|
$config['headers'] = \array_merge($config['headers'] ?? [], [
|
||||||
|
'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey
|
||||||
|
]);
|
||||||
|
$config['sleep'] = 3000;
|
||||||
|
|
||||||
$frameworks = Config::getParam('frameworks', []);
|
$frameworks = Config::getParam('frameworks', []);
|
||||||
$framework = $frameworks[$resource->getAttribute('framework', '')] ?? null;
|
$framework = $frameworks[$resource->getAttribute('framework', '')] ?? null;
|
||||||
if (!is_null($framework)) {
|
if (!is_null($framework)) {
|
||||||
$config['sleep'] = $framework['screenshotSleep'];
|
$config['sleep'] = $framework['screenshotSleep'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $client->fetch(
|
$fetchResponse = $client->fetch(
|
||||||
url: 'http://appwrite-browser:3000/v1/screenshots',
|
url: 'http://appwrite-browser:3000/v1/screenshots',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: $config
|
body: $config
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($response->getStatusCode() >= 400) {
|
if ($fetchResponse->getStatusCode() >= 400) {
|
||||||
throw new \Exception($response->getBody());
|
throw new \Exception($fetchResponse->getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
$screenshot = $response->getBody();
|
$screenshot = $fetchResponse->getBody();
|
||||||
|
|
||||||
$fileId = ID::unique();
|
$fileId = ID::unique();
|
||||||
$fileName = $fileId . '.png';
|
$fileName = $fileId . '.png';
|
||||||
$path = $deviceForFiles->getPath($fileName);
|
$path = $deviceForFiles->getPath($fileName);
|
||||||
$path = str_ireplace($deviceForFiles->getRoot(), $deviceForFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root
|
$path = str_ireplace($deviceForFiles->getRoot(), $deviceForFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root
|
||||||
$success = $deviceForFiles->write($path, $screenshot, "image/png");
|
$success = $deviceForFiles->write($path, $screenshot, "image/png");
|
||||||
|
|
||||||
if (!$success) {
|
if (!$success) {
|
||||||
throw new \Exception("Screenshot failed to save");
|
throw new \Exception("Screenshot failed to save");
|
||||||
}
|
}
|
||||||
|
|
||||||
$teamId = $project->getAttribute('teamId', '');
|
$teamId = $project->getAttribute('teamId', '');
|
||||||
$file = new Document([
|
$file = new Document([
|
||||||
'$id' => $fileId,
|
'$id' => $fileId,
|
||||||
'$permissions' => [
|
'$permissions' => [
|
||||||
Permission::read(Role::team(ID::custom($teamId))),
|
Permission::read(Role::team(ID::custom($teamId))),
|
||||||
],
|
],
|
||||||
'bucketId' => $bucket->getId(),
|
'bucketId' => $bucket->getId(),
|
||||||
'bucketInternalId' => $bucket->getInternalId(),
|
'bucketInternalId' => $bucket->getInternalId(),
|
||||||
'name' => $fileName,
|
'name' => $fileName,
|
||||||
'path' => $path,
|
'path' => $path,
|
||||||
'signature' => $deviceForFiles->getFileHash($path),
|
'signature' => $deviceForFiles->getFileHash($path),
|
||||||
'mimeType' => $deviceForFiles->getFileMimeType($path),
|
'mimeType' => $deviceForFiles->getFileMimeType($path),
|
||||||
'sizeOriginal' => \strlen($screenshot),
|
'sizeOriginal' => \strlen($screenshot),
|
||||||
'sizeActual' => $deviceForFiles->getFileSize($path),
|
'sizeActual' => $deviceForFiles->getFileSize($path),
|
||||||
'algorithm' => Compression::GZIP,
|
'algorithm' => Compression::GZIP,
|
||||||
'comment' => '',
|
'comment' => '',
|
||||||
'chunksTotal' => 1,
|
'chunksTotal' => 1,
|
||||||
'chunksUploaded' => 1,
|
'chunksUploaded' => 1,
|
||||||
'openSSLVersion' => null,
|
'openSSLVersion' => null,
|
||||||
'openSSLCipher' => null,
|
'openSSLCipher' => null,
|
||||||
'openSSLTag' => null,
|
'openSSLTag' => null,
|
||||||
'openSSLIV' => null,
|
'openSSLIV' => null,
|
||||||
'search' => implode(' ', [$fileId, $fileName]),
|
'search' => implode(' ', [$fileId, $fileName]),
|
||||||
'metadata' => ['content_type' => $deviceForFiles->getFileMimeType($path)],
|
'metadata' => ['content_type' => $deviceForFiles->getFileMimeType($path)],
|
||||||
]);
|
]);
|
||||||
$file = Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getInternalId(), $file));
|
$file = Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getInternalId(), $file));
|
||||||
|
|
||||||
$deployment->setAttribute($key, $fileId);
|
return [ 'key' => $key, 'fileId' => $fileId ];
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
$screenshotError = $th->getMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, \array_keys($configs)));
|
||||||
|
|
||||||
|
if (!\is_null($screenshotError)) {
|
||||||
|
throw new \Exception($screenshotError);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($screenshots as $screenshot) {
|
||||||
|
$deployment->setAttribute($screenshot['key'], $screenshot['fileId']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
|
$dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
|
||||||
|
|
@ -928,6 +937,25 @@ class Builds extends Action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Update the status */
|
||||||
|
$deployment->setAttribute('status', 'ready');
|
||||||
|
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
||||||
|
|
||||||
|
if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) {
|
||||||
|
$resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
||||||
|
$dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
$queueForRealtime
|
||||||
|
->setPayload($deployment->getArrayCopy())
|
||||||
|
->trigger();
|
||||||
|
|
||||||
|
if ($isVcsEnabled) {
|
||||||
|
$this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::success("Build id: $deploymentId created");
|
||||||
|
|
||||||
/** Set auto deploy */
|
/** Set auto deploy */
|
||||||
if ($deployment->getAttribute('activate') === true) {
|
if ($deployment->getAttribute('activate') === true) {
|
||||||
$resource->setAttribute('live', true);
|
$resource->setAttribute('live', true);
|
||||||
|
|
@ -1066,6 +1094,12 @@ class Builds extends Action
|
||||||
Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule));
|
Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule));
|
||||||
}
|
}
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $th) {
|
||||||
|
Console::warning('Build failed:');
|
||||||
|
Console::error($th->getMessage());
|
||||||
|
Console::error($th->getFile());
|
||||||
|
Console::error($th->getLine());
|
||||||
|
Console::error($th->getTraceAsString());
|
||||||
|
|
||||||
if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') {
|
if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') {
|
||||||
Console::info('Build has been canceled');
|
Console::info('Build has been canceled');
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class Get extends Base
|
||||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
||||||
->setHttpPath('/v1/sites/templates/:templateId')
|
->setHttpPath('/v1/sites/templates/:templateId')
|
||||||
->desc('Get site template')
|
->desc('Get site template')
|
||||||
->groups(['api', 'sites'])
|
->groups(['api'])
|
||||||
->label('scope', 'public')
|
->label('scope', 'public')
|
||||||
->label('resourceType', RESOURCE_TYPE_SITES)
|
->label('resourceType', RESOURCE_TYPE_SITES)
|
||||||
->label('sdk', new Method(
|
->label('sdk', new Method(
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class XList extends Base
|
||||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
||||||
->setHttpPath('/v1/sites/templates')
|
->setHttpPath('/v1/sites/templates')
|
||||||
->desc('List templates')
|
->desc('List templates')
|
||||||
->groups(['api', 'sites'])
|
->groups(['api'])
|
||||||
->label('scope', 'public')
|
->label('scope', 'public')
|
||||||
->label('resourceType', RESOURCE_TYPE_SITES)
|
->label('resourceType', RESOURCE_TYPE_SITES)
|
||||||
->label('sdk', new Method(
|
->label('sdk', new Method(
|
||||||
|
|
@ -76,10 +76,15 @@ class XList extends Base
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$responseTemplates = \array_slice($templates, $offset, $limit);
|
\usort($templates, function ($a, $b) {
|
||||||
|
return $b['score'] <=> $a['score'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$templates = \array_slice($templates, $offset, $limit);
|
||||||
|
|
||||||
$response->dynamic(new Document([
|
$response->dynamic(new Document([
|
||||||
'templates' => $responseTemplates,
|
'templates' => $templates,
|
||||||
'total' => \count($responseTemplates),
|
'total' => \count($templates),
|
||||||
]), Response::MODEL_TEMPLATE_SITE_LIST);
|
]), Response::MODEL_TEMPLATE_SITE_LIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ class Preview extends Adapter
|
||||||
|
|
||||||
$banner = <<<EOT
|
$banner = <<<EOT
|
||||||
<style>
|
<style>
|
||||||
|
@import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400);
|
||||||
|
|
||||||
#appwrite-preview {
|
#appwrite-preview {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
@ -80,7 +82,7 @@ class Preview extends Adapter
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||||
font-family: var(--font-family-sansSerif, Inter);
|
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||||
font-size: var(--font-size-XS, 12px);
|
font-size: var(--font-size-XS, 12px);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
@ -97,7 +99,7 @@ class Preview extends Adapter
|
||||||
padding: var(--space-1, 2px) var(--space-2, 4px);
|
padding: var(--space-1, 2px) var(--space-2, 4px);
|
||||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: var(--font-family-sansSerif, Inter);
|
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||||
font-size: var(--font-size-XS, 12px);
|
font-size: var(--font-size-XS, 12px);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
@ -120,7 +122,7 @@ class Preview extends Adapter
|
||||||
|
|
||||||
#appwrite-preview-text {
|
#appwrite-preview-text {
|
||||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||||
font-family: var(--font-family-sansSerif, Inter);
|
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||||
font-size: var(--font-size-XS, 12px);
|
font-size: var(--font-size-XS, 12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ class TemplateSite extends Model
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'example' => 'Starter site',
|
'example' => 'Starter site',
|
||||||
])
|
])
|
||||||
|
->addRule('tagline', [
|
||||||
|
'type' => self::TYPE_STRING,
|
||||||
|
'description' => 'Short description of template',
|
||||||
|
'default' => '',
|
||||||
|
'example' => 'Minimal web app integrating with Appwrite.',
|
||||||
|
])
|
||||||
->addRule('demoUrl', [
|
->addRule('demoUrl', [
|
||||||
'type' => self::TYPE_STRING,
|
'type' => self::TYPE_STRING,
|
||||||
'description' => 'URL hosting a template demo.',
|
'description' => 'URL hosting a template demo.',
|
||||||
|
|
|
||||||
|
|
@ -614,19 +614,26 @@ class RealtimeConsoleClientTest extends Scope
|
||||||
|
|
||||||
$previousBuildLogs = $response['data']['payload']['buildLogs'];
|
$previousBuildLogs = $response['data']['payload']['buildLogs'];
|
||||||
|
|
||||||
$this->assertThat(
|
$this->assertEquals('building', $response['data']['payload']['status']);
|
||||||
$response['data']['payload']['status'],
|
|
||||||
$this->logicalOr(
|
|
||||||
$this->equalTo('building'),
|
|
||||||
$this->equalTo('ready'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($response['data']['payload']['status'] === 'ready') {
|
if (!empty($response['data']['payload']['buildEndAt'])) {
|
||||||
|
$this->assertNotEmpty($response['data']['payload']['buildEndAt']);
|
||||||
|
$this->assertNotEmpty($response['data']['payload']['buildStartAt']);
|
||||||
|
$this->assertNotEmpty($response['data']['payload']['buildDuration']);
|
||||||
|
$this->assertNotEmpty($response['data']['payload']['buildPath']);
|
||||||
|
$this->assertNotEmpty($response['data']['payload']['buildSize']);
|
||||||
|
$this->assertNotEmpty($response['data']['payload']['totalSize']);
|
||||||
|
$this->assertNotEmpty($response['data']['payload']['buildLogs']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$response = json_decode($client->receive(), true);
|
||||||
|
$this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']);
|
||||||
|
$this->assertContains('console', $response['data']['channels']);
|
||||||
|
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
|
||||||
|
$this->assertEquals("ready", $response['data']['payload']['status']);
|
||||||
|
|
||||||
$client->close();
|
$client->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ class SitesCustomClientTest extends Scope
|
||||||
$this->assertArrayHasKey('variables', $template);
|
$this->assertArrayHasKey('variables', $template);
|
||||||
$this->assertArrayHasKey('screenshotDark', $template);
|
$this->assertArrayHasKey('screenshotDark', $template);
|
||||||
$this->assertArrayHasKey('screenshotLight', $template);
|
$this->assertArrayHasKey('screenshotLight', $template);
|
||||||
|
$this->assertArrayHasKey('tagline', $template);
|
||||||
}
|
}
|
||||||
|
|
||||||
// List templates with pagination
|
// List templates with pagination
|
||||||
|
|
@ -126,6 +127,7 @@ class SitesCustomClientTest extends Scope
|
||||||
$this->assertEquals('React starter', $template['body']['name']);
|
$this->assertEquals('React starter', $template['body']['name']);
|
||||||
$this->assertEquals(['starter'], $template['body']['useCases']);
|
$this->assertEquals(['starter'], $template['body']['useCases']);
|
||||||
$this->assertEquals('github', $template['body']['vcsProvider']);
|
$this->assertEquals('github', $template['body']['vcsProvider']);
|
||||||
|
$this->assertEquals('Simple React application integrated with Appwrite SDK.', $template['body']['tagline']);
|
||||||
$this->assertIsArray($template['body']['frameworks']);
|
$this->assertIsArray($template['body']['frameworks']);
|
||||||
$this->assertEquals('http://localhost/images/sites/templates/starter-for-react-dark.png', $template['body']['screenshotDark']);
|
$this->assertEquals('http://localhost/images/sites/templates/starter-for-react-dark.png', $template['body']['screenshotDark']);
|
||||||
$this->assertEquals('http://localhost/images/sites/templates/starter-for-react-light.png', $template['body']['screenshotLight']);
|
$this->assertEquals('http://localhost/images/sites/templates/starter-for-react-light.png', $template['body']['screenshotLight']);
|
||||||
|
|
|
||||||
|
|
@ -2430,4 +2430,38 @@ class SitesCustomServerTest extends Scope
|
||||||
|
|
||||||
$this->cleanupSite($siteId);
|
$this->cleanupSite($siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testPermanentRedirect(): void
|
||||||
|
{
|
||||||
|
$siteId = $this->setupSite([
|
||||||
|
'siteId' => ID::unique(),
|
||||||
|
'name' => 'Sub project site',
|
||||||
|
'framework' => 'other',
|
||||||
|
'buildRuntime' => 'node-22',
|
||||||
|
'outputDirectory' => './'
|
||||||
|
]);
|
||||||
|
$this->assertNotEmpty($siteId);
|
||||||
|
|
||||||
|
$domain = $this->setupSiteDomain($siteId);
|
||||||
|
$this->assertNotEmpty($domain);
|
||||||
|
|
||||||
|
$deploymentId = $this->setupDeployment($siteId, [
|
||||||
|
'code' => $this->packageSite('sub-directories'),
|
||||||
|
'activate' => 'true'
|
||||||
|
]);
|
||||||
|
$this->assertNotEmpty($deploymentId);
|
||||||
|
|
||||||
|
$proxyClient = new Client();
|
||||||
|
$proxyClient->setEndpoint('http://' . $domain);
|
||||||
|
$response = $proxyClient->call(Client::METHOD_GET, '/');
|
||||||
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
|
$this->assertStringContainsString('Sub-directory index', $response['body']);
|
||||||
|
$response1 = $proxyClient->call(Client::METHOD_GET, '/project1');
|
||||||
|
$this->assertEquals(200, $response1['headers']['status-code']);
|
||||||
|
$this->assertStringContainsString('Sub-directory project1', $response1['body']);
|
||||||
|
$response2 = $proxyClient->call(Client::METHOD_GET, '/project1/');
|
||||||
|
$this->assertEquals(200, $response2['headers']['status-code']);
|
||||||
|
$this->assertStringContainsString('Sub-directory project1', $response2['body']);
|
||||||
|
$this->cleanupSite($siteId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
tests/resources/sites/sub-directories/index.html
Normal file
5
tests/resources/sites/sub-directories/index.html
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<html lang="en">
|
||||||
|
<body>
|
||||||
|
<p>Sub-directory index</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<html lang="en">
|
||||||
|
<body>
|
||||||
|
<p>Sub-directory project1</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in a new issue