Compare commits

...
Author SHA1 Message Date
Chirag Aggarwal 76b9f48466 chore: update database library 2025-04-25 06:10:13 +00:00
Matej BačoandGitHub f1ff8dd783 Merge pull request #9660 from appwrite/fix-deployment-deletion
Fix deployment and executions deletion
2025-04-17 12:20:41 +02:00
Matej BačoandGitHub f803a2268b Merge branch 'feat-sites' into fix-deployment-deletion 2025-04-17 12:17:10 +02:00
Matej Bačo db44598419 Update composer.lock 2025-04-17 12:16:58 +02:00
Khushboo Verma 93db0c3cd2 Fix logs and executions deletion 2025-04-17 10:14:58 +00:00
Matej Bačo cd9a2b761c Merge branch '1.7.x' into feat-sites 2025-04-17 12:13:06 +02:00
Matej Bačo 9f69aa624e Update comments 2025-04-17 12:11:52 +02:00
Khushboo Verma ad85fc6184 Add resourceType query to deployment deletion 2025-04-17 06:47:16 +00:00
Jake BarnbyandGitHub d8e5a97266 Merge pull request #9622 from appwrite/csv-import
Feat: CSV Import
2025-04-17 06:13:33 +00:00
Darshan 6d3e40d73b address comments: change order, remove comment. 2025-04-17 11:03:03 +05:30
Darshan 767e202b34 update: name. 2025-04-17 10:54:23 +05:30
Darshan fda0af6694 bump: dependency. 2025-04-17 10:51:30 +05:30
Darshan 36ab6ce236 address comments: add more tests. 2025-04-17 10:36:05 +05:30
Darshan 680b214950 update: storage volume name. 2025-04-17 08:59:30 +05:30
Darshan cc7d038c3e address comments: change deviceForCsvImports to deviceForImports. 2025-04-17 08:54:50 +05:30
Matej Bačo 73d1e6c225 Fix tests 2025-04-16 15:39:08 +02:00
Darshan bc8683ab75 add: csv import tests! 2025-04-16 16:52:23 +05:30
Matej Bačo 87d14a88d2 AI-recommended changes 2025-04-16 12:45:58 +02:00
Matej Bačo 733e0498a7 AI-recommended changes 2025-04-16 11:50:42 +02:00
Matej Bačo e48fadf9fd PR review changes 2025-04-16 10:43:02 +02:00
Darshan 9d6cd8249a change: constant name. 2025-04-16 11:56:40 +05:30
Darshan 73b2a14ea3 update: changes as per migrations lib. 2025-04-16 11:55:04 +05:30
Matej BačoandGitHub 9893f77e6d Merge pull request #9606 from appwrite/feat-update-error-pages
Design nice looking error pages
2025-04-15 15:51:21 +02:00
Matej BačoandGitHub 2f537d3948 Merge branch 'feat-sites' into feat-update-error-pages 2025-04-15 15:20:03 +02:00
Matej Bačo e53ec21a2c Improve copy 2025-04-15 15:17:43 +02:00
Matej Bačo 8777fdb417 Remove leftover 2025-04-15 14:16:12 +02:00
Matej Bačo dbe42beb45 Improve tests 2025-04-15 14:16:04 +02:00
Chirag Aggarwal 8944e1db14 chore: update null check for sdk descriptions 2025-04-15 12:04:29 +00:00
Khushboo Verma 0fc41b27ee Dark theme for trace error page 2025-04-15 10:48:25 +00:00
Khushboo Verma 60c632363f Merge branch 'feat-sites' into feat-update-error-pages 2025-04-15 10:45:39 +00:00
Matej Bačo 60fafe8feb PR review changes 2025-04-15 11:40:32 +02:00
Matej BačoandGitHub 2669e66ae2 Merge pull request #9597 from appwrite/fix-usage-sites
Fix: usage stats changes
2025-04-15 11:26:02 +02:00
Matej Bačo 84ec907a47 Merge branch 'feat-sites' into feat-update-error-pages 2025-04-14 14:17:32 +02:00
Matej BačoandGitHub d1d36a2372 Merge pull request #9566 from appwrite/chore-add-tests-for-empty-output-dir
Add tests for empty output directory
2025-04-14 13:39:32 +02:00
Matej BačoandGitHub 0b6a8ec2ca Update tests/e2e/Services/Sites/SitesCustomServerTest.php 2025-04-14 13:39:23 +02:00
Darshan ab73a70c83 address comments. 2025-04-14 16:30:05 +05:30
Matej Bačo ed95ac7643 Re-add test, simplify 2025-04-14 12:54:56 +02:00
Matej Bačo 42f3e06985 Merge branch 'feat-sites' into chore-add-tests-for-empty-output-dir 2025-04-14 12:45:25 +02:00
Matej BačoandGitHub 470857daf8 Merge pull request #9542 from appwrite/chore-add-test-for-empty-source
Chore add test for empty source
2025-04-14 12:43:30 +02:00
Matej Bačo baa1cb19c6 Re-add test, simplify 2025-04-14 12:28:22 +02:00
Matej Bačo 3f5647bcc9 Merge branch 'feat-sites' into chore-add-test-for-empty-source 2025-04-14 12:10:57 +02:00
Darshan 91199e746b update: use plain csv, use options. 2025-04-14 15:03:30 +05:30
Darshan 2ad967043c update: deps. 2025-04-12 17:10:29 +05:30
Darshan a64b8e57af address comments. 2025-04-12 17:10:06 +05:30
Matej Bačo 52024ccc26 Add starters; update console 2025-04-10 16:11:38 +02:00
Khushboo Verma d733e8b75f Add trace button 2025-04-10 16:39:37 +05:30
Matej Bačo 2523613056 Improve logs coloring 2025-04-10 10:20:12 +02:00
Khushboo Verma 7bb548aecb Fix test 2025-04-10 00:39:36 +05:30
Khushboo Verma e78a3e1f83 Fix test 2025-04-10 00:11:17 +05:30
Khushboo Verma 98a5294709 Handle route_not_found 2025-04-09 23:35:08 +05:30
Khushboo Verma 39476fa3d5 Fix button URL for no active deployments 2025-04-09 23:20:06 +05:30
Darshan a53eb6c750 update: bump migrations and update params. 2025-04-09 18:24:59 +05:30
Matej Bačo db15b05332 Upgrade COnsole 2025-04-09 14:35:54 +02:00
Matej Bačo 1a2db06654 Upgrade detector 2025-04-09 13:51:34 +02:00
Darshan 624538fcaf revert: local dockerfile change. 2025-04-09 16:35:27 +05:30
Matej Bačo e2f082eea1 Update specs 2025-04-09 11:48:27 +02:00
Matej BačoandGitHub 2be7e1e8d4 Merge pull request #9627 from appwrite/feat-a-record
Feat: A/AAA record support
2025-04-09 11:13:28 +02:00
Matej Bačo dff1319e4d Fix failure test 2025-04-09 10:50:26 +02:00
Matej Bačo e7b64113ca pr review changes; fix tests 2025-04-09 10:31:33 +02:00
Khushboo Verma 921311e91e Fix tests 2025-04-09 11:58:54 +05:30
Khushboo Verma 0b4b7f5296 Update error message 2025-04-09 10:19:38 +05:30
Khushboo Verma 83401c1004 Add metadata to buttons 2025-04-09 10:13:54 +05:30
Damodar Lohani be939c6598 Fix typo 2025-04-09 02:57:49 +00:00
Damodar LohaniandGitHub db699fe0f6 Merge branch 'feat-sites' into fix-usage-sites 2025-04-09 08:01:15 +05:45
Damodar Lohani 387ef142cc fix test 2025-04-09 02:16:03 +00:00
Matej Baco 2689cceb71 Implement A/AAAA custom domain support 2025-04-08 14:48:50 +00:00
Matej Bačo d205ea61c1 Separate function & site timeout 2025-04-08 12:23:43 +02:00
Matej Bačo 2acf241827 Increase default timeout to fix screenshot cold-start issues 2025-04-08 12:12:53 +02:00
Damodar LohaniandGitHub b862fc6b4c Merge branch 'feat-sites' into fix-usage-sites 2025-04-08 15:30:52 +05:45
Matej Bačo f7605453b4 Upgrade console 2025-04-08 11:26:24 +02:00
Damodar LohaniandGitHub 0c35498dbb Merge branch 'feat-sites' into fix-usage-sites 2025-04-08 14:58:14 +05:45
Matej Bačo 5a0b22f638 Fix after merge 2025-04-08 11:09:12 +02:00
Damodar Lohani c7a97a16df fix test 2025-04-08 09:08:04 +00:00
Damodar Lohani 12bf434f6a fix division by 0 2025-04-08 09:08:00 +00:00
Damodar Lohani a1a6b40277 fix description 2025-04-08 08:59:20 +00:00
Damodar Lohani 8d239b7dc8 Fix test 2025-04-08 08:55:22 +00:00
Darshan 130024e0ef Merge branch '1.7.x' into csv-import 2025-04-08 14:25:01 +05:30
Damodar Lohani ad72805fd6 Fix test 2025-04-08 08:53:36 +00:00
Damodar Lohani 080350f7ad Fix data types and response 2025-04-08 08:52:12 +00:00
Damodar LohaniandGitHub 8d0cdb8e7f Merge branch 'feat-sites' into fix-usage-sites 2025-04-08 14:30:43 +05:45
Matej Bačo a0c013fcec Post-1.6.x-merge fixes 2025-04-08 10:44:57 +02:00
Damodar Lohani ed332a776f More stats in usage endpoints 2025-04-08 08:42:55 +00:00
Matej Bačo 8e32ef1851 Merge branch '1.7.x' into feat-sites 2025-04-08 10:41:39 +02:00
Matej Bačo 69a7c23d2b Merge branch '1.6.x' into 1.7.x 2025-04-08 10:24:09 +02:00
Darshan 89815cba1c revert: local dockerfile change. 2025-04-08 11:20:47 +05:30
Darshan 8dfbc128ac feat: import csv. 2025-04-08 11:19:39 +05:30
Khushboo Verma 9f00ad47f3 Added function execute tests 2025-04-08 11:07:32 +05:30
Damodar Lohani a6d15d032f improve sites usage 2025-04-08 05:06:03 +00:00
Damodar Lohani 327cb671a1 fix sites usage 2025-04-08 04:49:42 +00:00
Damodar LohaniandGitHub 314da2bb85 Merge branch 'feat-sites' into fix-usage-sites 2025-04-08 10:19:42 +05:45
Khushboo Verma 8db6474d80 Add tests for functions 2025-04-08 00:28:51 +05:30
Steven NguyenandGitHub a20ff31ba3 Merge pull request #9561 from appwrite/improve-gitpod-config
chore: update gitpod.yml config
2025-04-07 10:40:33 -07:00
Matej Bačo 89a0fb8c9b Update docker-compose.yml 2025-04-07 17:29:02 +02:00
Khushboo Verma ea1fc208e1 Add tests for no active deployments 2025-04-07 14:38:06 +05:30
Christy JacobandGitHub 31a5a175b3 Merge pull request #9420 from appwrite/PLA-1968
feat: refactor executor setup
2025-04-07 12:49:25 +04:00
Fabian Gruber 0ae70f8321 feat: inject executor instead of creating a new instance 2025-04-07 09:53:38 +02:00
Fabian Gruber 954ed45a36 feat: update appwrite to use generic S3 adapter 2025-04-07 09:53:38 +02:00
Khushboo Verma e718f4252f Add test for canceled deployment error 2025-04-07 12:56:51 +05:30
Damodar Lohani c07c1479f7 fix 2025-04-07 07:15:49 +00:00
Damodar Lohani 76fb59fd73 fix 2025-04-07 07:11:46 +00:00
Damodar Lohani 14e740e62d fix typo 2025-04-07 07:10:52 +00:00
Damodar Lohani cb2905c837 fix use correct method 2025-04-07 07:09:32 +00:00
Damodar Lohani e46ee904e0 reuse code 2025-04-07 07:07:17 +00:00
Khushboo Verma b78fbf02af Merge branch 'feat-sites' into feat-update-error-pages 2025-04-07 12:15:57 +05:30
Damodar Lohani 092bb1adac fix possible division by zero 2025-04-07 06:41:13 +00:00
Damodar Lohani af7c5f9f40 retry sites state test 2025-04-07 06:36:38 +00:00
Damodar Lohani 49a514a206 separate metric test 2025-04-07 06:35:20 +00:00
Damodar Lohani 1b88aa855c fix typo 2025-04-07 06:28:21 +00:00
Damodar Lohani 23ed68502f Sites usage test 2025-04-07 06:27:56 +00:00
Damodar Lohani 8e18af5db1 update get usage and response model 2025-04-07 04:45:20 +00:00
Darshan 179def8f4d add: imports collection 2025-04-07 10:12:58 +05:30
Damodar Lohani b6550c88ef new metrics in functions usage response 2025-04-07 03:52:17 +00:00
Steven NguyenandGitHub fcd31f4cff Merge pull request #9616 from appwrite/update-dependencies
chore: update php image to 0.8.1
2025-04-06 07:25:34 -07:00
Damodar LohaniandGitHub 2d7b01aa35 Merge pull request #9615 from appwrite/fix-owner-downgrade
Restrict role change for sole org owner
2025-04-06 13:59:02 +05:45
Damodar LohaniandGitHub 86478e463a Merge branch 'feat-sites' into fix-usage-sites 2025-04-06 12:04:04 +05:45
Darshan 2243f0c72e fix: test for only console db <> orgs. 2025-04-06 10:29:18 +05:30
Darshan c3c568653f add: roles check test. 2025-04-06 10:21:55 +05:30
Chirag AggarwalandGitHub 403083b0ce Update .gitpod.yml 2025-04-06 08:31:46 +05:30
Chirag Aggarwal e5ef825ac4 chore: update php image to 0.8.1 2025-04-05 15:47:22 +00:00
Chirag Aggarwal abd953974d chore: give read write permission to vendor for gitpod config 2025-04-05 14:43:07 +00:00
Darshan 7297188c1b update: roles check. 2025-04-05 19:42:20 +05:30
Darshan 2a672f5a63 fix: don't allow the only owner in an org to change their role to anything else. 2025-04-05 19:20:24 +05:30
Eldad A. FuxandGitHub a160b0f987 Merge pull request #9559 from appwrite/change-sample-rate
Sample rate from DSN
2025-04-04 11:08:21 +02:00
Matej Bačo fb1a19747a Add documentation template 2025-04-04 10:44:03 +02:00
DarshanandGitHub 01e2eb5025 Merge branch '1.6.x' into change-sample-rate 2025-04-04 13:44:28 +05:30
Jake BarnbyandGitHub baffa615e6 Merge pull request #9610 from appwrite/remove-audit-payload
Remove audit payload
2025-04-04 04:26:43 +00:00
fogelito bd87672607 Remove audit payload 2025-04-03 18:31:50 +03:00
Khushboo Verma 8139ec0d6f Add more error pages 2025-04-03 18:49:41 +05:30
Khushboo Verma 5841d5ee57 Add tests for error pages 2025-04-03 12:35:05 +05:30
Damodar Lohani 7935658222 dev interval to 30s 2025-04-03 06:11:44 +00:00
Damodar LohaniandGitHub 1c10528585 Merge branch 'feat-sites' into fix-usage-sites 2025-04-03 10:23:34 +05:45
Jake BarnbyandGitHub 2e784c0e8b Merge pull request #9608 from appwrite/fix-image-transformations-cache
Fix: image transformation cache
2025-04-03 04:21:49 +00:00
Damodar Lohani 5d2b0c38d9 Fix reduce for functions and sites 2025-04-03 04:16:27 +00:00
Damodar Lohani 1660c0b00c Fix: image transformation cache 2025-04-03 02:44:29 +00:00
Khushboo Verma 579f795c81 Merge branch 'feat-sites' into feat-update-error-pages 2025-04-03 00:00:19 +05:30
Khushboo Verma c684d0a2cd Enhance error pages 2025-04-02 23:59:43 +05:30
Matej Bačo 8fbc517b17 Fix rules cleanup 2025-04-02 16:47:37 +02:00
Damodar Lohani 13510ffcb5 new sites metrics 2025-04-02 05:15:33 +00:00
Damodar Lohani 0d9743c8cb separate sites network metrics 2025-04-02 05:10:12 +00:00
Damodar Lohani d1e083338e fix disable metrics for static sites 2025-04-02 05:05:24 +00:00
Damodar Lohani 0d7187a5cc Skip metrics when sites executed during build 2025-04-02 04:48:22 +00:00
Jake BarnbyandGitHub 96327a9ebc Merge pull request #9603 from appwrite/feat-tenant-type-fixes
Update database
2025-04-02 02:49:10 +00:00
Jake Barnby 32a5ff4c8c Update release 2025-04-02 13:37:26 +13:00
Jake Barnby 31b1663f6b Merge remote-tracking branch 'origin/1.6.x' into feat-tenant-type-fixes
# Conflicts:
#	composer.lock
2025-04-02 13:30:51 +13:00
Jake Barnby c152d8e001 Update database 2025-04-02 13:02:35 +13:00
Eldad A. FuxandGitHub 8fd6208502 Merge pull request #9602 from appwrite/feat-update-ws
Feat update ws
2025-04-01 21:52:14 +02:00
Eldad Fux 938505da51 Updated websocket version 2025-04-01 21:23:23 +02:00
Matej Bačo 51d2deca5f Fix endpoint description 2025-04-01 20:44:49 +02:00
Matej Bačo 1bdbb8fce1 Fix failing tests 2025-04-01 16:50:11 +02:00
Matej Bačo d87c67eecb Fix failing tests 2025-04-01 15:29:07 +02:00
Matej Bačo 8a2ec0dcd7 Add 1.7.x specs 2025-04-01 15:19:18 +02:00
Matej Bačo 9c6551ff7b Update specs 2025-04-01 13:27:33 +02:00
Matej Bačo 066474010b Improve QR quality 2025-04-01 11:24:42 +02:00
Matej Bačo 7bbf04e7ac Merge branch '1.7.x' into feat-sites 2025-04-01 10:49:44 +02:00
Damodar Lohani feb5d5cbf1 fix counts 2025-04-01 08:07:47 +00:00
Damodar Lohani a36adbd68b Fix: skipped metrics 2025-04-01 07:31:53 +00:00
Damodar LohaniandGitHub 30462b1951 Merge pull request #9598 from appwrite/cast-tenant
Fix tenant casting
2025-04-01 11:54:31 +05:45
fogelito b46de29735 database 0.63.2 2025-04-01 08:15:03 +03:00
fogelito d92413fd6b Revert database lib 2025-04-01 08:13:56 +03:00
Damodar Lohani 04010ca205 fix missing param 2025-04-01 05:08:58 +00:00
Damodar Lohani 840eb1776e fix typo 2025-04-01 05:07:44 +00:00
Damodar Lohani 3fd42d3fc6 sites metrics in stats resources 2025-04-01 05:02:54 +00:00
Damodar Lohani 3a3e9cc281 Fix get usage - sites and functions 2025-04-01 03:59:40 +00:00
Damodar Lohani 7ecba8e5bb add disabled metrics 2025-04-01 02:41:27 +00:00
Damodar Lohani 1af638deef new resource type metrics 2025-04-01 02:21:52 +00:00
Matej Bačo dd8b718985 Rollback unwanted changes 2025-03-31 18:52:46 +02:00
Matej Bačo ef39f8c2e2 Fix multiple small bugs
- VCS deployments stuck in waiting
- Fix tcp coroutine issues in builds worker, failing screenshots
- Fix command escaping with space and quotes
- Remove branding from already branded 404 page
- Fix css reset of preview banner
- Remove scope check from public endpoints
- Improve build logs colors
- Function logs say capturing screenshot
- Update GitHub comment design
2025-03-31 18:51:33 +02:00
fogelito 4698323f38 lock 2025-03-31 16:19:17 +03:00
fogelito 612b064d2a 0.63.2 2025-03-31 15:16:59 +03:00
Damodar Lohani e629037da2 use proper resource type 2025-03-31 07:56:26 +00:00
Damodar Lohani ad9d953e10 fix missing resource type 2025-03-31 07:51:37 +00:00
Damodar Lohani 11bd9e63f0 update constants 2025-03-31 06:45:16 +00:00
Damodar Lohani ac152a76b5 Fix: usage stats changes 2025-03-31 06:28:58 +00:00
Christy JacobandGitHub 1a5e9748f3 Merge pull request #9592 from appwrite/feat-update-fetch
Feat update fetch
2025-03-29 00:37:29 +04:00
Eldad Fux 22939831f2 Updated fetch version 2025-03-28 20:58:25 +01:00
Steven NguyenandGitHub e0a54a2ea6 Merge pull request #9503 from appwrite/pla-2610
feat: add query by role to memberships
2025-03-28 07:14:13 -07:00
Matej Bačo fbd0051118 Make env var public 2025-03-28 11:38:45 +01:00
Khushboo Verma ace7a6baa1 Resolve merge conflicts 2025-03-28 13:35:53 +05:30
Jake BarnbyandGitHub 2069c9fdad Merge pull request #9588 from appwrite/fix-select-cursor-pagination
Add order by for cursor
2025-03-28 06:33:27 +00:00
fogelito a4c18c4b77 Remove array merge 2025-03-28 09:16:25 +03:00
fogelito cba700402b Add order by for cursor 2025-03-28 09:04:50 +03:00
Chirag Aggarwal 85edfc6af8 chore: added test for users.listmemberships 2025-03-28 05:47:18 +00:00
Matej Bačo cfe6b8d34b Add score to function templates 2025-03-27 14:23:15 +01:00
Matej BačoandGitHub aedfe0352d Merge pull request #9553 from appwrite/feat-fix-308-redirect
Feat fix 308 redirect
2025-03-27 14:05:36 +01:00
Christy JacobandGitHub 60399aaa0a Merge pull request #9573 from appwrite/feat-multi-tenant-insert-2
Feat multi tenant insert
2025-03-27 15:54:30 +04:00
Khushboo Verma 9404e9225e Update test 2025-03-27 16:36:37 +05:30
Khushboo Verma e263d681d9 Resolve merge conflicts 2025-03-27 16:27:26 +05:30
Matej Bačo 6b8df26f84 Update libs 2025-03-27 11:56:09 +01:00
Matej Bačo e8cc95323e Generate specs 2025-03-27 11:34:38 +01:00
Matej Bačo 7c1fb0d945 Add template details 2025-03-27 11:32:03 +01:00
Matej Bačo 20f780a58b Add lynx 2025-03-27 09:55:04 +01:00
Jake Barnby ad7552e676 Merge remote-tracking branch 'origin/1.6.x' into feat-multi-tenant-insert-2 2025-03-27 21:39:57 +13:00
Christy JacobandGitHub 93839ec36d Merge pull request #9586 from appwrite/revert-9533-PLA-2683
Revert "chore(audits): return queue pre-fetch results"
2025-03-27 12:38:00 +04:00
Jake BarnbyandGitHub 17dc8e3f8a Revert "chore(audits): return queue pre-fetch results" 2025-03-27 21:37:10 +13:00
Matej BačoandGitHub 3d1ea6d330 Merge pull request #9580 from appwrite/fix-deployment-status
Fix: Deployment status
2025-03-27 09:31:17 +01:00
Matej Bačo 834872870f Linter fix 2025-03-27 09:17:15 +01:00
Matej BačoandGitHub 1946fca9f6 Merge branch 'feat-sites' into fix-deployment-status 2025-03-27 09:00:36 +01:00
Khushboo Verma e4b9b92cbf Use Fira Code for powered by 2025-03-27 13:27:51 +05:30
Jake Barnby c79e8e5b95 Update database 2025-03-27 18:04:17 +13:00
Jake Barnby a60d19fb42 Merge remote-tracking branch 'origin/1.6.x' into feat-multi-tenant-insert-2 2025-03-27 17:23:15 +13:00
Matej Bačo 6af57ca48e Fix async crashes 2025-03-26 17:51:39 +01:00
Christy JacobandGitHub ef7cf41a61 Merge pull request #9533 from appwrite/PLA-2683
chore(audits): return queue pre-fetch results
2025-03-26 22:16:52 +05:30
Matej Bačo 3c8e4da34d Update tests 2025-03-26 17:04:38 +01:00
Matej BačoandGitHub 3b1f2afbd5 Merge pull request #9569 from appwrite/chore-add-error-for-failed-builds
If build has failed, show correct error page
2025-03-26 15:44:39 +01:00
Matej Bačo 34ab21730d Linter fix 2025-03-26 15:22:19 +01:00
Matej Bačo 70fbf69c56 Fix fonts 2025-03-26 14:38:27 +01:00
Matej Bačo 62be0e1d00 Fix latest deployment attributes 2025-03-26 14:38:18 +01:00
Matej Bačo 2c55f5aaa6 Concurrency screenshots 2025-03-26 13:20:14 +01:00
Matej Bačo 681b6031aa Linter fix 2025-03-26 12:59:15 +01:00
Matej Bačo ab03b4e3ca Deployment ready after screenshot 2025-03-26 12:59:05 +01:00
Khushboo Verma 2e0a6f9b9e Update swoole version 2025-03-26 17:22:49 +05:30
Khushboo Verma 572544bf55 Merge branch 'feat-sites' into feat-fix-308-redirect 2025-03-26 17:17:23 +05:30
Khushboo Verma 583a18dcd7 Update assertion 2025-03-26 17:06:19 +05:30
Khushboo Verma 3b9318c2fc Add tests 2025-03-26 16:52:32 +05:30
Jake BarnbyandGitHub 91ad4097ff Merge branch '1.6.x' into feat-multi-tenant-insert-2 2025-03-26 11:16:27 +00:00
Jake Barnby d9d38197dd Update libs 2025-03-26 23:47:59 +13:00
Khushboo Verma e836df13ba Merge branch 'feat-sites' into chore-add-error-for-failed-builds 2025-03-26 16:11:03 +05:30
Jake Barnby a8b2ebb356 Merge remote-tracking branch 'origin/1.6.x' into feat-multi-tenant-insert-2 2025-03-26 23:36:18 +13:00
Matej Bačo 023597842e Merge branch 'feat-sites' of github.com:appwrite/appwrite into feat-sites 2025-03-26 10:34:57 +01:00
Matej Bačo c57ec57277 Upgrade Console 2025-03-26 10:22:58 +01:00
Matej Bačo 6978f6960e Add new templates; fix bash support during QA 2025-03-26 10:14:51 +01:00
Jake BarnbyandGitHub c53262a44c Merge pull request #9579 from appwrite/fix-select-cursor-pagination
Add $permissions for delete documents selects
2025-03-26 08:52:51 +00:00
fogelito 8339435fb5 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into fix-select-cursor-pagination 2025-03-26 10:02:50 +02:00
fogelito 424a357503 Add $permissions 2025-03-26 10:02:30 +02:00
Jake BarnbyandGitHub 9a7512d1fd Merge pull request #9578 from appwrite/fix-select-cursor-pagination
Deletes worker fix selects for pagination
2025-03-26 07:35:41 +00:00
fogelito a461d5bf72 Deletes fix selects 2025-03-26 09:20:44 +02:00
Matej BačoandGitHub 95ba881ab7 Merge pull request #9575 from appwrite/feat-bash-support
Feat: Bash support
2025-03-25 23:55:33 +01:00
Matej Bačo 708b6279e0 upgrade lib 2025-03-25 23:38:44 +01:00
Matej Bačo 0295dfcc63 Fix function tsts 2025-03-25 23:07:56 +01:00
Matej BačoandGitHub 06f138b39d Merge branch 'feat-sites' into feat-bash-support 2025-03-25 22:50:18 +01:00
Christy JacobandGitHub 9d020fdef5 Merge pull request #9577 from appwrite/fix-region-scheduler
Fix: schedules region filtering
2025-03-26 02:24:13 +05:30
Matej Bačo f25143b240 Support fra-region on cloud; temporary fix 2025-03-25 21:52:02 +01:00
Matej Bačo d89cdbcf5a Fix schedules region filtering 2025-03-25 21:34:09 +01:00
Matej Bačo 524ce8789f Upgrade libs 2025-03-25 21:01:28 +01:00
Matej Bačo 8db247c840 Update SDKs 2025-03-25 15:57:38 +01:00
Matej BačoandGitHub b11749c452 Merge pull request #9576 from appwrite/feat-add-logging-param-to-sites
Add logging param to sites
2025-03-25 15:55:22 +01:00
Khushboo Verma c38a5177dd Address PR comments 2025-03-25 20:02:29 +05:30
Khushboo Verma abae54f72c Update copy for logging 2025-03-25 19:49:57 +05:30
Khushboo Verma bf2b3b68e3 Add logging param to sites 2025-03-25 19:14:14 +05:30
Matej BačoandGitHub 11d2b06b67 Merge pull request #9570 from appwrite/feat-add-fallback-file-to-deployment
Add fallbackfile and adapter to deployments collection
2025-03-25 14:14:52 +01:00
Khushboo Verma fe94717196 Update tests 2025-03-25 18:31:14 +05:30
Khushboo Verma 5582c6956d Remove specific checks 2025-03-25 17:03:19 +05:30
Khushboo Verma 2acce83257 Merge branch 'feat-sites' into chore-add-tests-for-empty-output-dir 2025-03-25 16:31:27 +05:30
Matej Bačo 81b3e81d83 Add bash support 2025-03-25 10:57:32 +01:00
Jake Barnby 6195674611 Update database 2025-03-25 21:20:26 +13:00
Jake BarnbyandGitHub 4804bdf110 Merge pull request #9568 from appwrite/db-0-62-1
Bump database 0.62.x
2025-03-25 03:44:18 +00:00
Jake BarnbyandGitHub cb356bc410 Merge pull request #9523 from appwrite/delete-query-fixes
Delete worker queries fixes
2025-03-25 03:19:39 +00:00
Jake Barnby 74d9a3c181 Fix syntax 2025-03-25 16:19:18 +13:00
Jake BarnbyandGitHub 6bcdc8c769 Update src/Appwrite/Utopia/Database/Validator/Queries/Base.php 2025-03-25 16:01:27 +13:00
Jake BarnbyandGitHub c9c9db5640 Update src/Appwrite/Platform/Workers/Deletes.php 2025-03-25 15:52:59 +13:00
Jake BarnbyandGitHub a20140eb36 Update src/Appwrite/Platform/Workers/Deletes.php 2025-03-25 15:52:54 +13:00
Jake BarnbyandGitHub c0cb4b26a3 Apply suggestions from code review 2025-03-25 15:51:47 +13:00
Jake BarnbyandGitHub b842e03f38 Merge branch '1.6.x' into delete-query-fixes 2025-03-25 02:43:08 +00:00
fogelito 2795505e82 line 2025-03-24 17:38:01 +02:00
fogelito 5799ca1041 remove var_dump 2025-03-24 17:37:34 +02:00
fogelito e11e7e6780 Add internalId 2025-03-24 17:33:02 +02:00
Khushboo Verma 9fd8c5ab9d Add fallbackfile and adapter to deployments collection 2025-03-24 20:04:02 +05:30
fogelito 0648de2046 Revert Base 2025-03-24 14:32:57 +02:00
fogelito 42f72b4477 Add internalId to orders 2025-03-24 13:33:36 +02:00
Matej Bačo 871e4b70f7 Upgrade Console 2025-03-24 12:32:44 +01:00
Matej Bačo 3e7cf6d60a Fix tests 2025-03-24 12:13:28 +01:00
fogelito 25b6d59e30 Add internalId 2025-03-24 12:54:19 +02:00
Khushboo Verma bd18edc197 If build has failed, show correct error page 2025-03-24 15:50:25 +05:30
Fabian Gruber 5479e6f8f1 chore(audits): return queue pre-fetch results 2025-03-24 10:18:16 +01:00
fogelito 586e676299 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into db-0-62-1 2025-03-24 11:10:21 +02:00
fogelito 26821c8372 Bump database 0.62 2025-03-24 11:08:39 +02:00
Jake BarnbyandGitHub 6e146889bf Merge pull request #9563 from appwrite/refactor-init-auditretention
refactor: initialization of audit retention
2025-03-24 08:53:19 +00:00
Khushboo Verma 1580bac1fc Add tests for empty output directory 2025-03-24 13:30:21 +05:30
Chirag Aggarwal 37dfe0d719 refactor: initialization of audit retention 2025-03-22 14:05:39 +00:00
Chirag Aggarwal 86856bf87d chore: update gitpod.yml config 2025-03-22 13:55:23 +00:00
Darshan 7c2ab4fcf6 update: change sample rate for 4xx via env. 2025-03-22 13:47:09 +05:30
Steven NguyenandGitHub 29ea03b7bb Merge pull request #9554 from appwrite/fix-team-count
chore: only update total count for privileged users
2025-03-21 10:09:22 -07:00
Chirag Aggarwal d661195a5f chore: only update total count for prviledged users 2025-03-21 15:59:30 +00:00
Matej Bačo 0f182817ec Sync templates 2025-03-21 15:46:36 +01:00
Khushboo Verma 65aa218aac Add test for permanent redirect 2025-03-21 17:54:07 +05:30
Khushboo Verma df943c62ca Add test for permanent redirect 2025-03-21 17:53:22 +05:30
Christy JacobandGitHub 50e7986f84 Merge pull request #9547 from appwrite/fix-audit-deletion
chore: fix console audits delete
2025-03-21 15:23:06 +05:30
Christy JacobandGitHub c7301af18a Merge pull request #9525 from appwrite/pla-2676
chore: stop tests on failure
2025-03-21 15:15:09 +05:30
Chirag Aggarwal c0c0c921dc chore: fix naming 2025-03-21 08:08:30 +00:00
Chirag Aggarwal 7c795da72f chore: fix type 2025-03-21 07:48:50 +00:00
Chirag Aggarwal 13750f7dbd feat: introduce new env 2025-03-21 07:42:10 +00:00
Khushboo Verma 21f12879ef Remove extra check 2025-03-21 12:11:29 +05:30
Khushboo Verma 1091aa3ddc Merge branch 'feat-sites' into chore-add-test-for-empty-source 2025-03-21 12:08:22 +05:30
Matej BačoandGitHub c323c227f9 Merge pull request #9549 from appwrite/fix-github-check-url
Fix GitHub check URL
2025-03-20 16:50:34 +01:00
Matej BačoandGitHub d72ba2a4b9 Merge pull request #9551 from appwrite/chore-code-readability-tasks-and-workers
Split params across multiple lines where overflowing
2025-03-20 16:50:01 +01:00
Matej BačoandGitHub ccb96d6525 Merge pull request #9550 from appwrite/chore-re-enable-commented-tests
Re-enable test
2025-03-20 16:49:16 +01:00
Matej Bačo 2dcebf3083 Add remaining changes after sync with 1.7.x 2025-03-20 16:48:09 +01:00
Matej Bačo cb85cfc5d9 Merge branch '1.7.x' into feat-sites 2025-03-20 16:42:36 +01:00
Matej Bačo 4aaa07d57b Merge branch '1.6.x' into 1.7.x 2025-03-20 16:41:18 +01:00
Matej BačoandGitHub d07b543e71 Merge pull request #9537 from appwrite/feat-latest-deployment-details
Feat: Latest deployment details
2025-03-20 16:40:04 +01:00
Matej Bačo 08b74007f7 Fix specs for console 2025-03-20 16:20:31 +01:00
Khushboo Verma 813424aa3c Split params across multiple lines where overflowing 2025-03-20 20:37:32 +05:30
Khushboo Verma e28333ed63 Re-enable test 2025-03-20 20:23:36 +05:30
Matej Bačo 172ebb5f7f Update specs 2025-03-20 15:51:15 +01:00
Matej Bačo 0f5480cbc0 Fix copy 2025-03-20 15:48:18 +01:00
Matej Bačo e34fc92c7c PR review changes 2025-03-20 15:44:15 +01:00
Matej Bačo bb01c9e9e9 Add latest deployment tests 2025-03-20 15:22:35 +01:00
Chirag Aggarwal b0b57935da chore: add comments 2025-03-20 13:42:19 +00:00
Chirag Aggarwal 7c3f8504bb chore: fix initialization 2025-03-20 13:15:14 +00:00
Khushboo Verma ec6683cfa9 Refactor 2025-03-20 18:44:00 +05:30
Khushboo Verma c2d0aded6d Fix GitHub check URL 2025-03-20 18:04:36 +05:30
Chirag Aggarwal 9d82892219 chore: update logic 2025-03-20 11:32:06 +00:00
Chirag Aggarwal 5eb7c36f50 chore: add console audit retention 2025-03-20 10:32:36 +00:00
fogelito 9c54cce5bd Queries fixes 2025-03-20 09:07:32 +02:00
Jake BarnbyandGitHub 9345025ade Merge pull request #9546 from appwrite/feat-improve-maintenance
Use cursor pagination with bigger limit for maintenance project loop
2025-03-20 02:51:31 +00:00
Jake Barnby 31ca35782b Use cursor pagination with bigger limit for maintenance project loop 2025-03-20 15:21:24 +13:00
Christy JacobandGitHub 2505e25da8 Merge pull request #9430 from appwrite/updates-projects-regions
Remove default region
2025-03-19 22:36:30 +05:30
fogelito cc0a97b10e Fixes 2025-03-19 16:37:15 +02:00
Khushboo Verma 18022d680b Assert exception 2025-03-19 16:22:38 +05:30
Khushboo Verma 7c75b51b1a Merge branch 'feat-sites' into chore-add-test-for-empty-source 2025-03-19 16:16:25 +05:30
shimon 88d6150db2 revert 2025-03-19 10:29:18 +02:00
shimon faed019d92 revert 2025-03-19 09:32:48 +02:00
shimon b318c2cc08 Merge branch '1.6.x' of github.com:appwrite/appwrite into updates-projects-regions 2025-03-18 21:54:55 +02:00
shimon eb4340cf4c revert 2025-03-18 21:49:28 +02:00
shimon ee09e2c91b revert 2025-03-18 21:47:54 +02:00
shimon e6e7c5c816 revert 2025-03-18 21:44:34 +02:00
shimon e9841e53b9 revert 2025-03-18 21:40:46 +02:00
Eldad A. FuxandGitHub 7d86ce76d8 Merge pull request #9536 from appwrite/pla-2687
chore: set min operations to 1 for reads and writes
2025-03-18 16:30:52 +01:00
fogelito 795928a037 Fix $id 2025-03-18 16:59:05 +02:00
Matej Bačo e75441a097 Didn't mean to remove that 🎀 2025-03-18 15:46:28 +01:00
Matej Bačo ffb86ace38 Add latest info detail to site & function 2025-03-18 15:29:21 +01:00
Chirag Aggarwal aab8bca91e fix: logic 2025-03-18 14:20:25 +00:00
Matej BačoandGitHub 963760678c Merge pull request #9534 from appwrite/feat-active-deployment-details
Feat: Active deployment details - status, creation date
2025-03-18 15:03:06 +01:00
Chirag Aggarwal 70e27748be chore: set min operations to 1 for reads and writes 2025-03-18 12:52:41 +00:00
Jake BarnbyandGitHub 556e00b62b Merge pull request #9526 from appwrite/feat-disable-pdo-persist
Disable PDO persistence since we manage our own pool
2025-03-18 12:19:58 +00:00
Khushboo VermaandGitHub e95aeed56c Merge pull request #9535 from appwrite/fix-github-author-url
Fix incorrect URL for git commits
2025-03-18 17:39:37 +05:30
Matej Bačo 362520ff4a Remove active depoyment status (not relevant, always ready) 2025-03-18 12:56:44 +01:00
Khushboo Verma 1299fffdb2 Fix incorrect URL for git commits 2025-03-18 17:18:08 +05:30
Matej Bačo 7cade1a27d Add active deployment status and creation date 2025-03-18 12:44:21 +01:00
Matej BačoandGitHub 20d90e06f2 Merge pull request #9532 from appwrite/feat-site-deployment-details
Feat: Add screenshots to site
2025-03-18 12:16:55 +01:00
Matej Bačo ef163e8517 Add screenshots to site 2025-03-18 12:01:30 +01:00
Matej BačoandGitHub a0d4e4736c Merge pull request #9524 from appwrite/feat-deployment-total-size
Feat: totalSize attribute
2025-03-18 11:03:11 +01:00
Matej Bačo 3f1c4c2095 Add per-framework screenshot sleep 2025-03-18 11:02:32 +01:00
Christy JacobandGitHub 370a8e231c Merge pull request #9530 from appwrite/PLA-2662
feat: add pool telemetry
2025-03-18 14:44:52 +05:30
Matej Bačo 83bcad6e17 Fix deployment rule deletion 2025-03-18 10:10:16 +01:00
Fabian Gruber aa5ea7f3a1 feat: add pool telemetry 2025-03-18 10:01:06 +01:00
Jake BarnbyandGitHub 8a77eaf2bb Merge pull request #9529 from appwrite/feat-migration-read-db
Migration read from db
2025-03-18 08:01:07 +00:00
Jake Barnby fe308b4f1f Update lib 2025-03-18 20:49:19 +13:00
Khushboo Verma 20e3597a27 WIP: Add test for empty source 2025-03-18 13:04:44 +05:30
Jake Barnby e43a3109eb Update migration lib 2025-03-18 20:05:12 +13:00
Jake Barnby d9fbe9658d Merge branch '1.6.x' into feat-migration-read-db 2025-03-18 20:04:23 +13:00
Jake BarnbyandGitHub 1e2f5bcb84 Merge branch '1.6.x' into feat-disable-pdo-persist 2025-03-18 07:02:54 +00:00
Christy JacobandGitHub 088d0998cd Merge pull request #9514 from appwrite/feat-domains-count
Feat: domains count
2025-03-18 11:03:45 +05:30
Jake Barnby a7165e6a32 Disable PDO persistence since we manage our own pool 2025-03-18 16:51:00 +13:00
Chirag Aggarwal 5f7ceecb30 chore: stop tests on failure 2025-03-18 03:46:14 +00:00
Matej Bačo fd4b43569b Enable CodeRabbit for feat-sites 2025-03-17 17:48:33 +01:00
Matej Bačo b4536a94e0 Introduce dpeloyment totalSize + tests 2025-03-17 17:35:03 +01:00
shimon e5261e7d70 _app_region 2025-03-17 18:31:14 +02:00
shimon 60912cb084 _app_region 2025-03-17 18:14:58 +02:00
shimon 7149deeacb _app_region 2025-03-17 18:11:49 +02:00
shimon 59f613f9bb _app_region 2025-03-17 17:33:48 +02:00
shimon 8184bc8c78 _app_region 2025-03-17 17:31:24 +02:00
Matej BačoandGitHub 6c193f4862 Merge pull request #9522 from appwrite/fix-frameworks-response
Fix: Response model for framework (adapters)
2025-03-17 16:20:47 +01:00
fogelito bbfd22ce2e Index check for delete worker 2025-03-17 17:05:40 +02:00
Matej Bačo 23b245e058 Leftover 2025-03-17 16:03:52 +01:00
Matej Bačo ae5267cda7 Fix response model for adapters (frameworks) 2025-03-17 16:02:16 +01:00
Matej BačoandGitHub f1b5807174 Merge pull request #9519 from appwrite/fix-realtime-deployments
Fix: Realtime events in build worker
2025-03-17 15:30:54 +01:00
Matej Bačo 6e77221da0 Fix CI/CD preps 2025-03-17 14:25:29 +01:00
Matej Bačo 4de935a322 Fix CI/CD flaky test 2025-03-17 14:16:31 +01:00
Matej Bačo 86b66d70bf Debug CI/CD 2025-03-17 14:07:27 +01:00
Matej Bačo 828b9349c3 Improve build worker realtime, new tests 2025-03-17 13:21:36 +01:00
shimon 9cb860d446 _app_region 2025-03-17 13:52:17 +02:00
Matej Bačo 313a6b0f7e Fix bug in usage test 2025-03-17 12:29:44 +01:00
shimon 6eff011100 Merge branch '1.6.x' of github.com:appwrite/appwrite into updates-projects-regions
# Conflicts:
#	app/views/install/compose.phtml
2025-03-17 13:29:22 +02:00
Matej Bačo 04140c2acc Fix crashing init 2025-03-17 12:08:01 +01:00
Matej Bačo 0f961f0d04 Fix composer conflict 2025-03-17 11:55:14 +01:00
Matej Bačo 25f7741d3c Linter fix 2025-03-17 11:53:23 +01:00
Matej Bačo 2ff339dad4 Re-implement init changes 2025-03-17 11:53:09 +01:00
Matej Bačo 91dd4c9c6f Merge branch '1.7.x' into feat-sites 2025-03-17 11:47:22 +01:00
Matej Bačo 8413909b12 Merge branch '1.6.x' into 1.7.x 2025-03-17 11:42:30 +01:00
Matej Bačo a4d4b6ffb5 Fix tests 2025-03-17 11:41:02 +01:00
Matej Bačo cbdd344490 Remove framework env var 2025-03-17 11:21:52 +01:00
Damodar LohaniandGitHub 8fd877810d Merge branch '1.6.x' into feat-domains-count 2025-03-17 12:49:59 +05:45
Jake Barnby 04711d8c02 Add doc 2025-03-17 19:21:31 +13:00
Eldad A. FuxandGitHub 5a5d43f3d0 Merge pull request #9515 from appwrite/feat-env-to-system
Feat env vars to system lib
2025-03-16 17:09:47 +01:00
Eldad A. FuxandGitHub 3e462ded0a Merge pull request #9408 from appwrite/feat-dynamic-regions
Feat dynamic regions
2025-03-16 17:05:04 +01:00
Eldad Fux de96b2511a Merge remote-tracking branch 'origin/1.6.x' into feat-dynamic-regions 2025-03-16 16:31:09 +01:00
Eldad Fux 90899b92e3 Change envs to system lib 2025-03-16 10:36:32 +01:00
Damodar Lohani 4eece99768 Feat: domains count 2025-03-16 02:35:10 +00:00
Eldad A. FuxandGitHub 971a4b8f30 Merge pull request #9511 from appwrite/feat-eldad-cleanups
Cleanups
2025-03-15 19:15:32 +01:00
Eldad Fux 418185b914 fixed format 2025-03-15 14:43:51 +01:00
Eldad Fux 167011ce87 Fixed timelimit 2025-03-15 14:38:01 +01:00
Chirag Aggarwal e80bc2bb39 chore: shifted migration to 1.7.0 2025-03-15 13:36:08 +00:00
Eldad Fux 3d69a35d5a Fixed tests 2025-03-15 14:32:18 +01:00
Chirag AggarwalandGitHub 9a4220f2dd Merge branch '1.7.x' into pla-2610 2025-03-15 18:53:59 +05:30
Eldad Fux aac90ea8b8 Fixed format 2025-03-15 14:17:47 +01:00
Eldad Fux 56aa503146 Fixed paths 2025-03-15 13:57:12 +01:00
Eldad Fux 875a60fe07 fixed paths 2025-03-15 13:53:00 +01:00
Eldad Fux 3427755695 Merge remote-tracking branch 'origin/1.6.x' into feat-eldad-cleanups 2025-03-15 13:45:31 +01:00
Jake BarnbyandGitHub 68238193d2 Merge pull request #9512 from appwrite/feat-improve-ordering
Improve delete ordering
2025-03-16 01:34:02 +13:00
Eldad Fux 07926534bf Fixed namespace 2025-03-15 13:24:56 +01:00
Eldad Fux a2a0a1405f plurals 2025-03-15 13:23:02 +01:00
Eldad Fux 195edd19ac wip 2025-03-15 13:18:34 +01:00
Eldad Fux 6cf333141c Merge remote-tracking branch 'origin/1.6.x' into feat-eldad-cleanups 2025-03-15 13:18:30 +01:00
Jake Barnby 12dbb1d50d Reapply "Improve deletes queries"
This reverts commit 9dff192508.
2025-03-16 01:02:44 +13:00
Jake Barnby 9dff192508 Revert "Improve deletes queries"
This reverts commit 650627bfb4.
2025-03-16 01:02:41 +13:00
Jake Barnby 650627bfb4 Improve deletes queries 2025-03-16 01:01:13 +13:00
Eldad Fux 4016895b8f Fixed DB test 2025-03-15 12:58:41 +01:00
Eldad Fux 3b7aea22c2 Fixed test 2025-03-15 12:42:34 +01:00
Eldad Fux 50fe0bf98d Code review fix 2025-03-15 12:39:15 +01:00
Eldad Fux 4f0a7de868 Fixes 2025-03-15 12:34:49 +01:00
Eldad Fux 1933e48d9c Cleanups 2025-03-15 12:00:36 +01:00
Steven NguyenandGitHub 90228a5ffb Merge pull request #9294 from appwrite/feat-1.6.1-release-prep
Prepare 1.6.1 release
2025-03-14 16:38:55 -07:00
Steven NguyenandGitHub 063c2be38f Merge pull request #9495 from appwrite/chore-bump-console-5.2.53
Bump console to version 5.2.53
2025-03-14 16:35:22 -07:00
Steven NguyenandGitHub ff9845c9b9 Merge pull request #9496 from appwrite/main
Sync main into 1.6.x
2025-03-14 16:35:01 -07:00
Steven NguyenandGitHub bd5bfc04ef Merge pull request #9466 from appwrite/fix-certificates-in-deletes
Fix certificates in deletes worker
2025-03-14 16:34:21 -07:00
Matej Bačo 7a131d3508 Post-merge fixes 2025-03-14 13:56:37 +01:00
Matej Bačo d77dbebe8b Merge branch '1.7.x' into feat-sites 2025-03-14 13:53:34 +01:00
Matej Bačo 8eadaec676 Merge branch '1.6.x' into 1.7.x 2025-03-14 13:50:53 +01:00
Matej BačoandGitHub c55030387f Merge pull request #9508 from appwrite/feat-rules-improvements
Feat: Add rule attributes
2025-03-14 13:35:05 +01:00
Matej Bačo 5f2512dc4f code quality improvement 2025-03-14 12:07:38 +01:00
Matej Bačo f6fc425c98 Add rule attributes 2025-03-14 09:37:44 +01:00
Jake BarnbyandGitHub 810d650aba Merge pull request #9507 from appwrite/feat-improve-delete-queries
Feat improve delete queries
2025-03-14 18:37:56 +13:00
Jake Barnby 817a3808e5 Add 5 min timeout for workers and tasks DBs 2025-03-14 16:40:57 +13:00
Jake Barnby d96910138f Update lock 2025-03-14 15:40:05 +13:00
Jake Barnby b8673ac07f Merge remote-tracking branch 'origin/1.6.x' into feat-improve-delete-queries
# Conflicts:
#	composer.lock
2025-03-14 15:34:18 +13:00
Jake Barnby 246c8ce939 Add order on inequality queries 2025-03-14 15:29:52 +13:00
Jake Barnby 49d89a4206 Force clear timeout to ensure it's not set 2025-03-14 15:29:23 +13:00
Matej Bačo ba45c191c5 Updat console 2025-03-13 16:20:36 +01:00
Matej Bačo 74f9464c18 Fix site specs for vcs deployment 2025-03-13 15:39:41 +01:00
Matej Bačo c5dfabdb7c Fix commit deployments, allow for sites 2025-03-13 15:38:29 +01:00
Matej BačoandGitHub bfdd2b65dc Merge pull request #9504 from appwrite/fix-github-comment
Fix github comment
2025-03-13 15:17:13 +01:00
Christy JacobandGitHub 2c803b262c Merge pull request #9505 from appwrite/PLA-2640
update queue to 0.9.*
2025-03-13 18:51:41 +05:30
Matej Bačo 9bc793b216 Fix realtime tests 2025-03-13 14:08:14 +01:00
Fabian Gruber fcf15689e8 update queue to 0.9.* 2025-03-13 14:02:32 +01:00
Christy JacobandGitHub aef38aa114 Merge pull request #9414 from appwrite/bump-sdk
chore: bump sdk
2025-03-13 17:29:56 +05:30
Chirag Aggarwal 33ab1513d0 chore: update specs 2025-03-13 10:46:55 +00:00
Chirag Aggarwal d422f693f7 feat: add query by role to memberships 2025-03-13 09:48:39 +00:00
Chirag AggarwalandGitHub d81f2f8b5c Merge branch '1.6.x' into bump-sdk 2025-03-13 11:01:14 +05:30
Chirag Aggarwal e119bf6777 chore: update changelogs 2025-03-13 05:30:09 +00:00
Steven Nguyen 7402145c9d Bump console to version 5.2.53 2025-03-12 15:22:43 -07:00
Chirag Aggarwal 74f4ebf90e chore: update sdk generator 2025-03-12 10:26:01 +00:00
shimon d6e53d8e2e Merge branch '1.6.x' of github.com:appwrite/appwrite into updates-projects-regions 2025-03-11 11:17:18 +02:00
Chirag Aggarwal e3f59c696d bump: python version 2025-03-11 05:43:30 +00:00
Chirag Aggarwal 107a185953 Merge branch '1.6.x' into bump-sdk 2025-03-11 05:30:47 +00:00
Steven Nguyen f6b5deda6d fix: add missing _APP_EMAIL_CERTIFICATES env var to deletes worker
The deletes worker uses the certificates resource to delete
certificates, but the certificates resource requires the
_APP_EMAIL_CERTIFICATES env var to be set or it will throw an exception
and not process any delete jobs. This commit adds the missing env var
to the deletes worker.

Also add _APP_SYSTEM_SECURITY_EMAIL_ADDRESS as a fallback.
2025-03-07 12:46:14 -08:00
Chirag Aggarwal d9fc6b70ad chore: bump react native 2025-03-07 13:18:20 +00:00
Chirag Aggarwal a0605b14cb chore: regen specs and update vers 2025-03-07 04:14:45 +00:00
Chirag Aggarwal 6c652ba3ae Merge branch '1.6.x' into bump-sdk 2025-03-06 17:04:05 +00:00
shimon 2a5b3317bf update region 2025-03-04 11:36:45 +02:00
shimon 19ad2088a0 update region 2025-03-04 10:08:07 +02:00
Chirag Aggarwal 6ad34a7bf7 chore: sdk versions and corresponding docs 2025-02-27 05:05:31 +00:00
Chirag Aggarwal 57c7ebb53d chore: bump sdk 2025-02-26 17:51:00 +00:00
Eldad Fux ad56782b49 Fixed tests 2025-02-26 10:19:51 +01:00
Eldad Fux ce5a04a37d Merge remote-tracking branch 'origin/1.6.x' into feat-dynamic-regions 2025-02-26 07:52:40 +01:00
Eldad Fux e8fb2f8ae1 Changed config format 2025-02-25 20:25:54 +01:00
Eldad Fux 697c30f559 Init 2025-02-25 09:31:24 +01:00
Steven NguyenandGitHub 34d587d7c5 Merge pull request #9122 from gurjeetsinghvirdee/152-sdk-cli-command-update
Fix outdated CLI commands in documentation
2025-02-21 13:59:50 -08:00
Steven NguyenandGitHub 0547dbc454 fix: use github var instead of secret for DOCKERHUB_USERNAME
DOCKERHUB_USERNAME was moved to be a variable since it doesn't need to
be secret.
2025-02-03 22:34:08 +00:00
Gurjeet Singh VirdeeandGitHub a3324b7453 Merge branch 'main' into 152-sdk-cli-command-update 2025-02-01 03:43:11 +05:30
Steven NguyenandGitHub df017bccb2 chore: bump appwrite version to 1.6.1 2025-01-31 22:00:32 +00:00
Eldad A. FuxandGitHub c4ab6f5aff Merge pull request #9285 from appwrite/LauraDuRy-patch-1
replaced init for cloud link
2025-01-29 12:06:46 +01:00
Laura Du RyandGitHub 891c1c4093 Update README.md 2025-01-29 10:04:15 +01:00
Laura Du RyandGitHub 507c8bd3ec Update README.md 2025-01-29 10:02:40 +01:00
Laura Du RyandGitHub 2de4e71662 Update README.md 2025-01-29 09:58:04 +01:00
Gurjeet Singh VirdeeandGitHub 8508e6009b refactor: cleaned up syntax by removing unnecessary '=' 2025-01-24 19:13:56 +05:30
Gurjeet Singh VirdeeandGitHub a39341ada8 fix: add missing single quote 2025-01-08 14:48:54 +05:30
Gurjeet Singh VirdeeandGitHub c451074278 restored the permissions term 2025-01-06 01:29:06 +05:30
Gurjeet Singh VirdeeandGitHub cce6222184 docs: update CLI commands in documentation 2024-12-20 22:24:39 +05:30
Steven NguyenandGitHub 6e09bcf6c6 Bump appwrite version to 1.6.1-RC1 2024-11-27 18:10:28 +00:00
240 changed files with 171067 additions and 4093 deletions
+7
View File
@@ -0,0 +1,7 @@
reviews:
auto_review:
base_branches:
- main
- 1.6.x
- 1.7.x
- feat-sites # temporary until merged to 1.7.x
+8 -5
View File
@@ -18,12 +18,14 @@ _APP_SYSTEM_RESPONSE_FORMAT=
_APP_OPTIONS_ABUSE=disabled
_APP_OPTIONS_ROUTER_PROTECTION=disabled
_APP_OPTIONS_FORCE_HTTPS=disabled
_APP_OPTIONS_COMPUTE_FORCE_HTTPS=disabled
_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled
_APP_OPENSSL_KEY_V1=your-secret-key
_APP_DOMAIN=traefik
_APP_DOMAIN_FUNCTIONS=functions.localhost
_APP_DOMAIN_SITES=sites.localhost
_APP_DOMAIN_TARGET=test.appwrite.io
_APP_DOMAIN_TARGET_CNAME=test.appwrite.io
_APP_DOMAIN_TARGET_A=127.0.0.1
_APP_DOMAIN_TARGET_AAAA=::1
_APP_RULES_FORMAT=md5
_APP_REDIS_HOST=redis
_APP_REDIS_PORT=6379
@@ -71,7 +73,8 @@ _APP_SMS_PROJECTS_DENY_LIST=
_APP_STORAGE_LIMIT=30000000
_APP_STORAGE_PREVIEW_LIMIT=20000000
_APP_COMPUTE_SIZE_LIMIT=30000000
_APP_COMPUTE_TIMEOUT=900
_APP_FUNCTIONS_TIMEOUT=900
_APP_SITES_TIMEOUT=30
_APP_COMPUTE_BUILD_TIMEOUT=900
_APP_COMPUTE_CPUS=8
_APP_COMPUTE_MEMORY=8192
@@ -82,15 +85,15 @@ _APP_EXECUTOR_SECRET=your-secret-key
_APP_EXECUTOR_HOST=http://exc1/v1
_APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1
_APP_SITES_RUNTIMES=static-1,node-22,flutter-3.29
_APP_SITES_FRAMEWORKS=sveltekit,nextjs,nuxt,astro,remix,flutter,other,react,vue,analog,angular,vite
_APP_MAINTENANCE_INTERVAL=86400
_APP_MAINTENANCE_DELAY=
_APP_MAINTENANCE_RETENTION_CACHE=2592000
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
_APP_MAINTENANCE_RETENTION_ABUSE=86400
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800
_APP_USAGE_AGGREGATION_INTERVAL=30
_APP_STATS_RESOURCES_INTERVAL=3600
_APP_STATS_RESOURCES_INTERVAL=30
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
_APP_USAGE_STATS=enabled
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Cleanup
run: |
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 2
+2 -2
View File
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 2
submodules: recursive
@@ -26,7 +26,7 @@ jobs:
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@@ -28,7 +28,7 @@ jobs:
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
steps:
- name: Check out the repo
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Run CodeQL
run: |
+8
View File
@@ -122,6 +122,14 @@ jobs:
docker load --input /tmp/${{ env.IMAGE }}.tar
docker compose up -d
sleep 10
- name: Wait for Open Runtimes
timeout-minutes: 3
run: |
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
echo "Waiting for Executor to come online"
sleep 1
done
- name: Run General Tests
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/General --debug
+1 -8
View File
@@ -7,6 +7,7 @@ tasks:
docker pull composer
command: |
docker run --rm --interactive --tty \
--user "$(id -u):$(id -g)" \
--volume $PWD:/app \
composer install \
--ignore-platform-reqs \
@@ -23,11 +24,3 @@ vscode:
extensions:
- ms-azuretools.vscode-docker
- zobo.php-intellisense
github:
# https://www.gitpod.io/docs/prebuilds#github-specific-configuration
prebuilds:
# enable for pull requests coming from forks (defaults to false)
pullRequestsFromForks: true
# add a check to pull requests (defaults to true)
addCheck: false
+2
View File
@@ -44,12 +44,14 @@ COPY ./dev /usr/src/code/dev
# Set Volumes
RUN mkdir -p /storage/uploads && \
mkdir -p /storage/imports && \
mkdir -p /storage/cache && \
mkdir -p /storage/config && \
mkdir -p /storage/certificates && \
mkdir -p /storage/functions && \
mkdir -p /storage/debug && \
chown -Rf www-data.www-data /storage/uploads && chmod -Rf 0755 /storage/uploads && \
chown -Rf www-data.www-data /storage/imports && chmod -Rf 0755 /storage/imports && \
chown -Rf www-data.www-data /storage/cache && chmod -Rf 0755 /storage/cache && \
chown -Rf www-data.www-data /storage/config && chmod -Rf 0755 /storage/config && \
chown -Rf www-data.www-data /storage/certificates && chmod -Rf 0755 /storage/certificates && \
+3 -5
View File
@@ -1,4 +1,4 @@
> Appwrite Init has concluded! You can check out all the latest announcements [on our Init website](https://appwrite.io/init) :rocket:
> [Get started with Appwrite](https://apwr.dev/appcloud)
<br />
<p align="center">
@@ -24,11 +24,9 @@
English | [简体中文](README-CN.md)
[**Announcing Appwrite Cloud Public Beta! Sign up today!**](https://cloud.appwrite.io)
Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker<nobr> microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.
Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, and [more services](https://appwrite.io/docs).
Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and [more services](https://appwrite.io/docs).
<p align="center">
<br />
@@ -52,7 +50,7 @@ Table of Contents:
- [Upgrade from an Older Version](#upgrade-from-an-older-version)
- [One-Click Setups](#one-click-setups)
- [Getting Started](#getting-started)
- [Services](#services)
- [Products](#products)
- [SDKs](#sdks)
- [Client](#client)
- [Server](#server)
+6 -4
View File
@@ -9,6 +9,7 @@ use Appwrite\Event\StatsResources;
use Appwrite\Event\StatsUsage;
use Appwrite\Platform\Appwrite;
use Appwrite\Runtimes\Runtimes;
use Executor\Executor;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\CLI;
@@ -25,7 +26,7 @@ use Utopia\Queue\Publisher;
use Utopia\Registry\Registry;
use Utopia\System\System;
// overwriting runtimes to be architectur agnostic for CLI
// overwriting runtimes to be architecture agnostic for CLI
Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
// require controllers after overwriting runtimes
@@ -43,8 +44,7 @@ CLI::setResource('cache', function ($pools) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
->getResource();
}
return new Cache(new Sharding($adapters));
@@ -187,7 +187,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
$database
->setSharedTables(true)
->setNamespace('logsV1')
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS)
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
// set tenant
@@ -256,6 +256,8 @@ CLI::setResource('logError', function (Registry $register) {
};
}, ['register']);
CLI::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
$platform = new Appwrite();
$platform->init(Service::TYPE_TASK);
+10 -3
View File
@@ -1038,7 +1038,7 @@ return [
'$id' => ID::custom('providerUid'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'size' => 2048, // Decrease to 128 as in index length?
'signed' => true,
'required' => false,
'default' => null,
@@ -1107,14 +1107,14 @@ return [
'$id' => ID::custom('_key_userInternalId_provider_providerUid'),
'type' => Database::INDEX_UNIQUE,
'attributes' => ['userInternalId', 'provider', 'providerUid'],
'lengths' => [11, 128, 128],
'lengths' => [11, 128, 128], // providerUid is length 2000!
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_provider_providerUid'),
'type' => Database::INDEX_UNIQUE,
'attributes' => ['provider', 'providerUid'],
'lengths' => [128, 128],
'lengths' => [128, 128], // providerUid is length 2000!
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
],
[
@@ -1417,6 +1417,13 @@ return [
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_roles'),
'type' => Database::INDEX_KEY,
'attributes' => ['roles'],
'lengths' => [128],
'orders' => [],
],
],
],
+36
View File
@@ -1155,6 +1155,28 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('owner'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16,
'signed' => true,
'required' => false,
'default' => '', // "Appwrite" or empty string
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('region'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
@@ -1241,6 +1263,20 @@ return [
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_owner'),
'type' => Database::INDEX_KEY,
'attributes' => ['owner'],
'lengths' => [16],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_region'),
'type' => Database::INDEX_KEY,
'attributes' => ['region'],
'lengths' => [16],
'orders' => [Database::ORDER_ASC],
],
],
],
+224 -12
View File
@@ -579,6 +579,61 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('deploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('latestDeploymentId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentInternalId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('latestDeploymentStatus'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16,
'signed' => true,
'required' => false,
'default' => '',
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('vars'),
'type' => Database::VAR_STRING,
@@ -916,16 +971,16 @@ return [
'default' => false,
'array' => false,
],
// [
// '$id' => ID::custom('logging'),
// 'type' => Database::VAR_BOOLEAN,
// 'signed' => true,
// 'size' => 0,
// 'format' => '',
// 'filters' => [],
// 'required' => true,
// 'array' => false,
// ],
[
'$id' => ID::custom('logging'),
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'array' => false,
],
[
'$id' => ID::custom('framework'),
'type' => Database::VAR_STRING,
@@ -1003,6 +1058,83 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('deploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('deploymentScreenshotLight'), // File ID from 'screenshots' Console bucket
'type' => Database::VAR_STRING,
'format' => '',
'size' => 32,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('deploymentScreenshotDark'), // File ID from 'screenshots' Console bucket
'type' => Database::VAR_STRING,
'format' => '',
'size' => 32,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentInternalId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('latestDeploymentStatus'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16,
'signed' => true,
'required' => false,
'default' => '',
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('vars'),
'type' => Database::VAR_STRING,
@@ -1070,7 +1202,7 @@ return [
'filters' => [],
],
[
'$id' => ID::custom('adapter'), // ssr or static
'$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks
'type' => Database::VAR_STRING,
'format' => '',
'size' => 128,
@@ -1550,6 +1682,17 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('totalSize'),
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('status'),
'type' => Database::VAR_STRING,
@@ -1582,6 +1725,28 @@ return [
'default' => '',
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks
'type' => Database::VAR_STRING,
'format' => '',
'size' => 128,
'signed' => true,
'required' => false,
'default' => '',
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('fallbackFile'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
]
],
'indexes' => [
@@ -1620,6 +1785,13 @@ return [
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_totalSize'),
'type' => Database::INDEX_KEY,
'attributes' => ['totalSize'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_buildDuration'),
'type' => Database::INDEX_KEY,
@@ -2103,6 +2275,17 @@ return [
'array' => false,
'filters' => ['json', 'encrypt'],
],
[
'$id' => ID::custom('options'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 65536,
'signed' => true,
'required' => false,
'default' => [],
'array' => false,
'filters' => ['json'],
],
[
'$id' => ID::custom('resources'),
'type' => Database::VAR_STRING,
@@ -2157,7 +2340,29 @@ return [
'default' => null,
'array' => false,
'filters' => [],
]
],
[
'$id' => ID::custom('resourceId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('resourceType'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
@@ -2181,6 +2386,13 @@ return [
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => '_key_resource_id',
'type' => Database::INDEX_KEY,
'attributes' => ['resourceId'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_DESC],
],
[
'$id' => ID::custom('_fulltext_search'),
'type' => Database::INDEX_FULLTEXT,
+1
View File
@@ -27,6 +27,7 @@ $console = [
'hostname' => 'localhost',
], // Current host is added on app init
],
'region' => 'fra',
'legalName' => '',
'legalCountry' => '',
'legalState' => '',
+16 -6
View File
@@ -546,6 +546,11 @@ return [
'description' => 'Function runtime could not be detected.',
'code' => 400,
],
Exception::FUNCTION_EXECUTE_PERMISSION_MISSING => [
'name' => Exception::FUNCTION_EXECUTE_PERMISSION_MISSING,
'description' => 'To execute function using domain, execute permissions must include "any" or "guests".',
'code' => 401,
],
/** Sites */
Exception::SITE_NOT_FOUND => [
@@ -553,11 +558,6 @@ return [
'description' => 'Site with the requested ID could not be found.',
'code' => 404,
],
Exception::SITE_FRAMEWORK_UNSUPPORTED => [
'name' => Exception::SITE_FRAMEWORK_UNSUPPORTED,
'description' => 'The requested framework is either inactive or unsupported. Please check the value of the _APP_SITES_FRAMEWORKS environment variable.',
'code' => 404,
],
Exception::SITE_TEMPLATE_NOT_FOUND => [
'name' => Exception::SITE_TEMPLATE_NOT_FOUND,
'description' => 'Site Template with the requested ID could not be found.',
@@ -585,6 +585,16 @@ return [
'description' => 'Build with the requested ID is already completed and cannot be canceled.',
'code' => 400,
],
Exception::BUILD_CANCELED => [
'name' => Exception::BUILD_CANCELED,
'description' => 'Build with the requested ID has been canceled.',
'code' => 400,
],
Exception::BUILD_FAILED => [
'name' => Exception::BUILD_FAILED,
'description' => 'Build with the requested ID failed. Please check the logs for more information.',
'code' => 400,
],
/** Deployments */
Exception::DEPLOYMENT_NOT_FOUND => [
@@ -837,7 +847,7 @@ return [
Exception::RULE_VERIFICATION_FAILED => [
'name' => Exception::RULE_VERIFICATION_FAILED,
'description' => 'Domain verification failed. Please check if your DNS records are correct and try again.',
'code' => 401,
'code' => 400,
'publish' => true
],
Exception::PROJECT_SMTP_CONFIG_INVALID => [
+55 -26
View File
@@ -19,9 +19,10 @@ return [
'analog' => [
'key' => 'analog',
'name' => 'Analog',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/analog/bundle.sh',
'bundleCommand' => 'bash /usr/local/server/helpers/analog/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/analog/env.sh',
'adapters' => [
'ssr' => [
@@ -29,14 +30,14 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist/analog',
'startCommand' => 'sh helpers/analog/server.sh',
'startCommand' => 'bash helpers/analog/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist/analog/public',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
'fallbackFile' => 'index.html'
]
]
@@ -44,9 +45,10 @@ return [
'angular' => [
'key' => 'angular',
'name' => 'Angular',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/angular/bundle.sh',
'bundleCommand' => 'bash /usr/local/server/helpers/angular/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/angular/env.sh',
'adapters' => [
'ssr' => [
@@ -54,14 +56,14 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist/angular',
'startCommand' => 'sh helpers/angular/server.sh',
'startCommand' => 'bash helpers/angular/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist/angular/browser',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
'fallbackFile' => 'index.csr.html'
]
]
@@ -69,9 +71,10 @@ return [
'nextjs' => [
'key' => 'nextjs',
'name' => 'Next.js',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/next-js/bundle.sh',
'bundleCommand' => 'bash /usr/local/server/helpers/next-js/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/next-js/env.sh',
'adapters' => [
'ssr' => [
@@ -79,20 +82,21 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './.next',
'startCommand' => 'sh helpers/next-js/server.sh',
'startCommand' => 'bash helpers/next-js/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './out',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
]
]
],
'react' => [
'key' => 'react',
'name' => 'React',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
@@ -101,7 +105,7 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
'fallbackFile' => 'index.html'
]
]
@@ -109,9 +113,10 @@ return [
'nuxt' => [
'key' => 'nuxt',
'name' => 'Nuxt',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/nuxt/bundle.sh',
'bundleCommand' => 'bash /usr/local/server/helpers/nuxt/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/nuxt/env.sh',
'adapters' => [
'ssr' => [
@@ -119,20 +124,21 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './.output',
'startCommand' => 'sh helpers/nuxt/server.sh',
'startCommand' => 'bash helpers/nuxt/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run generate',
'installCommand' => 'npm install',
'outputDirectory' => './output/public',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
]
]
],
'vue' => [
'key' => 'vue',
'name' => 'Vue.js',
'screenshotSleep' => 5000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
@@ -141,7 +147,7 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
'fallbackFile' => 'index.html'
]
]
@@ -149,9 +155,10 @@ return [
'sveltekit' => [
'key' => 'sveltekit',
'name' => 'SvelteKit',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/sveltekit/bundle.sh',
'bundleCommand' => 'bash /usr/local/server/helpers/sveltekit/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/sveltekit/env.sh',
'adapters' => [
'ssr' => [
@@ -159,23 +166,24 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './build',
'startCommand' => 'sh helpers/sveltekit/server.sh',
'startCommand' => 'bash helpers/sveltekit/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './build',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
]
]
],
'astro' => [
'key' => 'astro',
'name' => 'Astro',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/astro/bundle.sh',
'bundleCommand' => 'bash /usr/local/server/helpers/astro/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/astro/env.sh',
'adapters' => [
'ssr' => [
@@ -183,23 +191,24 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist',
'startCommand' => 'sh helpers/astro/server.sh',
'startCommand' => 'bash helpers/astro/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
]
]
],
'remix' => [
'key' => 'remix',
'name' => 'Remix',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/remix/bundle.sh',
'bundleCommand' => 'bash /usr/local/server/helpers/remix/bundle.sh',
'envCommand' => 'source /usr/local/server/helpers/remix/env.sh',
'adapters' => [
'ssr' => [
@@ -207,20 +216,38 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './build',
'startCommand' => 'sh helpers/remix/server.sh',
'startCommand' => 'bash helpers/remix/server.sh',
],
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './build/client',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
]
]
],
'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' => [
'key' => 'flutter',
'name' => 'Flutter',
'screenshotSleep' => 5000,
'buildRuntime' => 'flutter-3.29',
'runtimes' => getVersions($templateRuntimes['FLUTTER']['versions'], 'flutter'),
'adapters' => [
@@ -229,13 +256,14 @@ return [
'buildCommand' => 'flutter build web',
'installCommand' => '',
'outputDirectory' => './build/web',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
],
],
],
'vite' => [
'key' => 'vite',
'name' => 'Vite',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
@@ -244,13 +272,14 @@ return [
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
],
]
],
'other' => [
'key' => 'other',
'name' => 'Other',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
@@ -259,7 +288,7 @@ return [
'buildCommand' => '',
'installCommand' => '',
'outputDirectory' => './',
'startCommand' => 'sh helpers/server.sh',
'startCommand' => 'bash helpers/server.sh',
],
]
],
+42 -7
View File
@@ -1,11 +1,46 @@
<?php
/**
* Continent codes with names and approximate central coordinates
*
* Coordinates represent approximate geographical centers of each continent
* Note: These are simplified centroids and may not represent the exact geographical center
*/
return [
'AF',
'AN',
'AS',
'EU',
'NA',
'OC',
'SA',
'AF' => [
'name' => 'Africa',
'latitude' => 8.7832,
'longitude' => 34.5085
],
'AN' => [
'name' => 'Antarctica',
'latitude' => -82.8628,
'longitude' => 135.0000
],
'AS' => [
'name' => 'Asia',
'latitude' => 34.0479,
'longitude' => 100.6197
],
'EU' => [
'name' => 'Europe',
'latitude' => 54.5260,
'longitude' => 15.2551
],
'NA' => [
'name' => 'North America',
'latitude' => 54.5260,
'longitude' => -105.2551
],
'OC' => [
'name' => 'Oceania',
'latitude' => -22.7359,
'longitude' => 140.0188
],
'SA' => [
'name' => 'South America',
'latitude' => -8.7832,
'longitude' => -55.4915
],
];
+199 -198
View File
@@ -1,209 +1,210 @@
<?php
/**
* ISO 3166 standard country codes
* ISO 3166 standard country codes with country names and coordinates
* https://www.iso.org/iso-3166-country-codes.html
*
* Source:
* https://www.iso.org/obp/ui/#search/code/
* Coordinates source: Natural Earth Data (approximate country centroids)
*/
return [
'AF',
'AO',
'AL',
'AD',
'AE',
'AR',
'AM',
'AG',
'AU',
'AT',
'AZ',
'BI',
'BE',
'BJ',
'BF',
'BD',
'BG',
'BH',
'BS',
'BA',
'BY',
'BZ',
'BO',
'BR',
'BB',
'BN',
'BT',
'BW',
'CF',
'CA',
'CH',
'CL',
'CN',
'CI',
'CM',
'CD',
'CG',
'CO',
'KM',
'CV',
'CR',
'CU',
'CY',
'CZ',
'DE',
'DJ',
'DM',
'DK',
'DO',
'DZ',
'EC',
'EG',
'ER',
'ES',
'EE',
'ET',
'FI',
'FJ',
'FR',
'FM',
'GA',
'GB',
'GE',
'GH',
'GN',
'GM',
'GW',
'GQ',
'GR',
'GD',
'GT',
'GY',
'HK',
'HN',
'HR',
'HT',
'HU',
'ID',
'IN',
'IE',
'IR',
'IQ',
'IS',
'IL',
'IT',
'JM',
'JO',
'JP',
'KZ',
'KE',
'KG',
'KH',
'KI',
'KN',
'KR',
'KW',
'LA',
'LB',
'LR',
'LY',
'LC',
'LI',
'LK',
'LS',
'LT',
'LU',
'LV',
'MA',
'MC',
'MD',
'MG',
'MV',
'MX',
'MH',
'MK',
'ML',
'MT',
'MM',
'ME',
'MN',
'MZ',
'MR',
'MU',
'MW',
'MY',
'NA',
'NE',
'NG',
'NI',
'NL',
'NO',
'NP',
'NR',
'NZ',
'OM',
'PK',
'PS',
'PA',
'PE',
'PH',
'PW',
'PG',
'PL',
'KP',
'PT',
'PY',
'QA',
'RO',
'RU',
'RW',
'SA',
'SD',
'SN',
'SG',
'SB',
'SL',
'SV',
'SM',
'SO',
'RS',
'SS',
'ST',
'SR',
'SK',
'SI',
'SE',
'SZ',
'SC',
'SY',
'TD',
'TG',
'TH',
'TJ',
'TM',
'TL',
'TO',
'TT',
'TN',
'TR',
'TV',
'TZ',
'TW',
'UG',
'UA',
'UY',
'US',
'UZ',
'VA',
'VC',
'VE',
'VN',
'VU',
'WS',
'YE',
'ZA',
'ZM',
'ZW',
'AF' => ['name' => 'Afghanistan', 'latitude' => 33.0, 'longitude' => 66.0],
'AO' => ['name' => 'Angola', 'latitude' => -12.5, 'longitude' => 18.5],
'AL' => ['name' => 'Albania', 'latitude' => 41.0, 'longitude' => 20.0],
'AD' => ['name' => 'Andorra', 'latitude' => 42.5, 'longitude' => 1.6],
'AE' => ['name' => 'United Arab Emirates', 'latitude' => 24.0, 'longitude' => 54.0],
'AR' => ['name' => 'Argentina', 'latitude' => -34.0, 'longitude' => -64.0],
'AM' => ['name' => 'Armenia', 'latitude' => 40.0, 'longitude' => 45.0],
'AG' => ['name' => 'Antigua and Barbuda', 'latitude' => 17.05, 'longitude' => -61.8],
'AU' => ['name' => 'Australia', 'latitude' => -25.0, 'longitude' => 135.0],
'AT' => ['name' => 'Austria', 'latitude' => 47.3, 'longitude' => 13.3],
'AZ' => ['name' => 'Azerbaijan', 'latitude' => 40.5, 'longitude' => 47.5],
'BI' => ['name' => 'Burundi', 'latitude' => -3.5, 'longitude' => 30.0],
'BE' => ['name' => 'Belgium', 'latitude' => 50.8, 'longitude' => 4.0],
'BJ' => ['name' => 'Benin', 'latitude' => 9.5, 'longitude' => 2.25],
'BF' => ['name' => 'Burkina Faso', 'latitude' => 13.0, 'longitude' => -2.0],
'BD' => ['name' => 'Bangladesh', 'latitude' => 24.0, 'longitude' => 90.0],
'BG' => ['name' => 'Bulgaria', 'latitude' => 43.0, 'longitude' => 25.0],
'BH' => ['name' => 'Bahrain', 'latitude' => 26.0, 'longitude' => 50.5],
'BS' => ['name' => 'Bahamas', 'latitude' => 24.25, 'longitude' => -76.0],
'BA' => ['name' => 'Bosnia and Herzegovina', 'latitude' => 44.0, 'longitude' => 18.0],
'BY' => ['name' => 'Belarus', 'latitude' => 53.0, 'longitude' => 28.0],
'BZ' => ['name' => 'Belize', 'latitude' => 17.25, 'longitude' => -88.75],
'BO' => ['name' => 'Bolivia', 'latitude' => -17.0, 'longitude' => -65.0],
'BR' => ['name' => 'Brazil', 'latitude' => -10.0, 'longitude' => -55.0],
'BB' => ['name' => 'Barbados', 'latitude' => 13.17, 'longitude' => -59.53],
'BN' => ['name' => 'Brunei', 'latitude' => 4.5, 'longitude' => 114.67],
'BT' => ['name' => 'Bhutan', 'latitude' => 27.5, 'longitude' => 90.5],
'BW' => ['name' => 'Botswana', 'latitude' => -22.0, 'longitude' => 24.0],
'CF' => ['name' => 'Central African Republic', 'latitude' => 7.0, 'longitude' => 21.0],
'CA' => ['name' => 'Canada', 'latitude' => 60.0, 'longitude' => -95.0],
'CH' => ['name' => 'Switzerland', 'latitude' => 47.0, 'longitude' => 8.0],
'CL' => ['name' => 'Chile', 'latitude' => -30.0, 'longitude' => -71.0],
'CN' => ['name' => 'China', 'latitude' => 35.0, 'longitude' => 105.0],
'CI' => ['name' => 'Côte d\'Ivoire', 'latitude' => 8.0, 'longitude' => -5.0],
'CM' => ['name' => 'Cameroon', 'latitude' => 6.0, 'longitude' => 12.0],
'CD' => ['name' => 'Democratic Republic of the Congo', 'latitude' => -2.5, 'longitude' => 23.5],
'CG' => ['name' => 'Republic of the Congo', 'latitude' => -1.0, 'longitude' => 15.0],
'CO' => ['name' => 'Colombia', 'latitude' => 4.0, 'longitude' => -72.0],
'KM' => ['name' => 'Comoros', 'latitude' => -12.17, 'longitude' => 44.25],
'CV' => ['name' => 'Cape Verde', 'latitude' => 16.0, 'longitude' => -24.0],
'CR' => ['name' => 'Costa Rica', 'latitude' => 10.0, 'longitude' => -84.0],
'CU' => ['name' => 'Cuba', 'latitude' => 21.5, 'longitude' => -80.0],
'CY' => ['name' => 'Cyprus', 'latitude' => 35.0, 'longitude' => 33.0],
'CZ' => ['name' => 'Czech Republic', 'latitude' => 49.75, 'longitude' => 15.5],
'DE' => ['name' => 'Germany', 'latitude' => 51.0, 'longitude' => 9.0],
'DJ' => ['name' => 'Djibouti', 'latitude' => 11.5, 'longitude' => 43.0],
'DM' => ['name' => 'Dominica', 'latitude' => 15.42, 'longitude' => -61.33],
'DK' => ['name' => 'Denmark', 'latitude' => 56.0, 'longitude' => 10.0],
'DO' => ['name' => 'Dominican Republic', 'latitude' => 19.0, 'longitude' => -70.67],
'DZ' => ['name' => 'Algeria', 'latitude' => 28.0, 'longitude' => 3.0],
'EC' => ['name' => 'Ecuador', 'latitude' => -2.0, 'longitude' => -77.5],
'EG' => ['name' => 'Egypt', 'latitude' => 27.0, 'longitude' => 30.0],
'ER' => ['name' => 'Eritrea', 'latitude' => 15.0, 'longitude' => 39.0],
'ES' => ['name' => 'Spain', 'latitude' => 40.0, 'longitude' => -4.0],
'EE' => ['name' => 'Estonia', 'latitude' => 59.0, 'longitude' => 26.0],
'ET' => ['name' => 'Ethiopia', 'latitude' => 8.0, 'longitude' => 38.0],
'FI' => ['name' => 'Finland', 'latitude' => 64.0, 'longitude' => 26.0],
'FJ' => ['name' => 'Fiji', 'latitude' => -18.0, 'longitude' => 175.0],
'FR' => ['name' => 'France', 'latitude' => 46.0, 'longitude' => 2.0],
'FM' => ['name' => 'Micronesia', 'latitude' => 6.92, 'longitude' => 158.25],
'GA' => ['name' => 'Gabon', 'latitude' => -1.0, 'longitude' => 11.75],
'GB' => ['name' => 'United Kingdom', 'latitude' => 54.0, 'longitude' => -2.0],
'GE' => ['name' => 'Georgia', 'latitude' => 42.0, 'longitude' => 43.5],
'GH' => ['name' => 'Ghana', 'latitude' => 8.0, 'longitude' => -2.0],
'GN' => ['name' => 'Guinea', 'latitude' => 11.0, 'longitude' => -10.0],
'GM' => ['name' => 'Gambia', 'latitude' => 13.47, 'longitude' => -16.57],
'GW' => ['name' => 'Guinea-Bissau', 'latitude' => 12.0, 'longitude' => -15.0],
'GQ' => ['name' => 'Equatorial Guinea', 'latitude' => 2.0, 'longitude' => 10.0],
'GR' => ['name' => 'Greece', 'latitude' => 39.0, 'longitude' => 22.0],
'GD' => ['name' => 'Grenada', 'latitude' => 12.12, 'longitude' => -61.67],
'GT' => ['name' => 'Guatemala', 'latitude' => 15.5, 'longitude' => -90.25],
'GY' => ['name' => 'Guyana', 'latitude' => 5.0, 'longitude' => -59.0],
'HK' => ['name' => 'Hong Kong', 'latitude' => 22.25, 'longitude' => 114.17],
'HN' => ['name' => 'Honduras', 'latitude' => 15.0, 'longitude' => -86.5],
'HR' => ['name' => 'Croatia', 'latitude' => 45.17, 'longitude' => 15.5],
'HT' => ['name' => 'Haiti', 'latitude' => 19.0, 'longitude' => -72.42],
'HU' => ['name' => 'Hungary', 'latitude' => 47.0, 'longitude' => 20.0],
'ID' => ['name' => 'Indonesia', 'latitude' => -5.0, 'longitude' => 120.0],
'IN' => ['name' => 'India', 'latitude' => 20.0, 'longitude' => 77.0],
'IE' => ['name' => 'Ireland', 'latitude' => 53.0, 'longitude' => -8.0],
'IR' => ['name' => 'Iran', 'latitude' => 32.0, 'longitude' => 53.0],
'IQ' => ['name' => 'Iraq', 'latitude' => 33.0, 'longitude' => 44.0],
'IS' => ['name' => 'Iceland', 'latitude' => 65.0, 'longitude' => -18.0],
'IL' => ['name' => 'Israel', 'latitude' => 31.5, 'longitude' => 34.75],
'IT' => ['name' => 'Italy', 'latitude' => 42.83, 'longitude' => 12.83],
'JM' => ['name' => 'Jamaica', 'latitude' => 18.25, 'longitude' => -77.5],
'JO' => ['name' => 'Jordan', 'latitude' => 31.0, 'longitude' => 36.0],
'JP' => ['name' => 'Japan', 'latitude' => 36.0, 'longitude' => 138.0],
'KZ' => ['name' => 'Kazakhstan', 'latitude' => 48.0, 'longitude' => 68.0],
'KE' => ['name' => 'Kenya', 'latitude' => 1.0, 'longitude' => 38.0],
'KG' => ['name' => 'Kyrgyzstan', 'latitude' => 41.0, 'longitude' => 75.0],
'KH' => ['name' => 'Cambodia', 'latitude' => 13.0, 'longitude' => 105.0],
'KI' => ['name' => 'Kiribati', 'latitude' => 1.42, 'longitude' => 173.0],
'KN' => ['name' => 'Saint Kitts and Nevis', 'latitude' => 17.33, 'longitude' => -62.75],
'KR' => ['name' => 'South Korea', 'latitude' => 37.0, 'longitude' => 127.5],
'KW' => ['name' => 'Kuwait', 'latitude' => 29.34, 'longitude' => 47.66],
'LA' => ['name' => 'Laos', 'latitude' => 18.0, 'longitude' => 105.0],
'LB' => ['name' => 'Lebanon', 'latitude' => 33.83, 'longitude' => 35.83],
'LR' => ['name' => 'Liberia', 'latitude' => 6.5, 'longitude' => -9.5],
'LY' => ['name' => 'Libya', 'latitude' => 25.0, 'longitude' => 17.0],
'LC' => ['name' => 'Saint Lucia', 'latitude' => 13.88, 'longitude' => -61.13],
'LI' => ['name' => 'Liechtenstein', 'latitude' => 47.17, 'longitude' => 9.53],
'LK' => ['name' => 'Sri Lanka', 'latitude' => 7.0, 'longitude' => 81.0],
'LS' => ['name' => 'Lesotho', 'latitude' => -29.5, 'longitude' => 28.5],
'LT' => ['name' => 'Lithuania', 'latitude' => 56.0, 'longitude' => 24.0],
'LU' => ['name' => 'Luxembourg', 'latitude' => 49.75, 'longitude' => 6.17],
'LV' => ['name' => 'latitudevia', 'latitude' => 57.0, 'longitude' => 25.0],
'MA' => ['name' => 'Morocco', 'latitude' => 32.0, 'longitude' => -5.0],
'MC' => ['name' => 'Monaco', 'latitude' => 43.73, 'longitude' => 7.4],
'MD' => ['name' => 'Moldova', 'latitude' => 47.0, 'longitude' => 29.0],
'MG' => ['name' => 'Madagascar', 'latitude' => -20.0, 'longitude' => 47.0],
'MV' => ['name' => 'Maldives', 'latitude' => 3.25, 'longitude' => 73.0],
'MX' => ['name' => 'Mexico', 'latitude' => 23.0, 'longitude' => -102.0],
'MH' => ['name' => 'Marshall Islands', 'latitude' => 9.0, 'longitude' => 168.0],
'MK' => ['name' => 'North Macedonia', 'latitude' => 41.83, 'longitude' => 22.0],
'ML' => ['name' => 'Mali', 'latitude' => 17.0, 'longitude' => -4.0],
'MT' => ['name' => 'Malta', 'latitude' => 35.83, 'longitude' => 14.58],
'MM' => ['name' => 'Myanmar', 'latitude' => 22.0, 'longitude' => 98.0],
'ME' => ['name' => 'Montenegro', 'latitude' => 42.5, 'longitude' => 19.3],
'MN' => ['name' => 'Mongolia', 'latitude' => 46.0, 'longitude' => 105.0],
'MZ' => ['name' => 'Mozambique', 'latitude' => -18.25, 'longitude' => 35.0],
'MR' => ['name' => 'Mauritania', 'latitude' => 20.0, 'longitude' => -12.0],
'MU' => ['name' => 'Mauritius', 'latitude' => -20.28, 'longitude' => 57.55],
'MW' => ['name' => 'Malawi', 'latitude' => -13.5, 'longitude' => 34.0],
'MY' => ['name' => 'Malaysia', 'latitude' => 2.5, 'longitude' => 112.5],
'NA' => ['name' => 'Namibia', 'latitude' => -22.0, 'longitude' => 17.0],
'NE' => ['name' => 'Niger', 'latitude' => 16.0, 'longitude' => 8.0],
'NG' => ['name' => 'Nigeria', 'latitude' => 10.0, 'longitude' => 8.0],
'NI' => ['name' => 'Nicaragua', 'latitude' => 13.0, 'longitude' => -85.0],
'NL' => ['name' => 'Netherlands', 'latitude' => 52.5, 'longitude' => 5.75],
'NO' => ['name' => 'Norway', 'latitude' => 62.0, 'longitude' => 10.0],
'NP' => ['name' => 'Nepal', 'latitude' => 28.0, 'longitude' => 84.0],
'NR' => ['name' => 'Nauru', 'latitude' => -0.53, 'longitude' => 166.92],
'NZ' => ['name' => 'New Zealand', 'latitude' => -41.0, 'longitude' => 174.0],
'OM' => ['name' => 'Oman', 'latitude' => 21.0, 'longitude' => 57.0],
'PK' => ['name' => 'Pakistan', 'latitude' => 30.0, 'longitude' => 70.0],
'PS' => ['name' => 'Palestine', 'latitude' => 31.9, 'longitude' => 35.2],
'PA' => ['name' => 'Panama', 'latitude' => 9.0, 'longitude' => -80.0],
'PE' => ['name' => 'Peru', 'latitude' => -10.0, 'longitude' => -76.0],
'PH' => ['name' => 'Philippines', 'latitude' => 13.0, 'longitude' => 122.0],
'PW' => ['name' => 'Palau', 'latitude' => 7.5, 'longitude' => 134.5],
'PG' => ['name' => 'Papua New Guinea', 'latitude' => -6.0, 'longitude' => 147.0],
'PL' => ['name' => 'Poland', 'latitude' => 52.0, 'longitude' => 20.0],
'KP' => ['name' => 'North Korea', 'latitude' => 40.0, 'longitude' => 127.0],
'PT' => ['name' => 'Portugal', 'latitude' => 39.5, 'longitude' => -8.0],
'PY' => ['name' => 'Paraguay', 'latitude' => -23.0, 'longitude' => -58.0],
'QA' => ['name' => 'Qatar', 'latitude' => 25.5, 'longitude' => 51.25],
'RO' => ['name' => 'Romania', 'latitude' => 46.0, 'longitude' => 25.0],
'RU' => ['name' => 'Russia', 'latitude' => 60.0, 'longitude' => 100.0],
'RW' => ['name' => 'Rwanda', 'latitude' => -2.0, 'longitude' => 30.0],
'SA' => ['name' => 'Saudi Arabia', 'latitude' => 25.0, 'longitude' => 45.0],
'SD' => ['name' => 'Sudan', 'latitude' => 15.0, 'longitude' => 30.0],
'SN' => ['name' => 'Senegal', 'latitude' => 14.0, 'longitude' => -14.0],
'SG' => ['name' => 'Singapore', 'latitude' => 1.37, 'longitude' => 103.8],
'SB' => ['name' => 'Solomon Islands', 'latitude' => -8.0, 'longitude' => 159.0],
'SL' => ['name' => 'Sierra Leone', 'latitude' => 8.5, 'longitude' => -11.5],
'SV' => ['name' => 'El Salvador', 'latitude' => 13.83, 'longitude' => -88.92],
'SM' => ['name' => 'San Marino', 'latitude' => 43.77, 'longitude' => 12.42],
'SO' => ['name' => 'Somalia', 'latitude' => 10.0, 'longitude' => 49.0],
'RS' => ['name' => 'Serbia', 'latitude' => 44.0, 'longitude' => 21.0],
'SS' => ['name' => 'South Sudan', 'latitude' => 8.0, 'longitude' => 30.0],
'ST' => ['name' => 'São Tomé and Príncipe', 'latitude' => 1.0, 'longitude' => 7.0],
'SR' => ['name' => 'Suriname', 'latitude' => 4.0, 'longitude' => -56.0],
'SK' => ['name' => 'Slovakia', 'latitude' => 48.67, 'longitude' => 19.5],
'SI' => ['name' => 'Slovenia', 'latitude' => 46.0, 'longitude' => 15.0],
'SE' => ['name' => 'Sweden', 'latitude' => 62.0, 'longitude' => 15.0],
'SZ' => ['name' => 'Eswatini', 'latitude' => -26.5, 'longitude' => 31.5],
'SC' => ['name' => 'Seychelles', 'latitude' => -4.58, 'longitude' => 55.67],
'SY' => ['name' => 'Syria', 'latitude' => 35.0, 'longitude' => 38.0],
'TD' => ['name' => 'Chad', 'latitude' => 15.0, 'longitude' => 19.0],
'TG' => ['name' => 'Togo', 'latitude' => 8.0, 'longitude' => 1.17],
'TH' => ['name' => 'Thailand', 'latitude' => 15.0, 'longitude' => 100.0],
'TJ' => ['name' => 'Tajikistan', 'latitude' => 39.0, 'longitude' => 71.0],
'TM' => ['name' => 'Turkmenistan', 'latitude' => 40.0, 'longitude' => 60.0],
'TL' => ['name' => 'Timor-Leste', 'latitude' => -8.83, 'longitude' => 125.92],
'TO' => ['name' => 'Tonga', 'latitude' => -20.0, 'longitude' => -175.0],
'TT' => ['name' => 'Trinidad and Tobago', 'latitude' => 11.0, 'longitude' => -61.0],
'TN' => ['name' => 'Tunisia', 'latitude' => 34.0, 'longitude' => 9.0],
'TR' => ['name' => 'Turkey', 'latitude' => 39.0, 'longitude' => 35.0],
'TV' => ['name' => 'Tuvalu', 'latitude' => -8.0, 'longitude' => 178.0],
'TZ' => ['name' => 'Tanzania', 'latitude' => -6.0, 'longitude' => 35.0],
'TW' => ['name' => 'Taiwan', 'latitude' => 23.5, 'longitude' => 121.0],
'UG' => ['name' => 'Uganda', 'latitude' => 1.0, 'longitude' => 32.0],
'UA' => ['name' => 'Ukraine', 'latitude' => 49.0, 'longitude' => 32.0],
'UY' => ['name' => 'Uruguay', 'latitude' => -33.0, 'longitude' => -56.0],
'US' => ['name' => 'United States', 'latitude' => 38.0, 'longitude' => -97.0],
'UZ' => ['name' => 'Uzbekistan', 'latitude' => 41.0, 'longitude' => 64.0],
'VA' => ['name' => 'Vatican City', 'latitude' => 41.9, 'longitude' => 12.45],
'VC' => ['name' => 'Saint Vincent and the Grenadines', 'latitude' => 13.25, 'longitude' => -61.2],
'VE' => ['name' => 'Venezuela', 'latitude' => 8.0, 'longitude' => -66.0],
'VN' => ['name' => 'Vietnam', 'latitude' => 16.0, 'longitude' => 106.0],
'VU' => ['name' => 'Vanuatu', 'latitude' => -16.0, 'longitude' => 167.0],
'WS' => ['name' => 'Samoa', 'latitude' => -13.58, 'longitude' => -172.33],
'YE' => ['name' => 'Yemen', 'latitude' => 15.0, 'longitude' => 48.0],
'ZA' => ['name' => 'South Africa', 'latitude' => -29.0, 'longitude' => 24.0],
'ZM' => ['name' => 'Zambia', 'latitude' => -15.0, 'longitude' => 30.0],
'ZW' => ['name' => 'Zimbabwe', 'latitude' => -20.0, 'longitude' => 30.0],
];
+9 -9
View File
@@ -11,7 +11,7 @@ return [
[
'key' => 'web',
'name' => 'Web',
'version' => '16.1.0',
'version' => '17.0.1',
'url' => 'https://github.com/appwrite/sdk-for-web',
'package' => 'https://www.npmjs.com/package/appwrite',
'enabled' => true,
@@ -59,7 +59,7 @@ return [
[
'key' => 'flutter',
'name' => 'Flutter',
'version' => '13.1.1',
'version' => '15.0.0',
'url' => 'https://github.com/appwrite/sdk-for-flutter',
'package' => 'https://pub.dev/packages/appwrite',
'enabled' => true,
@@ -77,7 +77,7 @@ return [
[
'key' => 'apple',
'name' => 'Apple',
'version' => '7.1.0',
'version' => '9.0.0',
'url' => 'https://github.com/appwrite/sdk-for-apple',
'package' => 'https://github.com/appwrite/sdk-for-apple',
'enabled' => true,
@@ -134,7 +134,7 @@ return [
[
'key' => 'react-native',
'name' => 'React Native',
'version' => '0.6.0',
'version' => '0.7.1',
'url' => 'https://github.com/appwrite/sdk-for-react-native',
'package' => 'https://npmjs.com/package/react-native-appwrite',
'enabled' => true,
@@ -217,7 +217,7 @@ return [
[
'key' => 'cli',
'name' => 'Command Line',
'version' => '6.2.0',
'version' => '6.2.2',
'url' => 'https://github.com/appwrite/sdk-for-cli',
'package' => 'https://www.npmjs.com/package/appwrite-cli',
'enabled' => true,
@@ -245,7 +245,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '14.2.0',
'version' => '15.0.1',
'url' => 'https://github.com/appwrite/sdk-for-node',
'package' => 'https://www.npmjs.com/package/node-appwrite',
'enabled' => true,
@@ -299,7 +299,7 @@ return [
[
'key' => 'python',
'name' => 'Python',
'version' => '6.2.0',
'version' => '9.0.2',
'url' => 'https://github.com/appwrite/sdk-for-python',
'package' => 'https://pypi.org/project/appwrite/',
'enabled' => true,
@@ -371,7 +371,7 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '12.2.0',
'version' => '14.0.0',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'package' => 'https://pub.dev/packages/dart_appwrite',
'enabled' => true,
@@ -411,7 +411,7 @@ return [
[
'key' => 'swift',
'name' => 'Swift',
'version' => '6.2.0',
'version' => '8.0.0',
'url' => 'https://github.com/appwrite/sdk-for-swift',
'package' => 'https://github.com/appwrite/sdk-for-swift',
'enabled' => true,
+1 -65
View File
@@ -3,72 +3,8 @@
return [
'default' => [
'$id' => 'default',
'name' => 'Frankfurt',
'name' => 'default',
'disabled' => false,
'flag' => 'de',
'default' => true,
],
'fra' => [
'$id' => 'fra',
'name' => 'Frankfurt',
'disabled' => false,
'flag' => 'de',
'default' => true,
],
'nyc' => [
'$id' => 'nyc',
'name' => 'New York',
'disabled' => true,
'flag' => 'us',
'default' => true,
],
'sfo' => [
'$id' => 'sfo',
'name' => 'San Francisco',
'disabled' => true,
'flag' => 'us',
'default' => true,
],
'blr' => [
'$id' => 'blr',
'name' => 'Bengaluru',
'disabled' => true,
'flag' => 'in',
'default' => true,
],
'lon' => [
'$id' => 'lon',
'name' => 'London',
'disabled' => true,
'flag' => 'gb',
'default' => true,
],
'ams' => [
'$id' => 'ams',
'name' => 'Amsterdam',
'disabled' => true,
'flag' => 'nl',
'default' => true,
],
'sgp' => [
'$id' => 'sgp',
'name' => 'Singapore',
'disabled' => true,
'flag' => 'sg',
'default' => true,
],
'tor' => [
'$id' => 'tor',
'name' => 'Toronto',
'disabled' => true,
'flag' => 'ca',
'default' => true,
],
'syd' => [
'$id' => 'syd',
'name' => 'Sydney',
'disabled' => true,
'flag' => 'au',
'default' => true,
],
];
+1 -1
View File
@@ -184,7 +184,7 @@ return [
'docsUrl' => 'https://appwrite.io/docs/sites',
'tests' => false,
'optional' => true,
'icon' => '', // TODO: Update icon later
'icon' => '/images/services/sites.png',
],
'functions' => [
'key' => 'functions',
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -6848,7 +6848,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"schema": {
"type": "array",
+161 -21
View File
@@ -9268,7 +9268,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"entrypoint": {
@@ -9362,7 +9362,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "functions.read",
"scope": "public",
"platforms": [
"server"
],
@@ -9889,7 +9889,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"entrypoint": {
@@ -10140,7 +10140,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@@ -10510,17 +10510,18 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"x-example": "branch",
"enum": [
"branch"
"branch",
"commit"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"x-example": "<REFERENCE>"
},
"activate": {
@@ -19352,8 +19353,7 @@
"description": "Project Region.",
"x-example": "default",
"enum": [
"default",
"fra"
"default"
],
"x-enum-name": null,
"x-enum-keys": []
@@ -24718,6 +24718,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -24730,6 +24731,11 @@
"description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
@@ -24912,7 +24918,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "sites.read",
"scope": "public",
"platforms": [
"server"
],
@@ -25348,6 +25354,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -25360,6 +25367,11 @@
"description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
@@ -25698,7 +25710,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@@ -25902,7 +25914,7 @@
},
"\/sites\/{siteId}\/deployments\/template": {
"post": {
"summary": "Create deployment",
"summary": "Create template deployment",
"operationId": "sitesCreateTemplateDeployment",
"tags": [
"sites"
@@ -26068,18 +26080,19 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"x-example": "branch",
"enum": [
"branch",
"commit"
"commit",
"tag"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"x-example": "<REFERENCE>"
},
"activate": {
@@ -28882,7 +28895,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"schema": {
"type": "array",
@@ -30975,6 +30988,30 @@
"x-example": "<USER_ID>"
},
"in": "path"
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"schema": {
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"in": "query"
},
{
"name": "search",
"description": "Search term to filter your list results. Max length: 256 chars.",
"required": false,
"schema": {
"type": "string",
"x-example": "<SEARCH>",
"default": ""
},
"in": "query"
}
]
}
@@ -36863,6 +36900,11 @@
"description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"framework": {
"type": "string",
"description": "Site framework.",
@@ -36873,6 +36915,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@@ -36955,8 +37027,15 @@
"name",
"enabled",
"live",
"logging",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@@ -36987,6 +37066,11 @@
"description": "Site Template Name.",
"x-example": "Starter site"
},
"tagline": {
"type": "string",
"description": "Short description of template",
"x-example": "Minimal web app integrating with Appwrite."
},
"demoUrl": {
"type": "string",
"description": "URL hosting a template demo.",
@@ -37050,6 +37134,7 @@
"required": [
"key",
"name",
"tagline",
"demoUrl",
"screenshotDark",
"screenshotLight",
@@ -37168,7 +37253,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"runtime": {
@@ -37181,6 +37266,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@@ -37273,6 +37378,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@@ -37924,13 +38033,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@@ -37984,6 +38099,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@@ -38006,7 +38127,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@@ -38081,6 +38202,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",
@@ -40750,11 +40872,21 @@
"description": "Console Variables",
"type": "object",
"properties": {
"_APP_DOMAIN_TARGET": {
"_APP_DOMAIN_TARGET_CNAME": {
"type": "string",
"description": "CNAME target for your Appwrite custom domains.",
"x-example": "appwrite.io"
},
"_APP_DOMAIN_TARGET_A": {
"type": "string",
"description": "A target for your Appwrite custom domains.",
"x-example": "127.0.0.1"
},
"_APP_DOMAIN_TARGET_AAAA": {
"type": "string",
"description": "AAAA target for your Appwrite custom domains.",
"x-example": "::1"
},
"_APP_STORAGE_LIMIT": {
"type": "integer",
"description": "Maximum file size allowed for file upload in bytes.",
@@ -40792,6 +40924,11 @@
"description": "A domain to use for site URLs.",
"x-example": "sites.localhost"
},
"_APP_DOMAIN_FUNCTIONS": {
"type": "string",
"description": "A domain to use for function URLs.",
"x-example": "functions.localhost"
},
"_APP_OPTIONS_FORCE_HTTPS": {
"type": "string",
"description": "Defines if HTTPS is enforced for all requests.",
@@ -40804,7 +40941,9 @@
}
},
"required": [
"_APP_DOMAIN_TARGET",
"_APP_DOMAIN_TARGET_CNAME",
"_APP_DOMAIN_TARGET_A",
"_APP_DOMAIN_TARGET_AAAA",
"_APP_STORAGE_LIMIT",
"_APP_COMPUTE_SIZE_LIMIT",
"_APP_USAGE_STATS",
@@ -40812,6 +40951,7 @@
"_APP_DOMAIN_ENABLED",
"_APP_ASSISTANT_ENABLED",
"_APP_DOMAIN_SITES",
"_APP_DOMAIN_FUNCTIONS",
"_APP_OPTIONS_FORCE_HTTPS",
"_APP_DOMAINS_NAMESERVERS"
]
+134 -17
View File
@@ -8355,7 +8355,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"entrypoint": {
@@ -8449,7 +8449,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "functions.read",
"scope": "public",
"platforms": [
"server"
],
@@ -8751,7 +8751,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"entrypoint": {
@@ -9005,7 +9005,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@@ -9379,17 +9379,18 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"x-example": "branch",
"enum": [
"branch"
"branch",
"commit"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"x-example": "<REFERENCE>"
},
"activate": {
@@ -16815,6 +16816,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -16827,6 +16829,11 @@
"description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
@@ -17009,7 +17016,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "sites.read",
"scope": "public",
"platforms": [
"server"
],
@@ -17220,6 +17227,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -17232,6 +17240,11 @@
"description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
@@ -17573,7 +17586,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@@ -17779,7 +17792,7 @@
},
"\/sites\/{siteId}\/deployments\/template": {
"post": {
"summary": "Create deployment",
"summary": "Create template deployment",
"operationId": "sitesCreateTemplateDeployment",
"tags": [
"sites"
@@ -17947,18 +17960,19 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"x-example": "branch",
"enum": [
"branch",
"commit"
"commit",
"tag"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"x-example": "<REFERENCE>"
},
"activate": {
@@ -20501,7 +20515,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"schema": {
"type": "array",
@@ -22555,6 +22569,30 @@
"x-example": "<USER_ID>"
},
"in": "path"
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"schema": {
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"in": "query"
},
{
"name": "search",
"description": "Search term to filter your list results. Max length: 256 chars.",
"required": false,
"schema": {
"type": "string",
"x-example": "<SEARCH>",
"default": ""
},
"in": "query"
}
]
}
@@ -27411,6 +27449,11 @@
"description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"framework": {
"type": "string",
"description": "Site framework.",
@@ -27421,6 +27464,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@@ -27503,8 +27576,15 @@
"name",
"enabled",
"live",
"logging",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@@ -27565,7 +27645,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"runtime": {
@@ -27578,6 +27658,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@@ -27670,6 +27770,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@@ -27823,13 +27927,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@@ -27883,6 +27993,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@@ -27905,7 +28021,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@@ -27980,6 +28096,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7060,7 +7060,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"type": "array",
"collectionFormat": "multi",
+162 -23
View File
@@ -9425,7 +9425,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"default": true,
"x-example": false
},
@@ -9530,7 +9530,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "functions.read",
"scope": "public",
"platforms": [
"server"
],
@@ -10061,7 +10061,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"default": true,
"x-example": false
},
@@ -10322,7 +10322,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@@ -10687,18 +10687,19 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"default": null,
"x-example": "branch",
"enum": [
"branch"
"branch",
"commit"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"default": null,
"x-example": "<REFERENCE>"
},
@@ -19822,8 +19823,7 @@
"default": "default",
"x-example": "default",
"enum": [
"default",
"fra"
"default"
],
"x-enum-name": null,
"x-enum-keys": []
@@ -25221,6 +25221,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -25234,10 +25235,16 @@
"default": true,
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"default": true,
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
"default": 15,
"default": 30,
"x-example": 1
},
"installCommand": {
@@ -25430,7 +25437,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "sites.read",
"scope": "public",
"platforms": [
"server"
],
@@ -25865,6 +25872,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -25878,10 +25886,16 @@
"default": true,
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"default": true,
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
"default": 15,
"default": 30,
"x-example": 1
},
"installCommand": {
@@ -26229,7 +26243,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@@ -26428,7 +26442,7 @@
},
"\/sites\/{siteId}\/deployments\/template": {
"post": {
"summary": "Create deployment",
"summary": "Create template deployment",
"operationId": "sitesCreateTemplateDeployment",
"consumes": [
"application\/json"
@@ -26596,19 +26610,20 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"default": null,
"x-example": "branch",
"enum": [
"branch",
"commit"
"commit",
"tag"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"default": null,
"x-example": "<REFERENCE>"
},
@@ -29413,7 +29428,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"type": "array",
"collectionFormat": "multi",
@@ -31556,6 +31571,27 @@
"type": "string",
"x-example": "<USER_ID>",
"in": "path"
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"type": "array",
"collectionFormat": "multi",
"items": {
"type": "string"
},
"default": [],
"in": "query"
},
{
"name": "search",
"description": "Search term to filter your list results. Max length: 256 chars.",
"required": false,
"type": "string",
"x-example": "<SEARCH>",
"default": "",
"in": "query"
}
]
}
@@ -37443,6 +37479,11 @@
"description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"framework": {
"type": "string",
"description": "Site framework.",
@@ -37453,6 +37494,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@@ -37536,8 +37607,15 @@
"name",
"enabled",
"live",
"logging",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@@ -37568,6 +37646,11 @@
"description": "Site Template Name.",
"x-example": "Starter site"
},
"tagline": {
"type": "string",
"description": "Short description of template",
"x-example": "Minimal web app integrating with Appwrite."
},
"demoUrl": {
"type": "string",
"description": "URL hosting a template demo.",
@@ -37633,6 +37716,7 @@
"required": [
"key",
"name",
"tagline",
"demoUrl",
"screenshotDark",
"screenshotLight",
@@ -37751,7 +37835,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"runtime": {
@@ -37764,6 +37848,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@@ -37857,6 +37961,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@@ -38511,13 +38619,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@@ -38571,6 +38685,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@@ -38593,7 +38713,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@@ -38668,6 +38788,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",
@@ -41410,11 +41531,21 @@
"description": "Console Variables",
"type": "object",
"properties": {
"_APP_DOMAIN_TARGET": {
"_APP_DOMAIN_TARGET_CNAME": {
"type": "string",
"description": "CNAME target for your Appwrite custom domains.",
"x-example": "appwrite.io"
},
"_APP_DOMAIN_TARGET_A": {
"type": "string",
"description": "A target for your Appwrite custom domains.",
"x-example": "127.0.0.1"
},
"_APP_DOMAIN_TARGET_AAAA": {
"type": "string",
"description": "AAAA target for your Appwrite custom domains.",
"x-example": "::1"
},
"_APP_STORAGE_LIMIT": {
"type": "integer",
"description": "Maximum file size allowed for file upload in bytes.",
@@ -41452,6 +41583,11 @@
"description": "A domain to use for site URLs.",
"x-example": "sites.localhost"
},
"_APP_DOMAIN_FUNCTIONS": {
"type": "string",
"description": "A domain to use for function URLs.",
"x-example": "functions.localhost"
},
"_APP_OPTIONS_FORCE_HTTPS": {
"type": "string",
"description": "Defines if HTTPS is enforced for all requests.",
@@ -41464,7 +41600,9 @@
}
},
"required": [
"_APP_DOMAIN_TARGET",
"_APP_DOMAIN_TARGET_CNAME",
"_APP_DOMAIN_TARGET_A",
"_APP_DOMAIN_TARGET_AAAA",
"_APP_STORAGE_LIMIT",
"_APP_COMPUTE_SIZE_LIMIT",
"_APP_USAGE_STATS",
@@ -41472,6 +41610,7 @@
"_APP_DOMAIN_ENABLED",
"_APP_ASSISTANT_ENABLED",
"_APP_DOMAIN_SITES",
"_APP_DOMAIN_FUNCTIONS",
"_APP_OPTIONS_FORCE_HTTPS",
"_APP_DOMAINS_NAMESERVERS"
]
+135 -19
View File
@@ -8509,7 +8509,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"default": true,
"x-example": false
},
@@ -8614,7 +8614,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "functions.read",
"scope": "public",
"platforms": [
"server"
],
@@ -8924,7 +8924,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"default": true,
"x-example": false
},
@@ -9188,7 +9188,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@@ -9557,18 +9557,19 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"default": null,
"x-example": "branch",
"enum": [
"branch"
"branch",
"commit"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"default": null,
"x-example": "<REFERENCE>"
},
@@ -17284,6 +17285,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -17297,10 +17299,16 @@
"default": true,
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"default": true,
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
"default": 15,
"default": 30,
"x-example": 1
},
"installCommand": {
@@ -17493,7 +17501,7 @@
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "sites.read",
"scope": "public",
"platforms": [
"server"
],
@@ -17707,6 +17715,7 @@
"sveltekit",
"astro",
"remix",
"lynx",
"flutter",
"vite",
"other"
@@ -17720,10 +17729,16 @@
"default": true,
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"default": true,
"x-example": false
},
"timeout": {
"type": "integer",
"description": "Maximum request time in seconds.",
"default": 15,
"default": 30,
"x-example": 1
},
"installCommand": {
@@ -18074,7 +18089,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@@ -18275,7 +18290,7 @@
},
"\/sites\/{siteId}\/deployments\/template": {
"post": {
"summary": "Create deployment",
"summary": "Create template deployment",
"operationId": "sitesCreateTemplateDeployment",
"consumes": [
"application\/json"
@@ -18445,19 +18460,20 @@
"properties": {
"type": {
"type": "string",
"description": "Type of reference passed. Allowed values are: branch",
"description": "Type of reference passed. Allowed values are: branch, commit",
"default": null,
"x-example": "branch",
"enum": [
"branch",
"commit"
"commit",
"tag"
],
"x-enum-name": "VCSDeploymentType",
"x-enum-keys": []
},
"reference": {
"type": "string",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name",
"description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash",
"default": null,
"x-example": "<REFERENCE>"
},
@@ -21007,7 +21023,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"type": "array",
"collectionFormat": "multi",
@@ -23111,6 +23127,27 @@
"type": "string",
"x-example": "<USER_ID>",
"in": "path"
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
"required": false,
"type": "array",
"collectionFormat": "multi",
"items": {
"type": "string"
},
"default": [],
"in": "query"
},
{
"name": "search",
"description": "Search term to filter your list results. Max length: 256 chars.",
"required": false,
"type": "string",
"x-example": "<SEARCH>",
"default": "",
"in": "query"
}
]
}
@@ -27962,6 +27999,11 @@
"description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.",
"x-example": false
},
"logging": {
"type": "boolean",
"description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.",
"x-example": false
},
"framework": {
"type": "string",
"description": "Site framework.",
@@ -27972,6 +28014,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@@ -28055,8 +28127,15 @@
"name",
"enabled",
"live",
"logging",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@@ -28117,7 +28196,7 @@
},
"logging": {
"type": "boolean",
"description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.",
"description": "When disabled, executions will exclude logs and errors, and will be slightly faster.",
"x-example": false
},
"runtime": {
@@ -28130,6 +28209,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@@ -28223,6 +28322,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@@ -28377,13 +28480,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@@ -28437,6 +28546,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@@ -28459,7 +28574,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@@ -28534,6 +28649,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",
+3
View File
@@ -1,5 +1,8 @@
<?php
// TODO: Remove, replace with runtimes.php directly
// Used in function templates and site frameworks
return [
'NODE' => [
'name' => 'node',
+39
View File
@@ -23,6 +23,7 @@ return [
'icon' => 'icon-lightning-bolt',
'id' => 'starter',
'name' => 'Starter function',
'score' => 5,
'tagline' =>
'A simple function to get started. Edit this function to explore endless possibilities with Appwrite Functions.',
'permissions' => ['any'],
@@ -62,6 +63,7 @@ return [
'icon' => 'icon-upstash',
'id' => 'query-upstash-vector',
'name' => 'Query Upstash Vector',
'score' => 4,
'tagline' => 'Vector database that stores text embeddings and context retrieval for LLMs',
'permissions' => ['any'],
'events' => [],
@@ -106,6 +108,7 @@ return [
'icon' => 'icon-redis',
'id' => 'query-redis-labs',
'name' => 'Query Redis Labs',
'score' => 4,
'tagline' => 'Key-value database with advanced caching capabilities.',
'permissions' => ['any'],
'events' => [],
@@ -149,6 +152,7 @@ return [
'icon' => 'icon-neo4j',
'id' => 'query-neo4j-auradb',
'name' => 'Query Neo4j AuraDB',
'score' => 4,
'tagline' => 'Graph database with focus on relations between data.',
'permissions' => ['any'],
'events' => [],
@@ -200,6 +204,7 @@ return [
'icon' => 'icon-mongodb',
'id' => 'query-mongo-atlas',
'name' => 'Query MongoDB Atlas',
'score' => 4,
'tagline' =>
'Realtime NoSQL document database with geospecial, graph, search, and vector suport.',
'permissions' => ['any'],
@@ -237,6 +242,7 @@ return [
'icon' => 'icon-neon',
'id' => 'query-neon-postgres',
'name' => 'Query Neon Postgres',
'score' => 4,
'tagline' =>
'Reliable SQL database with replication, point-in-time recovery, and pgvector support.',
'permissions' => ['any'],
@@ -305,6 +311,7 @@ return [
'icon' => 'icon-open-ai',
'id' => 'prompt-chatgpt',
'name' => 'Prompt ChatGPT',
'score' => 7,
'tagline' => 'Ask questions and let OpenAI GPT-3.5-turbo answer.',
'permissions' => ['any'],
'events' => [],
@@ -366,6 +373,7 @@ return [
'icon' => 'icon-discord',
'id' => 'discord-command-bot',
'name' => 'Discord Command Bot',
'score' => 6,
'tagline' => 'Simple command using Discord Interactions.',
'permissions' => ['any'],
'events' => [],
@@ -429,6 +437,7 @@ return [
'icon' => 'icon-perspective-api',
'id' => 'analyze-with-perspectiveapi',
'name' => 'Analyze with PerspectiveAPI',
'score' => 5,
'tagline' => 'Automate moderation by getting toxicity of messages.',
'permissions' => ['any'],
'events' => [],
@@ -464,6 +473,7 @@ return [
'icon' => 'icon-pangea',
'id' => 'censor-with-redact',
'name' => 'Censor with Redact',
'score' => 5,
'tagline' =>
'Censor sensitive information from a provided text string using Redact API by Pangea.',
'permissions' => ['any'],
@@ -512,6 +522,7 @@ return [
'icon' => 'icon-document',
'id' => 'generate-pdf',
'name' => 'Generate PDF',
'score' => 7,
'tagline' => 'Document containing sample invoice in PDF format.',
'permissions' => ['any'],
'events' => [],
@@ -533,6 +544,7 @@ return [
'icon' => 'icon-github',
'id' => 'github-issue-bot',
'name' => 'GitHub issue bot',
'score' => 4,
'tagline' =>
'Automate the process of responding to newly opened issues in a GitHub repository.',
'permissions' => ['any'],
@@ -577,6 +589,7 @@ return [
'icon' => 'icon-bookmark',
'id' => 'url-shortener',
'name' => 'URL shortener',
'score' => 3,
'tagline' => 'Generate URL with short ID and redirect to the original URL when visited.',
'permissions' => ['any'],
'events' => [],
@@ -628,6 +641,7 @@ return [
'icon' => 'icon-algolia',
'id' => 'sync-with-algolia',
'name' => 'Sync with Algolia',
'score' => 4,
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
'permissions' => ['any'],
'events' => [],
@@ -709,6 +723,7 @@ return [
'icon' => 'icon-meilisearch',
'id' => 'sync-with-meilisearch',
'name' => 'Sync with Meilisearch',
'score' => 4,
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
'permissions' => ['any'],
'events' => [],
@@ -802,6 +817,7 @@ return [
'icon' => 'icon-vonage',
'id' => 'whatsapp-with-vonage',
'name' => 'WhatsApp with Vonage',
'score' => 6,
'tagline' => 'Simple bot to answer WhatsApp messages.',
'permissions' => ['any'],
'events' => [],
@@ -888,6 +904,7 @@ return [
'icon' => 'icon-bell',
'id' => 'push-notification-with-fcm',
'name' => 'Push notification with FCM',
'score' => 4,
'tagline' => 'Send push notifications to your users using Firebase Cloud Messaging (FCM).',
'permissions' => ['any'],
'events' => [],
@@ -944,6 +961,7 @@ return [
'icon' => 'icon-mail',
'id' => 'email-contact-form',
'name' => 'Email contact form',
'score' => 7,
'tagline' => 'Sends an email with the contents of a HTML form.',
'permissions' => ['any'],
'events' => [],
@@ -1027,6 +1045,7 @@ return [
'icon' => 'icon-stripe',
'id' => 'subscriptions-with-stripe',
'name' => 'Subscriptions with Stripe',
'score' => 6,
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
'permissions' => ['any'],
'events' => [],
@@ -1068,6 +1087,7 @@ return [
'icon' => 'icon-stripe',
'id' => 'payments-with-stripe',
'name' => 'Payments with Stripe',
'score' => 8,
'tagline' => 'Receive card payments and store paid orders.',
'permissions' => ['any'],
'events' => [],
@@ -1125,6 +1145,7 @@ return [
'icon' => 'icon-chat',
'id' => 'text-generation-with-huggingface',
'name' => 'Text generation',
'score' => 5,
'tagline' => 'Generate text using the Hugging Face inference API.',
'permissions' => ['any'],
'events' => [],
@@ -1159,6 +1180,7 @@ return [
'icon' => 'icon-translate',
'id' => 'language-translation-with-huggingface',
'name' => 'Language translation',
'score' => 5,
'tagline' => 'Translate text using the Hugging Face inference API.',
'permissions' => ['any'],
'events' => [],
@@ -1193,6 +1215,7 @@ return [
'icon' => 'icon-eye',
'id' => 'image-classification-with-huggingface',
'name' => 'Image classification',
'score' => 5,
'tagline' => 'Classify images using the Hugging Face inference API.',
'permissions' => ['any'],
'events' => ['buckets.*.files.*.create'],
@@ -1251,6 +1274,7 @@ return [
'icon' => 'icon-eye',
'id' => 'object-detection-with-huggingface',
'name' => 'Object detection',
'score' => 5,
'tagline' => 'Detect objects in images using the Hugging Face inference API.',
'permissions' => ['any'],
'events' => ['buckets.*.files.*.create'],
@@ -1309,6 +1333,7 @@ return [
'icon' => 'icon-text',
'id' => 'speech-recognition-with-huggingface',
'name' => 'Speech recognition',
'score' => 5,
'tagline' => 'Transcribe audio to text using the Hugging Face inference API.',
'permissions' => ['any'],
'events' => ['buckets.*.files.*.create'],
@@ -1367,6 +1392,7 @@ return [
'icon' => 'icon-chat',
'id' => 'text-to-speech-with-huggingface',
'name' => 'Text to speech',
'score' => 5,
'tagline' => 'Convert text to speech using the Hugging Face inference API.',
'permissions' => ['any'],
'events' => ['databases.*.collections.*.documents.*.create'],
@@ -1425,6 +1451,7 @@ return [
'icon' => 'icon-chip',
'id' => 'generate-with-replicate',
'name' => 'Generate with Replicate',
'score' => 5,
'tagline' => "Generate text, audio and images using Replicate's API.",
'permissions' => ['any'],
'events' => [],
@@ -1460,6 +1487,7 @@ return [
'icon' => 'icon-chip',
'id' => 'generate-with-together-ai',
'name' => 'Generate with Together AI',
'score' => 5,
'tagline' => "Generate text and images using Together AI's API.",
'permissions' => ['any'],
'events' => [],
@@ -1502,6 +1530,7 @@ return [
'icon' => 'icon-chip',
'id' => 'chat-with-perplexity-ai',
'name' => 'Chat with Perplexity AI',
'score' => 5,
'tagline' => 'Create a chatbot using the Perplexity AI API.',
'permissions' => ['any'],
'events' => [],
@@ -1543,6 +1572,7 @@ return [
'icon' => 'icon-chip',
'id' => 'generate-with-replicate',
'name' => 'Generate with Replicate',
'score' => 5,
'tagline' => "Generate text, audio and images using Replicate's API.",
'permissions' => ['any'],
'events' => [],
@@ -1578,6 +1608,7 @@ return [
'icon' => 'icon-document-search',
'id' => 'sync-with-pinecone',
'name' => 'Sync with Pinecone',
'score' => 4,
'tagline' => "Sync your Appwrite database with Pinecone's vector database.",
'permissions' => ['any'],
'events' => [],
@@ -1641,6 +1672,7 @@ return [
'icon' => 'icon-chip',
'id' => 'rag-with-langchain',
'name' => 'RAG with LangChain',
'score' => 6,
'tagline' => 'Generate text using a LangChain RAG model',
'permissions' => ['any'],
'events' => [],
@@ -1704,6 +1736,7 @@ return [
'icon' => 'icon-chat',
'id' => 'speak-with-elevenlabs',
'name' => 'Speak with ElevenLabs',
'score' => 5,
'tagline' => 'Convert text to speech using the ElevenLabs API.',
'permissions' => ['any'],
'cron' => '',
@@ -1759,6 +1792,7 @@ return [
'icon' => 'icon-chip',
'id' => 'speak-with-lmnt',
'name' => 'Speak with LMNT',
'score' => 5,
'tagline' => 'Convert text to speech using the LMNT API.',
'permissions' => ['any'],
'cron' => '',
@@ -1800,6 +1834,7 @@ return [
'icon' => 'icon-chip',
'id' => 'chat-with-anyscale',
'name' => 'Chat with AnyScale',
'score' => 5,
'tagline' => 'Create a chatbot using the AnyScale API.',
'permissions' => ['any'],
'cron' => '',
@@ -1841,6 +1876,7 @@ return [
'icon' => 'icon-music-note',
'id' => 'music-generation-with-huggingface',
'name' => 'Music generation',
'score' => 4,
'tagline' => 'Generate music from a text prompt using the Hugging Face inference API.',
'permissions' => ['any'],
'events' => [],
@@ -1883,6 +1919,7 @@ return [
'icon' => 'icon-chip',
'id' => 'generate-with-fal-ai',
'name' => 'Generate with fal.ai',
'score' => 5,
'tagline' => "Generate images using fal.ai's API.",
'permissions' => ['any'],
'events' => [],
@@ -1918,6 +1955,7 @@ return [
'icon' => 'icon-currency-dollar',
'id' => 'subscriptions-with-lemon-squeezy',
'name' => 'Subscriptions with Lemon Squeezy',
'score' => 6,
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
'permissions' => ['any'],
'events' => [],
@@ -1973,6 +2011,7 @@ return [
'icon' => 'icon-currency-dollar',
'id' => 'payments-with-lemon-squeezy',
'name' => 'Payments with Lemon Squeezy',
'score' => 6,
'tagline' => 'Receive card payments and store paid orders.',
'permissions' => ['any'],
'events' => [],
+499 -102
View File
@@ -16,6 +16,16 @@ if (System::getEnv('_APP_ENV') === 'development') {
$url = $protocol . '://' . $hostname;
class UseCases
{
public const PORTFOLIO = 'portfolio';
public const STARTER = 'starter';
public const EVENTS = 'events';
public const ECOMMERCE = 'ecommerce';
public const DOCUMENTATION = 'documentation';
public const BLOG = 'blog';
}
const TEMPLATE_FRAMEWORKS = [
'SVELTEKIT' => [
'key' => 'sveltekit',
@@ -77,15 +87,6 @@ const TEMPLATE_FRAMEWORKS = [
'adapter' => 'static',
'fallbackFile' => '',
],
'OTHER' => [
'key' => 'other',
'name' => 'Other',
'installCommand' => 'npm install',
'buildCommand' => 'npm run build',
'buildRuntime' => 'node-22',
'adapter' => 'static',
'fallbackFile' => 'index.html',
],
'VITE' => [
'key' => 'vite',
'name' => 'Vite',
@@ -115,6 +116,15 @@ const TEMPLATE_FRAMEWORKS = [
'outputDirectory' => './dist/angular/browser',
'fallbackFile' => 'index.html',
],
'ANALOG' => [
'key' => 'analog',
'name' => 'Analog',
'installCommand' => 'npm install',
'buildCommand' => 'npm run build',
'buildRuntime' => 'node-22',
'adapter' => 'ssr',
'outputDirectory' => './dist/analog',
],
'VUE' => [
'key' => 'vue',
'name' => 'Vue.js',
@@ -125,6 +135,25 @@ const TEMPLATE_FRAMEWORKS = [
'outputDirectory' => './dist',
'fallbackFile' => 'index.html',
],
'OTHER' => [
'key' => 'other',
'name' => 'Other',
'installCommand' => '',
'buildCommand' => '',
'buildRuntime' => 'node-22',
'adapter' => 'static',
'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)
@@ -135,14 +164,180 @@ function getFramework(string $frameworkEnum, array $overrides)
return [
[
'key' => 'template-for-onelink',
'name' => 'Onelink template',
'useCases' => ['starter'],
'screenshotDark' => $url . '/images/sites/templates/template-for-onelink-dark.png',
'screenshotLight' => $url . '/images/sites/templates/template-for-onelink-light.png',
'key' => 'template-for-documentation',
'name' => 'Documentation template',
'tagline' => 'Modern site to store your knowledge with a clean design, full-text search, dark mode, and more.',
'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::DOCUMENTATION],
'screenshotDark' => $url . '/images/sites/templates/template-for-documentation-dark.png',
'screenshotLight' => $url . '/images/sites/templates/template-for-documentation-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'template-for-documentation',
'providerOwner' => 'appwrite',
'providerVersion' => '0.1.*',
'variables' => []
],
[
'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',
'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],
'screenshotDark' => $url . '/images/sites/templates/vitepress-dark.png',
'screenshotLight' => $url . '/images/sites/templates/vitepress-light.png',
'frameworks' => [
getFramework('VITE', [
'providerRootDirectory' => './vite/vitepress',
'outputDirectory' => '404.html',
'installCommand' => 'npm i vitepress && npm install',
'buildCommand' => 'npm run docs:build',
'outputDirectory' => './.vitepress/dist',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/vuepress-dark.png',
'screenshotLight' => $url . '/images/sites/templates/vuepress-light.png',
'frameworks' => [
getFramework('VUE', [
'providerRootDirectory' => './vue/vuepress',
'outputDirectory' => '404.html',
'installCommand' => 'npm install',
'buildCommand' => 'npm run build',
'outputDirectory' => './src/.vuepress/dist',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/docusaurus-dark.png',
'screenshotLight' => $url . '/images/sites/templates/docusaurus-light.png',
'frameworks' => [
getFramework('REACT', [
'providerRootDirectory' => './react/docusaurus',
'outputDirectory' => '404.html',
'installCommand' => 'npm install',
'buildCommand' => 'npm run build',
'outputDirectory' => './build',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/nxt-lnk-dark.png',
'screenshotLight' => $url . '/images/sites/templates/nxt-lnk-light.png',
'frameworks' => [
getFramework('NEXTJS', [
'providerRootDirectory' => './nextjs/nxtlnk',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/magic-portfolio-dark.png',
'screenshotLight' => $url . '/images/sites/templates/magic-portfolio-light.png',
'frameworks' => [
getFramework('NEXTJS', [
'providerRootDirectory' => './nextjs/magic-portfolio',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/littlelink-dark.png',
'screenshotLight' => $url . '/images/sites/templates/littlelink-light.png',
'frameworks' => [
getFramework('OTHER', [
'providerRootDirectory' => './other/littlelink',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/logspot-dark.png',
'screenshotLight' => $url . '/images/sites/templates/logspot-light.png',
'frameworks' => [
getFramework('NUXT', [
'providerRootDirectory' => './onelink',
'providerRootDirectory' => './nuxt/logspot',
'buildCommand' => 'npm run generate',
'outputDirectory' => './dist',
'adapter' => 'static',
@@ -150,20 +345,128 @@ return [
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'Meldiron',
'providerVersion' => '0.1.*',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/astro-nano-dark.png',
'screenshotLight' => $url . '/images/sites/templates/astro-nano-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './astro/nano',
'outputDirectory' => './dist',
'adapter' => 'static',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/astro-starlight-dark.png',
'screenshotLight' => $url . '/images/sites/templates/astro-starlight-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './astro/starlight',
'outputDirectory' => './dist',
'adapter' => 'static',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/astro-sphere-dark.png',
'screenshotLight' => $url . '/images/sites/templates/astro-sphere-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './astro/sphere',
'outputDirectory' => './dist',
'adapter' => 'static',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/astro-starlog-dark.png',
'screenshotLight' => $url . '/images/sites/templates/astro-starlog-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './astro/starlog',
'outputDirectory' => './dist',
'adapter' => 'static',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => '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],
'screenshotDark' => $url . '/images/sites/templates/onelink-dark.png',
'screenshotLight' => $url . '/images/sites/templates/onelink-light.png',
'frameworks' => [
getFramework('NUXT', [
'providerRootDirectory' => './nuxt/onelink',
'buildCommand' => 'npm run generate',
'outputDirectory' => './dist',
'adapter' => 'static',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
[
'key' => 'starter-for-flutter',
'name' => 'Flutter starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-flutter-light.png',
'frameworks' => [
getFramework('FLUTTER', [
'providerRootDirectory' => './',
'buildCommand' => 'sh build.sh',
'buildCommand' => 'bash build.sh',
]),
],
'vcsProvider' => 'github',
@@ -200,7 +503,9 @@ return [
[
'key' => 'starter-for-js',
'name' => 'JavaScript starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-js-light.png',
'frameworks' => [
@@ -242,14 +547,16 @@ return [
[
'key' => 'starter-for-angular',
'name' => 'Angular starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-angular-light.png',
'frameworks' => [
getFramework('ANGULAR', [
'providerRootDirectory' => './',
'outputDirectory' => './dist/angular-starter-kit-for-appwrite/browser',
'buildCommand' => 'sh prepare-env.sh && npm run build'
'buildCommand' => 'bash prepare-env.sh && npm run build'
]),
],
'vcsProvider' => 'github',
@@ -283,10 +590,145 @@ return [
],
]
],
[
'key' => 'starter-for-astro',
'name' => 'Astro starter',
'useCases' => [UseCases::STARTER],
'tagline' => 'Simple Astro application integrated with Appwrite SDK.',
'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'screenshotDark' => $url . '/images/sites/templates/starter-for-astro-dark.png',
'screenshotLight' => $url . '/images/sites/templates/starter-for-astro-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './',
'adapter' => 'static',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'starter-for-astro',
'providerOwner' => 'appwrite',
'providerVersion' => '0.1.*',
'variables' => [
[
'name' => 'PUBLIC_APPWRITE_ENDPOINT',
'description' => 'Endpoint of Appwrite server',
'value' => '{apiEndpoint}',
'placeholder' => '{apiEndpoint}',
'required' => true,
'type' => 'text'
],
[
'name' => 'PUBLIC_APPWRITE_PROJECT_ID',
'description' => 'Your Appwrite project ID',
'value' => '{projectId}',
'placeholder' => '{projectId}',
'required' => true,
'type' => 'text'
],
[
'name' => 'PUBLIC_APPWRITE_PROJECT_NAME',
'description' => 'Your Appwrite project name',
'value' => '{projectName}',
'placeholder' => '{projectName}',
'required' => true,
'type' => 'text'
],
]
],
[
'key' => 'starter-for-analog',
'name' => 'Analog starter',
'useCases' => [UseCases::STARTER],
'tagline' => 'Simple Analog application integrated with Appwrite SDK.',
'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'screenshotDark' => $url . '/images/sites/templates/starter-for-analog-dark.png',
'screenshotLight' => $url . '/images/sites/templates/starter-for-analog-light.png',
'frameworks' => [
getFramework('ANALOG', [
'providerRootDirectory' => './',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'starter-for-analog',
'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-remix',
'name' => 'Remix starter',
'useCases' => [UseCases::STARTER],
'tagline' => 'Simple Remix application integrated with Appwrite SDK.',
'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'screenshotDark' => $url . '/images/sites/templates/starter-for-remix-dark.png',
'screenshotLight' => $url . '/images/sites/templates/starter-for-remix-light.png',
'frameworks' => [
getFramework('REMIX', [
'providerRootDirectory' => './',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'starter-for-remix',
'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-svelte',
'name' => 'Svelte starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-svelte-light.png',
'frameworks' => [
@@ -328,7 +770,9 @@ return [
[
'key' => 'starter-for-react',
'name' => 'React starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-react-light.png',
'frameworks' => [
@@ -370,7 +814,9 @@ return [
[
'key' => 'starter-for-vue',
'name' => 'Vue starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-vue-light.png',
'frameworks' => [
@@ -412,7 +858,9 @@ return [
[
'key' => 'starter-for-react-native',
'name' => 'React Native starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-react-native-light.png',
'frameworks' => [
@@ -455,7 +903,9 @@ return [
[
'key' => 'starter-for-nextjs',
'name' => 'Next.js starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-nextjs-light.png',
'frameworks' => [
@@ -497,7 +947,9 @@ return [
[
'key' => 'starter-for-nuxt',
'name' => 'Nuxt starter',
'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',
'screenshotLight' => $url . '/images/sites/templates/starter-for-nuxt-light.png',
'frameworks' => [
@@ -539,7 +991,9 @@ return [
[
'key' => 'template-for-event',
'name' => 'Event template',
'useCases' => ['starter'],
'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],
'screenshotDark' => $url . '/images/sites/templates/template-for-event-dark.png',
'screenshotLight' => $url . '/images/sites/templates/template-for-event-light.png',
'frameworks' => [
@@ -575,7 +1029,9 @@ return [
[
'key' => 'template-for-portfolio',
'name' => 'Portfolio template',
'useCases' => ['starter'],
'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],
'screenshotDark' => $url . '/images/sites/templates/template-for-portfolio-dark.png',
'screenshotLight' => $url . '/images/sites/templates/template-for-portfolio-light.png',
'frameworks' => [
@@ -592,7 +1048,9 @@ return [
[
'key' => 'template-for-store',
'name' => 'Store template',
'useCases' => ['starter'],
'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],
'screenshotDark' => $url . '/images/sites/templates/template-for-store-dark.png',
'screenshotLight' => $url . '/images/sites/templates/template-for-store-light.png',
'frameworks' => [
@@ -634,7 +1092,9 @@ return [
[
'key' => 'template-for-blog',
'name' => 'Blog template',
'useCases' => ['starter'],
'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],
'screenshotDark' => $url . '/images/sites/templates/template-for-blog-dark.png',
'screenshotLight' => $url . '/images/sites/templates/template-for-blog-light.png',
'frameworks' => [
@@ -648,10 +1108,13 @@ return [
'providerVersion' => '0.1.*',
'variables' => []
],
// TODO: Remove astro starter eventually, or add all frameworks's starters
[
'key' => 'astro-starter',
'name' => 'Astro starter',
'useCases' => ['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],
'screenshotDark' => $url . '/images/sites/templates/astro-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/astro-starter-light.png',
'frameworks' => [
@@ -668,7 +1131,9 @@ return [
[
'key' => 'remix-starter',
'name' => 'Remix starter',
'useCases' => ['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],
'screenshotDark' => $url . '/images/sites/templates/remix-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/remix-starter-light.png',
'frameworks' => [
@@ -682,72 +1147,4 @@ return [
'providerVersion' => '0.2.*',
'variables' => [],
],
[
'key' => 'flutter-starter',
'name' => 'Flutter starter',
'useCases' => ['starter'],
'screenshotDark' => $url . '/images/sites/templates/flutter-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/flutter-starter-light.png',
'frameworks' => [
getFramework('FLUTTER', [
'providerRootDirectory' => './flutter/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'variables' => [],
],
[
'key' => 'nextjs-starter',
'name' => 'Next.js starter website',
'useCases' => ['starter'],
'screenshotDark' => $url . '/images/sites/templates/nextjs-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/nextjs-starter-light.png',
'frameworks' => [
getFramework('NEXTJS', [
'providerRootDirectory' => './nextjs/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'variables' => [],
],
[
'key' => 'nuxt-starter',
'name' => 'Nuxt starter website',
'useCases' => ['starter'],
'screenshotDark' => $url . '/images/sites/templates/nuxt-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/nuxt-starter-light.png',
'frameworks' => [
getFramework('NUXT', [
'providerRootDirectory' => './nuxt/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'variables' => [],
],
[
'key' => 'sveltekit-starter',
'name' => 'SvelteKit starter website',
'useCases' => ['starter'],
'screenshotDark' => $url . '/images/sites/templates/sveltekit-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/sveltekit-starter-light.png',
'frameworks' => [
getFramework('SVELTEKIT', [
'providerRootDirectory' => './sveltekit/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'variables' => [],
],
];
+143 -10
View File
@@ -45,7 +45,16 @@ return [
],
[
'name' => '_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS',
'description' => 'Allows you to force HTTPS connection to function domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.',
'description' => 'Deprecated since 1.7.0. Allows you to force HTTPS connection to function domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.',
'introduction' => '',
'default' => 'disabled',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_OPTIONS_ROUTER_FORCE_HTTPS',
'description' => 'Allows you to force HTTPS connection to function and site domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.',
'introduction' => '',
'default' => 'disabled',
'required' => false,
@@ -90,13 +99,40 @@ return [
],
[
'name' => '_APP_DOMAIN_TARGET',
'description' => 'A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.',
'description' => 'Deprecated since 1.7.0. A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.',
'introduction' => '',
'default' => 'localhost',
'required' => true,
'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.' . PHP_EOL . 'You can use the same value as used for the Appwrite hostname.',
'filter' => 'domainTarget'
],
[
'name' => '_APP_DOMAIN_TARGET_CNAME',
'description' => 'A domain that can be used as DNS CNAME record to point to instance of Appwrite server.',
'introduction' => '',
'default' => 'localhost',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOMAIN_TARGET_AAAA',
'description' => 'An IPv6 that can be used as DNS AAAA record to point to instance of Appwrite server.',
'introduction' => '',
'default' => '::1',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOMAIN_TARGET_A',
'description' => 'An IPV4 that can be used as DNS A record to point to instance of Appwrite server.',
'introduction' => '',
'default' => '127.0.0.1',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_CONSOLE_WHITELIST_ROOT',
'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by inviting them to your project. By default this option is enabled.',
@@ -746,13 +782,22 @@ return [
'variables' => [
[
'name' => '_APP_FUNCTIONS_SIZE_LIMIT',
'description' => 'The maximum size of a function in bytes. The default value is 30MB.',
'description' => 'Deprecated since 1.7.0. The maximum size of a function in bytes. The default value is 30MB.',
'introduction' => '0.13.0',
'default' => '30000000',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_COMPUTE_SIZE_LIMIT',
'description' => 'The maximum size of a function and site deployments in bytes. The default value is 30MB.',
'introduction' => '1.7.0',
'default' => '30000000',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_FUNCTIONS_BUILD_SIZE_LIMIT',
'description' => 'The maximum size of a built deployment in bytes. The default value is 2,000,000,000 (2GB), and the maximum value is 4,294,967,295 (4.2GB).',
@@ -773,13 +818,22 @@ return [
],
[
'name' => '_APP_FUNCTIONS_BUILD_TIMEOUT',
'description' => 'The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds.',
'description' => 'Deprecated since 1.7.0. The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds.',
'introduction' => '0.13.0',
'default' => '900',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_COMPUTE_BUILD_TIMEOUT',
'description' => 'The maximum number of seconds allowed as a timeout value when building a new function or site. The default value is 900 seconds.',
'introduction' => '1.7.0',
'default' => '900',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_FUNCTIONS_CONTAINERS',
'description' => 'Deprecated since 1.2.0. Runtimes now timeout by inactivity using \'_APP_FUNCTIONS_INACTIVE_THRESHOLD\'.',
@@ -791,22 +845,40 @@ return [
],
[
'name' => '_APP_FUNCTIONS_CPUS',
'description' => 'The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.',
'description' => 'Deprecated since 1.7.0. The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.',
'introduction' => '0.7.0',
'default' => '0',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_COMPUTE_CPUS',
'description' => 'The maximum number of CPU core a single cloud function or a site is allowed to use. Please note that setting a value higher than available cores might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.',
'introduction' => '1.7.0',
'default' => '0',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_FUNCTIONS_MEMORY',
'description' => 'The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.',
'description' => 'Deprecated since 1.7.0. The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.',
'introduction' => '0.7.0',
'default' => '0',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_COMPUTE_MEMORY',
'description' => 'The maximum amount of memory a single function or site is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.',
'introduction' => '1.7.0',
'default' => '0',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_FUNCTIONS_MEMORY_SWAP',
'description' => 'Deprecated since 1.2.0. High use of swap memory is not recommended to preserve harddrive health.',
@@ -864,13 +936,22 @@ return [
],
[
'name' => '_APP_FUNCTIONS_INACTIVE_THRESHOLD',
'description' => 'The minimum time a function must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.',
'description' => 'Deprecated since 1.7.0. The minimum time a function must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.',
'introduction' => '0.13.0',
'default' => '60',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_COMPUTE_INACTIVE_THRESHOLD',
'description' => 'The minimum time a function or site must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.',
'introduction' => '1.7.0',
'default' => '60',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => 'DOCKERHUB_PULL_USERNAME',
'description' => 'Deprecated with 1.2.0, use \'_APP_DOCKER_HUB_USERNAME\' instead.',
@@ -909,13 +990,22 @@ return [
],
[
'name' => '_APP_FUNCTIONS_RUNTIMES_NETWORK',
'description' => 'The docker network used for communication between the executor and runtimes.',
'description' => 'Deprecated since 1.7.0. The docker network used for communication between the executor and runtimes.',
'introduction' => '1.2.0',
'default' => 'runtimes',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_COMPUTE_RUNTIMES_NETWORK',
'description' => 'The docker network used for communication between the executor and runtimes for sites and functions.',
'introduction' => '1.7.0',
'default' => 'runtimes',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOCKER_HUB_USERNAME',
'description' => 'The username for hub.docker.com. This variable is used to pull images from hub.docker.com.',
@@ -936,7 +1026,7 @@ return [
],
[
'name' => '_APP_FUNCTIONS_MAINTENANCE_INTERVAL',
'description' => 'Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour).',
'description' => 'Deprecated since 1.7.0. Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour).',
'introduction' => '1.4.0',
'default' => '3600',
'required' => false,
@@ -944,8 +1034,42 @@ return [
'question' => '',
'filter' => ''
],
[
'name' => '_APP_COMPUTE_MAINTENANCE_INTERVAL',
'description' => 'Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes of functions and sites. The default value is 3600 seconds (1 hour).',
'introduction' => '1.7.0',
'default' => '3600',
'required' => false,
'overwrite' => true,
'question' => '',
'filter' => ''
],
],
],
[
'category' => 'Sites',
'description' => '',
'variables' => [
[
'name' => '_APP_SITES_TIMEOUT',
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new site. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the sites\'s settings or in appwrite.json.',
'introduction' => '1.7.0',
'default' => '900',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_SITES_RUNTIMES',
'description' => "This option allows you to enable or disable runtime environments for Sites. Disable unused runtimes to save disk space.\n\nTo enable cloud site runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: " . \implode(', ', \array_keys(Config::getParam('runtimes'))),
'introduction' => '1.7.0',
'default' => 'static-1,node-22,flutter-3.29',
'required' => false,
'question' => '',
'filter' => ''
],
]
],
[
'category' => 'VCS (Version Control System)',
'description' => '',
@@ -1048,13 +1172,22 @@ return [
],
[
'name' => '_APP_MAINTENANCE_RETENTION_AUDIT',
'description' => 'IThe maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).',
'description' => 'The maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).',
'introduction' => '0.7.0',
'default' => '1209600',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE',
'description' => 'The maximum duration (in seconds) upto which to retain console audit logs. The default value is 15778800 seconds (6 months).',
'introduction' => '1.6.2',
'default' => '15778800',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_MAINTENANCE_RETENTION_ABUSE',
'description' => 'The maximum duration (in seconds) upto which to retain abuse logs. The default value is 86400 seconds (1 day).',
+2 -1
View File
@@ -496,6 +496,7 @@ App::get('/v1/avatars/qr')
'addQuietzone' => true,
'quietzoneSize' => $margin,
'outputType' => QRCode::OUTPUT_IMAGICK,
'scale' => 15,
]);
$qrcode = new QRCode($options);
@@ -510,7 +511,7 @@ App::get('/v1/avatars/qr')
$response
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
->setContentType('image/png')
->send($image->output('png', 9));
->send($image->output('png', 90));
});
App::get('/v1/avatars/initials')
+21 -5
View File
@@ -8,7 +8,9 @@ use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Database\Document;
use Utopia\Domains\Domain;
use Utopia\System\System;
use Utopia\Validator\IP;
use Utopia\Validator\Text;
App::init()
@@ -40,10 +42,21 @@ App::get('/v1/console/variables')
))
->inject('response')
->action(function (Response $response) {
$isDomainEnabled = !empty(System::getEnv('_APP_DOMAIN', ''))
&& !empty(System::getEnv('_APP_DOMAIN_TARGET', ''))
&& System::getEnv('_APP_DOMAIN', '') !== 'localhost'
&& System::getEnv('_APP_DOMAIN_TARGET', '') !== 'localhost';
$validator = new Domain(System::getEnv('_APP_DOMAIN'));
$isDomainValid = !empty(System::getEnv('_APP_DOMAIN', '')) && $validator->isKnown() && !$validator->isTest();
$validator = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME'));
$isCNAMEValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')) && $validator->isKnown() && !$validator->isTest();
$validator = new IP(IP::V4);
$isAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_A', '')) && ($validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_A')));
$validator = new IP(IP::V6);
$isAAAAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_AAAA', '')) && $validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA'));
$isDomainEnabled = $isDomainValid && (
$isAAAAValid || $isAValid || $isCNAMEValid
);
$isVcsEnabled = !empty(System::getEnv('_APP_VCS_GITHUB_APP_NAME', ''))
&& !empty(System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY', ''))
@@ -54,7 +67,9 @@ App::get('/v1/console/variables')
$isAssistantEnabled = !empty(System::getEnv('_APP_ASSISTANT_OPENAI_API_KEY', ''));
$variables = new Document([
'_APP_DOMAIN_TARGET' => System::getEnv('_APP_DOMAIN_TARGET'),
'_APP_DOMAIN_TARGET_CNAME' => System::getEnv('_APP_DOMAIN_TARGET_CNAME'),
'_APP_DOMAIN_TARGET_AAAA' => System::getEnv('_APP_DOMAIN_TARGET_AAAA'),
'_APP_DOMAIN_TARGET_A' => System::getEnv('_APP_DOMAIN_TARGET_A'),
'_APP_STORAGE_LIMIT' => +System::getEnv('_APP_STORAGE_LIMIT'),
'_APP_COMPUTE_SIZE_LIMIT' => +System::getEnv('_APP_COMPUTE_SIZE_LIMIT'),
'_APP_USAGE_STATS' => System::getEnv('_APP_USAGE_STATS'),
@@ -62,6 +77,7 @@ App::get('/v1/console/variables')
'_APP_DOMAIN_ENABLED' => $isDomainEnabled,
'_APP_ASSISTANT_ENABLED' => $isAssistantEnabled,
'_APP_DOMAIN_SITES' => System::getEnv('_APP_DOMAIN_SITES'),
'_APP_DOMAIN_FUNCTIONS' => System::getEnv('_APP_DOMAIN_FUNCTIONS'),
'_APP_OPTIONS_FORCE_HTTPS' => System::getEnv('_APP_OPTIONS_FORCE_HTTPS'),
'_APP_DOMAINS_NAMESERVERS' => System::getEnv('_APP_DOMAINS_NAMESERVERS'),
]);
+4 -4
View File
@@ -3355,7 +3355,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
$processDocument($collection, $document);
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations)
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations)
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection
@@ -3520,7 +3520,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
}
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations)
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
$response->addHeader('X-Debug-Operations', $operations);
@@ -3661,7 +3661,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$processDocument($collection, $document);
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations)
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
$response->addHeader('X-Debug-Operations', $operations);
@@ -3959,7 +3959,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$setCollection($collection, $newDocument);
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations)
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations);
$response->addHeader('X-Debug-Operations', $operations);
+2 -2
View File
@@ -118,7 +118,7 @@ App::get('/v1/locale/countries')
->inject('response')
->inject('locale')
->action(function (Response $response, Locale $locale) {
$list = Config::getParam('locale-countries'); /* @var $list array */
$list = array_keys(Config::getParam('locale-countries')); /* @var $list array */
$output = [];
foreach ($list as $value) {
@@ -229,7 +229,7 @@ App::get('/v1/locale/continents')
->inject('response')
->inject('locale')
->action(function (Response $response, Locale $locale) {
$list = Config::getParam('locale-continents');
$list = array_keys(Config::getParam('locale-continents'));
foreach ($list as $value) {
$output[] = new Document([
+6 -6
View File
@@ -2936,7 +2936,7 @@ App::post('/v1/messaging/messages/email')
break;
case MessageStatus::SCHEDULED:
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => System::getEnv('_APP_REGION', 'default'),
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
@@ -3058,7 +3058,7 @@ App::post('/v1/messaging/messages/sms')
break;
case MessageStatus::SCHEDULED:
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => System::getEnv('_APP_REGION', 'default'),
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
@@ -3275,7 +3275,7 @@ App::post('/v1/messaging/messages/push')
break;
case MessageStatus::SCHEDULED:
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => System::getEnv('_APP_REGION', 'default'),
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
@@ -3661,7 +3661,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => System::getEnv('_APP_REGION', 'default'),
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
@@ -3862,7 +3862,7 @@ App::patch('/v1/messaging/messages/sms/:messageId')
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => System::getEnv('_APP_REGION', 'default'),
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
@@ -4035,7 +4035,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => System::getEnv('_APP_REGION', 'default'),
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
+100 -1
View File
@@ -1,5 +1,6 @@
<?php
use Appwrite\Auth\Auth;
use Appwrite\Event\Event;
use Appwrite\Event\Migration;
use Appwrite\Extend\Exception;
@@ -7,6 +8,7 @@ use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CompoundUID;
use Appwrite\Utopia\Database\Validator\Queries\Migrations;
use Appwrite\Utopia\Response;
use Utopia\App;
@@ -15,12 +17,18 @@ use Utopia\Database\Document;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Query\Cursor;
use Utopia\Database\Validator\UID;
use Utopia\Migration\Resource;
use Utopia\Migration\Sources\Appwrite;
use Utopia\Migration\Sources\CSV;
use Utopia\Migration\Sources\Firebase;
use Utopia\Migration\Sources\NHost;
use Utopia\Migration\Sources\Supabase;
use Utopia\Migration\Transfer;
use Utopia\Storage\Compression\Compression;
use Utopia\Storage\Device;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Integer;
use Utopia\Validator\Text;
@@ -89,7 +97,6 @@ App::post('/v1/migrations/appwrite')
->dynamic($migration, Response::MODEL_MIGRATION);
});
App::post('/v1/migrations/firebase')
->groups(['api', 'migrations'])
->desc('Migrate Firebase data')
@@ -290,6 +297,98 @@ App::post('/v1/migrations/nhost')
->dynamic($migration, Response::MODEL_MIGRATION);
});
App::post('/v1/migrations/csv')
->groups(['api', 'migrations'])
->desc('Import documents from a CSV')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
name: 'createCsvMigration',
description: '/docs/references/migrations/migration-csv.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_ACCEPTED,
model: Response::MODEL_MIGRATION,
)
]
))
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
->param('fileId', '', new UID(), 'File ID.')
->param('resourceId', null, new CompoundUID(), 'Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.')
->inject('response')
->inject('dbForProject')
->inject('project')
->inject('deviceForFiles')
->inject('deviceForImports')
->inject('queueForEvents')
->inject('queueForMigrations')
->action(function (string $bucketId, string $fileId, string $resourceId, Response $response, Database $dbForProject, Document $project, Device $deviceForFiles, Device $deviceForImports, Event $queueForEvents, Migration $queueForMigrations) {
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
if ($bucket->isEmpty() || (!$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
}
$path = $file->getAttribute('path', '');
if (!$deviceForFiles->exists($path)) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path);
}
if (!empty($file->getAttribute('openSSLCipher')) || $file->getAttribute('algorithm', Compression::NONE) !== Compression::NONE) {
throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED, "Only uncompressed, unencrypted CSV files can be used for document import.");
}
// copy to temporary folder
$migrationId = ID::unique();
$newPath = $deviceForImports->getPath('/' . $migrationId . '_' . $fileId . '.csv');
if (!$deviceForFiles->transfer($path, $newPath, $deviceForImports)) {
throw new \Exception("Unable to copy file");
}
$fileSize = $deviceForImports->getFileSize($path);
$resources = Transfer::extractServices([Transfer::GROUP_DATABASES]);
$migration = $dbForProject->createDocument('migrations', new Document([
'$id' => $migrationId,
'status' => 'pending',
'stage' => 'init',
'source' => CSV::getName(),
'destination' => Appwrite::getName(),
'resources' => $resources,
'resourceId' => $resourceId,
'resourceType' => Resource::TYPE_DATABASE,
'statusCounters' => [],
'resourceData' => [],
'errors' => [],
'options' => [
'path' => $newPath,
'size' => $fileSize,
],
]));
$queueForEvents->setParam('migrationId', $migration->getId());
$queueForMigrations
->setMigration($migration)
->setProject($project)
->trigger();
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
->dynamic($migration, Response::MODEL_MIGRATION);
});
App::get('/v1/migrations')
->groups(['api', 'migrations'])
->desc('List migrations')
+7 -7
View File
@@ -149,7 +149,7 @@ App::get('/v1/project/usage')
$executionsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -165,7 +165,7 @@ App::get('/v1/project/usage')
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -181,7 +181,7 @@ App::get('/v1/project/usage')
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -230,13 +230,13 @@ App::get('/v1/project/usage')
$functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE);
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE);
$deploymentValue = $dbForProject->findOne('stats', [
Query::equal('metric', [$deploymentMetric]),
Query::equal('period', ['inf'])
]);
$buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE);
$buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE);
$buildValue = $dbForProject->findOne('stats', [
Query::equal('metric', [$buildMetric]),
Query::equal('period', ['inf'])
@@ -254,7 +254,7 @@ App::get('/v1/project/usage')
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -270,7 +270,7 @@ App::get('/v1/project/usage')
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
+25 -6
View File
@@ -4,7 +4,7 @@ use Appwrite\Event\Certificate;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\Network\Validator\CNAME;
use Appwrite\Network\Validator\DNS;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
@@ -21,6 +21,8 @@ use Utopia\Database\Validator\UID;
use Utopia\Domains\Domain;
use Utopia\Logger\Log;
use Utopia\System\System;
use Utopia\Validator\AnyOf;
use Utopia\Validator\IP;
use Utopia\Validator\Text;
App::get('/v1/proxy/rules')
@@ -208,17 +210,27 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
throw new Exception(Exception::RULE_NOT_FOUND);
}
$target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', ''));
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if (!$targetCNAME->isKnown() || $targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
}
if (!$target->isKnown() || $target->isTest()) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Domain target must be configured as environment variable.');
if (empty($validators)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
}
if ($rule->getAttribute('verification') === true) {
return $response->dynamic($rule, Response::MODEL_PROXY_RULE);
}
$validator = new CNAME($target->get()); // Verify Domain with DNS records
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
$domain = new Domain($rule->getAttribute('domain', ''));
$validationStart = \microtime(true);
@@ -226,7 +238,14 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
$log->addTag('dnsDomain', $domain->get());
$error = $validator->getLogs();
$errors = [];
foreach ($validators as $validator) {
if (!empty($validator->getLogs())) {
$errors[] = $validator->getLogs();
}
}
$error = \implode("\n", $errors);
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
throw new Exception(Exception::RULE_VERIFICATION_FAILED);
+21 -3
View File
@@ -615,7 +615,10 @@ App::post('/v1/teams/:teamId/memberships')
$membership = ($isPrivilegedUser || $isAppUser) ?
Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) :
$dbForProject->createDocument('memberships', $membership);
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
if ($isPrivilegedUser || $isAppUser) {
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
}
} elseif ($membership->getAttribute('confirm') === false) {
$membership->setAttribute('secret', Auth::hash($secret));
@@ -1031,7 +1034,6 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->param('membershipId', '', new UID(), 'Membership ID.')
->param('roles', [], function (Document $project) {
if ($project->getId() === 'console') {
;
$roles = array_keys(Config::getParam('roles', []));
array_filter($roles, function ($role) {
return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]);
@@ -1043,9 +1045,10 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->inject('request')
->inject('response')
->inject('user')
->inject('project')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) {
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
@@ -1066,6 +1069,21 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
$isAppUser = Auth::isAppUser(Authorization::getRoles());
$isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');
if ($project->getId() === 'console') {
// Quick check: fetch up to 2 owners to determine if only one exists
$ownersCount = $dbForProject->count(
collection: 'memberships',
queries: [Query::contains('roles', ['owner'])],
max: 2
);
// Prevent role change if there's only one owner left,
// the requester is that owner, and the new `$roles` no longer include 'owner'!
if ($ownersCount === 1 && $isOwner && !\in_array('owner', $roles)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'There must be at least one owner in the organization.');
}
}
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to modify roles');
}
+18 -2
View File
@@ -21,6 +21,7 @@ use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Identities;
use Appwrite\Utopia\Database\Validator\Queries\Memberships;
use Appwrite\Utopia\Database\Validator\Queries\Targets;
use Appwrite\Utopia\Database\Validator\Queries\Users;
use Appwrite\Utopia\Request;
@@ -799,9 +800,11 @@ App::get('/v1/users/:userId/memberships')
]
))
->param('userId', '', new UID(), 'User ID.')
->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Memberships::ALLOWED_ATTRIBUTES), true)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $userId, Response $response, Database $dbForProject) {
->action(function (string $userId, array $queries, string $search, Response $response, Database $dbForProject) {
$user = $dbForProject->getDocument('users', $userId);
@@ -809,6 +812,19 @@ App::get('/v1/users/:userId/memberships')
throw new Exception(Exception::USER_NOT_FOUND);
}
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
if (!empty($search)) {
$queries[] = Query::search('search', $search);
}
// Set internal queries
$queries[] = Query::equal('userInternalId', [$user->getInternalId()]);
$memberships = array_map(function ($membership) use ($dbForProject, $user) {
$team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId'));
@@ -818,7 +834,7 @@ App::get('/v1/users/:userId/memberships')
->setAttribute('userEmail', $user->getAttribute('email'));
return $membership;
}, $user->getAttribute('memberships', []));
}, $dbForProject->find('memberships', $queries));
$response->dynamic(new Document([
'memberships' => $memberships,
+22 -7
View File
@@ -134,12 +134,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
$comment = new Comment();
$comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId));
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '', '');
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '');
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
} else {
$comment = new Comment();
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '', '');
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '');
$latestCommentId = \strval($github->createComment($owner, $repositoryName, $providerPullRequestId, $comment->generateComment()));
if (!empty($latestCommentId)) {
@@ -176,7 +176,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
$latestCommentId = $comment->getAttribute('providerCommentId', '');
$comment = new Comment();
$comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId));
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '', '');
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '');
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
}
@@ -219,7 +219,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
$commands[] = $resource->getAttribute('commands', '');
}
$deployment = $dbForProject->createDocument('deployments', new Document([
$deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([
'$id' => $deploymentId,
'$permissions' => [
Permission::read(Role::any()),
@@ -232,6 +232,8 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
'entrypoint' => $resource->getAttribute('entrypoint', ''),
'buildCommands' => \implode(' && ', $commands),
'buildOutput' => $resource->getAttribute('outputDirectory', ''),
'adapter' => $resource->getAttribute('adapter', ''),
'fallbackFile' => $resource->getAttribute('fallbackFile', ''),
'type' => 'vcs',
'installationId' => $installationId,
'installationInternalId' => $installationInternalId,
@@ -251,7 +253,14 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
'providerBranch' => $providerBranch,
'search' => implode(' ', [$deploymentId, $resource->getAttribute('entrypoint', '')]),
'activate' => $activate,
]));
])));
$resource = $resource
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource));
if ($resource->getCollection() === 'sites') {
$projectId = $project->getId();
@@ -277,6 +286,8 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
'status' => 'verified',
'certificateId' => '',
'search' => implode(' ', [$ruleId, $domain]),
'owner' => 'Appwrite',
'region' => $project->getAttribute('region')
]))
);
@@ -302,6 +313,8 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
'status' => 'verified',
'certificateId' => '',
'search' => implode(' ', [$ruleId, $domain]),
'owner' => 'Appwrite',
'region' => $project->getAttribute('region')
]))
);
} catch (Duplicate $err) {
@@ -331,6 +344,8 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
'status' => 'verified',
'certificateId' => '',
'search' => implode(' ', [$ruleId, $domain]),
'owner' => 'Appwrite',
'region' => $project->getAttribute('region')
]))
);
} catch (Duplicate $err) {
@@ -724,7 +739,7 @@ App::post('/v1/vcs/github/installations/:installationId/detections')
}
$frameworks = Config::getParam('frameworks');
if (!\in_array($framework, array_keys($frameworks), true)) {
if (!\in_array($framework, \array_keys($frameworks), true)) {
$framework = 'other';
}
$output->setAttribute('framework', $framework);
@@ -876,7 +891,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
}
$frameworks = Config::getParam('frameworks');
if (!\in_array($framework, array_keys($frameworks), true)) {
if (!\in_array($framework, \array_keys($frameworks), true)) {
$framework = 'other';
}
$repo['framework'] = $framework;
+179 -56
View File
@@ -56,10 +56,8 @@ Config::setParam('domainVerification', false);
Config::setParam('cookieDomain', 'localhost');
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey)
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey)
{
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
$host = $request->getHostname() ?? '';
if (!empty($previewHostname)) {
$host = $previewHostname;
@@ -77,24 +75,28 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
)[0] ?? new Document();
}
$errorView = __DIR__ . '/../views/general/error.phtml';
$url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', '');
if ($rule->isEmpty()) {
if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '') || $host === System::getEnv('_APP_DOMAIN_SITES', '')) {
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.');
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.', view: $errorView);
}
if (\str_ends_with($host, System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) || \str_ends_with($host, System::getEnv('_APP_DOMAIN_SITES', ''))) {
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain is not connected to any Appwrite resource yet. Please configure custom domain or function domain to allow this request.');
$exception = new AppwriteException(AppwriteException::RULE_NOT_FOUND, 'This domain is not connected to any Appwrite resources. Visit domains tab under function/site settings to configure it.', view: $errorView);
$exception->addCTA('Start with this domain', $url . '/console');
throw $exception;
}
if (System::getEnv('_APP_OPTIONS_ROUTER_PROTECTION', 'disabled') === 'enabled') {
if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL && $host !== System::getEnv('_APP_CONSOLE_DOMAIN', '')) {
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.');
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.', view: $errorView);
}
}
// Act as API - no Proxy logic
$utopia->getRoute()?->label('error', '');
return false;
}
@@ -114,7 +116,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
if (array_key_exists('proxy', $project->getAttribute('services', []))) {
$status = $project->getAttribute('services', [])['proxy'];
if (!$status) {
throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED);
throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED, view: $errorView);
}
}
@@ -127,10 +129,10 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$type = $rule->getAttribute('type', '');
if ($type === 'deployment') {
if (System::getEnv('_APP_OPTIONS_COMPUTE_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
if (System::getEnv('_APP_OPTIONS_ROUTER_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
if ($request->getProtocol() !== 'https' && $request->getHostname() !== APP_HOSTNAME_INTERNAL) {
if ($request->getMethod() !== Request::METHOD_GET) {
throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP. Please use HTTPS instead.');
throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP. Please use HTTPS instead.', view: $errorView);
}
return $response->redirect('https://' . $request->getHostname() . $request->getURI());
}
@@ -139,6 +141,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
/** @var Database $dbForProject */
$dbForProject = $getProjectDB($project);
/** @var Document $deployment */
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId')));
if ($deployment->getAttribute('resourceType', '') === 'functions') {
@@ -147,6 +150,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$type = 'site';
}
if ($deployment->isEmpty()) {
$resourceType = $rule->getAttribute('deploymentResourceType', '');
$resourceId = $rule->getAttribute('deploymentResourceId', '');
$type = ($resourceType === 'site') ? 'sites' : 'functions';
$exception = new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, view: $errorView);
$exception->addCTA('View deployments', $url . '/console/project-' . $projectId . '/' . $type . '/' . $resourceType . '-' . $resourceId);
throw $exception;
}
$resource = $type === 'function' ?
Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) :
Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', '')));
@@ -239,11 +251,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$requestHeaders = $request->getHeaders();
if ($resource->isEmpty() || !$resource->getAttribute('enabled')) {
throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND);
if ($type === 'functions') {
throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND, view: $errorView);
} else {
throw new AppwriteException(AppwriteException::SITE_NOT_FOUND, view: $errorView);
}
}
if ($isResourceBlocked($project, $type === 'function' ? RESOURCE_TYPE_FUNCTIONS : RESOURCE_TYPE_SITES, $resource->getId())) {
throw new AppwriteException(AppwriteException::GENERAL_RESOURCE_BLOCKED);
throw new AppwriteException(AppwriteException::GENERAL_RESOURCE_BLOCKED, view: $errorView);
}
$version = match ($type) {
@@ -261,22 +277,45 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
};
// Static site enforced runtime
if ($resource->getAttribute('adapter', '') === 'static') {
if ($deployment->getAttribute('adapter', '') === 'static') {
$runtime = $runtimes['static-1'] ?? null;
}
if (\is_null($runtime)) {
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', view: $errorView);
}
if ($deployment->getAttribute('status') !== 'ready') {
throw new AppwriteException(AppwriteException::BUILD_NOT_READY);
$allowAnyStatus = !\is_null($apiKey) && $apiKey->isDeploymentStatusIgnored();
if (!$allowAnyStatus && $deployment->getAttribute('status') !== 'ready') {
$status = $deployment->getAttribute('status');
switch ($status) {
case 'failed':
$exception = new AppwriteException(AppwriteException::BUILD_FAILED, view: $errorView);
$ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId();
$exception->addCTA('View logs', $url . $ctaUrl);
break;
case 'canceled':
$exception = new AppwriteException(AppwriteException::BUILD_CANCELED, view: $errorView);
$ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments';
$exception->addCTA('View deployments', $url . $ctaUrl);
break;
default:
$exception = new AppwriteException(AppwriteException::BUILD_NOT_READY, view: $errorView);
$ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId();
$exception->addCTA('Reload', '/');
$exception->addCTA('View logs', $url . $ctaUrl);
break;
}
throw $exception;
}
if ($type === 'function') {
$permissions = $resource->getAttribute('execute');
if (!(\in_array('any', $permissions)) && !(\in_array('guests', $permissions))) {
throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"');
$exception = new AppwriteException(AppwriteException::FUNCTION_EXECUTE_PERMISSION_MISSING, view: $errorView);
$exception->addCTA('View settings', $url . '/console/project-' . $project->getId() . '/functions/function-' . $resource->getId() . '/settings');
throw $exception;
}
}
@@ -410,12 +449,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
]);
// SPA fallbackFile override
if ($resource->getAttribute('adapter', '') === 'static' && $resource->getAttribute('fallbackFile', '') !== '') {
$vars['OPEN_RUNTIMES_STATIC_FALLBACK'] = $resource->getAttribute('fallbackFile', '');
if ($deployment->getAttribute('adapter', '') === 'static' && $deployment->getAttribute('fallbackFile', '') !== '') {
$vars['OPEN_RUNTIMES_STATIC_FALLBACK'] = $deployment->getAttribute('fallbackFile', '');
}
/** Execute function */
$executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST'));
try {
$version = match ($type) {
'function' => $resource->getAttribute('version', 'v2'),
@@ -438,7 +476,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$startCommand = $runtime['startCommand'];
if (!is_null($framework)) {
$adapter = ($framework['adapters'] ?? [])[$resource->getAttribute('adapter', '')] ?? null;
$adapter = ($framework['adapters'] ?? [])[$deployment->getAttribute('adapter', '')] ?? null;
if (!is_null($adapter) && isset($adapter['startCommand'])) {
$startCommand = $adapter['startCommand'];
}
@@ -473,29 +511,51 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
);
// Branded 404 override
if ($executionResponse['statusCode'] === 404 && $resource->getAttribute('adapter', '') === 'static') {
$isResponseBranded = false;
if ($executionResponse['statusCode'] === 404 && $deployment->getAttribute('adapter', '') === 'static') {
$layout = new View(__DIR__ . '/../views/general/404.phtml');
$executionResponse['body'] = $layout->render();
$executionResponse['headers']['content-length'] = \strlen($executionResponse['body']);
$isResponseBranded = true;
}
// Branded banner for previews
if (\is_null($apiKey) || $apiKey->isBannerDisabled() === false) {
$transformation = new Transformation();
$transformation->addAdapter(new Preview());
$transformation->setInput($executionResponse['body']);
$transformation->setTraits($executionResponse['headers']);
if ($isPreview && $transformation->transform()) {
$executionResponse['body'] = $transformation->getOutput();
if (!$isResponseBranded) {
if (\is_null($apiKey) || $apiKey->isBannerDisabled() === false) {
$transformation = new Transformation();
$transformation->addAdapter(new Preview());
$transformation->setInput($executionResponse['body']);
$transformation->setTraits($executionResponse['headers']);
if ($isPreview && $transformation->transform()) {
$executionResponse['body'] = $transformation->getOutput();
foreach ($executionResponse['headers'] as $key => $value) {
if (\strtolower($key) === 'content-length') {
$executionResponse['headers'][$key] = \strlen($executionResponse['body']);
foreach ($executionResponse['headers'] as $key => $value) {
if (\strtolower($key) === 'content-length') {
$executionResponse['headers'][$key] = \strlen($executionResponse['body']);
}
}
}
}
}
// Branded error pages (when developer left body empty)
if ($executionResponse['statusCode'] >= 400 && empty($executionResponse['body'])) {
$layout = new View($errorView);
$layout
->setParam('title', $project->getAttribute('name') . ' - Error')
->setParam('type', 'proxy_error_override')
->setParam('code', $executionResponse['statusCode']);
$executionResponse['body'] = $layout->render();
foreach ($executionResponse['headers'] as $key => $value) {
if (\strtolower($key) === 'content-length') {
$executionResponse['headers'][$key] = \strlen($executionResponse['body']);
} elseif (\strtolower($key) === 'content-type') {
$executionResponse['headers'][$key] = 'text/html';
}
}
}
$headersFiltered = [];
foreach ($executionResponse['headers'] as $key => $value) {
if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) {
@@ -577,22 +637,67 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size'];
}
if (!empty($apiKey) && !empty($apiKey->getDisabledMetrics())) {
foreach ($apiKey->getDisabledMetrics() as $key) {
$queueForStatsUsage->disableMetric($key);
}
}
$metricTypeExecutions = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS);
$metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
$metricTypeExecutionsCompute = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE);
$metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE);
$metricTypeExecutionsMbSeconds = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS);
$metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
if ($deployment->getAttribute('resourceType') === 'sites') {
$queueForStatsUsage
->disableMetric(METRIC_NETWORK_REQUESTS)
->disableMetric(METRIC_NETWORK_INBOUND)
->disableMetric(METRIC_NETWORK_OUTBOUND);
if ($resource->getAttribute('adapter') !== 'ssr') {
$queueForStatsUsage
->disableMetric(METRIC_EXECUTIONS)
->disableMetric(METRIC_EXECUTIONS_COMPUTE)
->disableMetric(METRIC_EXECUTIONS_MB_SECONDS)
->disableMetric($metricTypeExecutions)
->disableMetric($metricTypeIdExecutions)
->disableMetric($metricTypeExecutionsCompute)
->disableMetric($metricTypeIdExecutionsCompute)
->disableMetric($metricTypeExecutionsMbSeconds)
->disableMetric($metricTypeIdExecutionsMBSeconds);
}
$queueForStatsUsage
->addMetric(METRIC_SITES_REQUESTS, 1)
->addMetric(METRIC_SITES_INBOUND, $request->getSize() + $fileSize)
->addMetric(METRIC_SITES_OUTBOUND, $response->getSize())
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_REQUESTS), 1)
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize)
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_OUTBOUND), $response->getSize())
;
}
$compute = (int)($execution->getAttribute('duration') * 1000);
$mbSeconds = (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT));
$queueForStatsUsage
->addMetric(METRIC_NETWORK_REQUESTS, 1)
->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize)
->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize())
->addMetric(METRIC_EXECUTIONS, 1)
->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1)
->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project
->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function
->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT)))
->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT)))
->addMetric($metricTypeExecutions, 1)
->addMetric($metricTypeIdExecutions, 1)
->addMetric(METRIC_EXECUTIONS_COMPUTE, $compute) // per project
->addMetric($metricTypeExecutionsCompute, $compute) // per function
->addMetric($metricTypeIdExecutionsCompute, $compute) // per function
->addMetric(METRIC_EXECUTIONS_MB_SECONDS, $mbSeconds)
->addMetric($metricTypeExecutionsMbSeconds, $mbSeconds)
->addMetric($metricTypeIdExecutionsMBSeconds, $mbSeconds)
->setProject($project)
->trigger();
return true;
} elseif ($type === 'api') {
$utopia->getRoute()?->label('error', '');
return false;
} elseif ($type === 'redirect') {
$url = $rule->getAttribute('redirectUrl', '');
@@ -605,10 +710,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$response->redirect($url, \intval($rule->getAttribute('redirectStatusCode', 301)));
return true;
} else {
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Unknown resource type ' . $type);
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Unknown resource type ' . $type, view: $errorView);
}
$utopia->getRoute()?->label('error', '');
return false;
}
@@ -653,10 +757,11 @@ App::init()
->inject('queueForEvents')
->inject('queueForCertificates')
->inject('queueForFunctions')
->inject('executor')
->inject('isResourceBlocked')
->inject('previewHostname')
->inject('apiKey')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
/*
* Appwrite Router
*/
@@ -664,7 +769,7 @@ App::init()
$mainDomain = System::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain || !empty($previewHostname)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
$utopia->getRoute()?->label('router', true);
}
}
@@ -736,6 +841,12 @@ App::init()
]);
}
$owner = '';
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
if (!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) {
$owner = 'Appwrite';
}
if ($domainDocument->isEmpty()) {
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
$domainDocument = new Document([
@@ -744,9 +855,11 @@ App::init()
'domain' => $domain->get(),
'type' => 'api',
'status' => 'verifying',
'projectId' => 'console',
'projectInternalId' => 'console',
'projectId' => $console->getId(),
'projectInternalId' => $console->getInternalId(),
'search' => implode(' ', [$ruleId, $domain->get()]),
'owner' => $owner,
'region' => $console->getAttribute('region')
]);
$domainDocument = $dbForPlatform->createDocument('rules', $domainDocument);
@@ -909,12 +1022,13 @@ App::options()
->inject('queueForEvents')
->inject('queueForStatsUsage')
->inject('queueForFunctions')
->inject('executor')
->inject('geodb')
->inject('isResourceBlocked')
->inject('previewHostname')
->inject('project')
->inject('apiKey')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, ?Key $apiKey) {
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, ?Key $apiKey) {
/*
* Appwrite Router
*/
@@ -922,7 +1036,7 @@ App::options()
$mainDomain = System::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain || !empty($previewHostname)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
$utopia->getRoute()?->label('router', true);
}
}
@@ -1039,17 +1153,18 @@ App::error()
if (!empty($providerConfig) && $error->getCode() >= 400 && $error->getCode() < 500) {
// Register error logger
try {
$loggingProvider = new DSN($providerConfig ?? '');
$loggingProvider = new DSN($providerConfig);
$providerName = $loggingProvider->getScheme();
if (!empty($providerName) && $providerName === 'sentry') {
$key = $loggingProvider->getPassword();
$projectId = $loggingProvider->getUser() ?? '';
$host = 'https://' . $loggingProvider->getHost();
$sampleRate = $loggingProvider->getParam('sample', 0.01);
$adapter = new Sentry($projectId, $key, $host);
$logger = new Logger($adapter);
$logger->setSample(0.01);
$logger->setSample($sampleRate);
$publish = true;
} else {
throw new \Exception('Invalid experimental logging provider');
@@ -1192,9 +1307,14 @@ App::error()
->addHeader('Pragma', 'no-cache')
->setStatusCode($code);
$template = ($route) ? $route->getLabel('error', null) : null;
$template = $error->getView() ?? (($route) ? $route->getLabel('error', null) : null);
if ($template) {
// TODO: Ideally use group 'api' here, but all wildcard routes seem to have 'api' at the moment
if (!\str_starts_with($route->getPath(), '/v1')) {
$template = __DIR__ . '/../views/general/error.phtml';
}
if (!empty($template)) {
$layout = new View($template);
$layout
@@ -1205,7 +1325,8 @@ App::error()
->setParam('message', $output['message'] ?? '')
->setParam('type', $output['type'] ?? '')
->setParam('code', $output['code'] ?? '')
->setParam('trace', $output['trace'] ?? []);
->setParam('trace', $output['trace'] ?? [])
->setParam('exception', $error);
$response->html($layout->render());
return;
@@ -1230,11 +1351,12 @@ App::get('/robots.txt')
->inject('queueForEvents')
->inject('queueForStatsUsage')
->inject('queueForFunctions')
->inject('executor')
->inject('geodb')
->inject('isResourceBlocked')
->inject('previewHostname')
->inject('apiKey')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
$host = $request->getHostname() ?? '';
$mainDomain = System::getEnv('_APP_DOMAIN', '');
@@ -1242,7 +1364,7 @@ App::get('/robots.txt')
$template = new View(__DIR__ . '/../views/general/robots.phtml');
$response->text($template->render(false));
} else {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
$utopia->getRoute()?->label('router', true);
}
}
@@ -1261,11 +1383,12 @@ App::get('/humans.txt')
->inject('queueForEvents')
->inject('queueForStatsUsage')
->inject('queueForFunctions')
->inject('executor')
->inject('geodb')
->inject('isResourceBlocked')
->inject('previewHostname')
->inject('apiKey')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
$host = $request->getHostname() ?? '';
$mainDomain = System::getEnv('_APP_DOMAIN', '');
@@ -1273,7 +1396,7 @@ App::get('/humans.txt')
$template = new View(__DIR__ . '/../views/general/humans.phtml');
$response->text($template->render(false));
} else {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
$utopia->getRoute()?->label('router', true);
}
}
+15 -6
View File
@@ -175,8 +175,10 @@ $usageDatabaseListener = function (string $event, Document $document, StatsUsage
$queueForStatsUsage
->addMetric(METRIC_DEPLOYMENTS, $value) // per project
->addMetric(METRIC_DEPLOYMENTS_STORAGE, $document->getAttribute('size') * $value) // per project
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS), $value) // per function
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value);
->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS), $value) // per function
->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value)
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $value) // per function
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value);
break;
default:
break;
@@ -399,7 +401,8 @@ App::init()
->inject('timelimit')
->inject('mode')
->inject('apiKey')
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, string $mode, ?Key $apiKey) use ($usageDatabaseListener, $eventDatabaseListener) {
->inject('plan')
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, string $mode, ?Key $apiKey, array $plan) use ($usageDatabaseListener, $eventDatabaseListener) {
$route = $utopia->getRoute();
@@ -529,6 +532,10 @@ App::init()
$useCache = $route->getLabel('cache', false);
if ($useCache) {
$route = $utopia->match($request);
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser(Authorization::getRoles());
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
$cache = new Cache(
@@ -541,7 +548,7 @@ App::init()
$parts = explode('/', $cacheLog->getAttribute('resourceType'));
$type = $parts[0] ?? null;
if ($type === 'bucket') {
if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) {
$bucketId = $parts[1] ?? null;
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -582,8 +589,10 @@ App::init()
$response
->addHeader('Cache-Control', sprintf('private, max-age=%d', $timestamp))
->addHeader('X-Appwrite-Cache', 'hit')
->setContentType($cacheLog->getAttribute('mimeType'))
->send($data);
->setContentType($cacheLog->getAttribute('mimeType'));
if (!$isImageTransformation || !$isDisabled) {
$response->send($data);
}
} else {
$response
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
+9 -1925
View File
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
<?php
use Utopia\Config\Config;
Config::load('template-runtimes', __DIR__ . '/../config/template-runtimes.php');
Config::load('events', __DIR__ . '/../config/events.php');
Config::load('auth', __DIR__ . '/../config/auth.php');
Config::load('apis', __DIR__ . '/../config/apis.php'); // List of APIs
Config::load('errors', __DIR__ . '/../config/errors.php');
Config::load('oAuthProviders', __DIR__ . '/../config/oAuthProviders.php');
Config::load('platforms', __DIR__ . '/../config/platforms.php');
Config::load('console', __DIR__ . '/../config/console.php');
Config::load('collections', __DIR__ . '/../config/collections.php');
Config::load('frameworks', __DIR__ . '/../config/frameworks.php');
Config::load('runtimes', __DIR__ . '/../config/runtimes.php');
Config::load('runtimes-v2', __DIR__ . '/../config/runtimes-v2.php');
Config::load('usage', __DIR__ . '/../config/usage.php');
Config::load('roles', __DIR__ . '/../config/roles.php'); // User roles and scopes
Config::load('scopes', __DIR__ . '/../config/scopes.php'); // User roles and scopes
Config::load('services', __DIR__ . '/../config/services.php'); // List of services
Config::load('variables', __DIR__ . '/../config/variables.php'); // List of env variables
Config::load('regions', __DIR__ . '/../config/regions.php'); // List of available regions
Config::load('avatar-browsers', __DIR__ . '/../config/avatars/browsers.php');
Config::load('avatar-credit-cards', __DIR__ . '/../config/avatars/credit-cards.php');
Config::load('avatar-flags', __DIR__ . '/../config/avatars/flags.php');
Config::load('locale-codes', __DIR__ . '/../config/locale/codes.php');
Config::load('locale-currencies', __DIR__ . '/../config/locale/currencies.php');
Config::load('locale-eu', __DIR__ . '/../config/locale/eu.php');
Config::load('locale-languages', __DIR__ . '/../config/locale/languages.php');
Config::load('locale-phones', __DIR__ . '/../config/locale/phones.php');
Config::load('locale-countries', __DIR__ . '/../config/locale/countries.php');
Config::load('locale-continents', __DIR__ . '/../config/locale/continents.php');
Config::load('locale-templates', __DIR__ . '/../config/locale/templates.php');
Config::load('storage-logos', __DIR__ . '/../config/storage/logos.php');
Config::load('storage-mimes', __DIR__ . '/../config/storage/mimes.php');
Config::load('storage-inputs', __DIR__ . '/../config/storage/inputs.php');
Config::load('storage-outputs', __DIR__ . '/../config/storage/outputs.php');
Config::load('specifications', __DIR__ . '/../config/specifications.php');
Config::load('templates-function', __DIR__ . '/../config/templates/function.php');
Config::load('templates-site', __DIR__ . '/../config/templates/site.php');
+259
View File
@@ -0,0 +1,259 @@
<?php
use Appwrite\Platform\Modules\Compute\Specification;
const APP_NAME = 'Appwrite';
const APP_DOMAIN = 'appwrite.io';
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
const APP_EMAIL_SECURITY = ''; // Default security email address
const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s';
const APP_MODE_DEFAULT = 'default';
const APP_MODE_ADMIN = 'admin';
const APP_PAGING_LIMIT = 12;
const APP_LIMIT_COUNT = 5000;
const APP_LIMIT_USERS = 10_000;
const APP_LIMIT_USER_PASSWORD_HISTORY = 20;
const APP_LIMIT_USER_SESSIONS_MAX = 100;
const APP_LIMIT_USER_SESSIONS_DEFAULT = 10;
const APP_LIMIT_ANTIVIRUS = 20_000_000; //20MB
const APP_LIMIT_ENCRYPTION = 20_000_000; //20MB
const APP_LIMIT_COMPRESSION = 20_000_000; //20MB
const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value
const APP_LIMIT_ARRAY_LABELS_SIZE = 1000; // Default maximum of how many labels elements can there be in API parameter that expects array value
const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length.
const APP_LIMIT_SUBQUERY = 1000;
const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000;
const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate period
const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate period in seconds
const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return in list API calls
const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours
const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours
const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours
const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
const APP_CACHE_BUSTER = 4318;
const APP_VERSION_STABLE = '1.7.0';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
const APP_DATABASE_ATTRIBUTE_DATETIME = 'datetime';
const APP_DATABASE_ATTRIBUTE_URL = 'url';
const APP_DATABASE_ATTRIBUTE_INT_RANGE = 'intRange';
const APP_DATABASE_ATTRIBUTE_FLOAT_RANGE = 'floatRange';
const APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH = 1_073_741_824; // 2^32 bits / 4 bits per char
const APP_DATABASE_TIMEOUT_MILLISECONDS_API = 15 * 1000; // 15 seconds
const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes
const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes
const APP_DATABASE_QUERY_MAX_VALUES = 500;
const APP_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_SITES = '/storage/sites';
const APP_STORAGE_FUNCTIONS = '/storage/functions';
const APP_STORAGE_BUILDS = '/storage/builds';
const APP_STORAGE_CACHE = '/storage/cache';
const APP_STORAGE_IMPORTS = '/storage/imports'; // Temporary storage for csv imports
const APP_STORAGE_CERTIFICATES = '/storage/certificates';
const APP_STORAGE_CONFIG = '/storage/config';
const APP_STORAGE_READ_BUFFER = 20 * (1000 * 1000); //20MB other names `APP_STORAGE_MEMORY_LIMIT`, `APP_STORAGE_MEMORY_BUFFER`, `APP_STORAGE_READ_LIMIT`, `APP_STORAGE_BUFFER_LIMIT`
const APP_SOCIAL_TWITTER = 'https://twitter.com/appwrite';
const APP_SOCIAL_TWITTER_HANDLE = 'appwrite';
const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io';
const APP_SOCIAL_LINKEDIN = 'https://www.linkedin.com/company/appwrite';
const APP_SOCIAL_INSTAGRAM = 'https://www.instagram.com/appwrite.io';
const APP_SOCIAL_GITHUB = 'https://github.com/appwrite';
const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord';
const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244';
const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite';
const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1';
const APP_HOSTNAME_INTERNAL = 'appwrite';
const APP_COMPUTE_CPUS_DEFAULT = 0.5;
const APP_COMPUTE_MEMORY_DEFAULT = 512;
const APP_COMPUTE_SPECIFICATION_DEFAULT = Specification::S_1VCPU_512MB;
const APP_PLATFORM_SERVER = 'server';
const APP_PLATFORM_CLIENT = 'client';
const APP_PLATFORM_CONSOLE = 'console';
// Database Reconnect
const DATABASE_RECONNECT_SLEEP = 2;
const DATABASE_RECONNECT_MAX_ATTEMPTS = 10;
// Database Worker Types
const DATABASE_TYPE_CREATE_ATTRIBUTE = 'createAttribute';
const DATABASE_TYPE_CREATE_INDEX = 'createIndex';
const DATABASE_TYPE_DELETE_ATTRIBUTE = 'deleteAttribute';
const DATABASE_TYPE_DELETE_INDEX = 'deleteIndex';
const DATABASE_TYPE_DELETE_COLLECTION = 'deleteCollection';
const DATABASE_TYPE_DELETE_DATABASE = 'deleteDatabase';
// Build Worker Types
const BUILD_TYPE_DEPLOYMENT = 'deployment';
const BUILD_TYPE_RETRY = 'retry';
// Deletion Types
const DELETE_TYPE_DATABASES = 'databases';
const DELETE_TYPE_DOCUMENT = 'document';
const DELETE_TYPE_COLLECTIONS = 'collections';
const DELETE_TYPE_PROJECTS = 'projects';
const DELETE_TYPE_SITES = 'sites';
const DELETE_TYPE_FUNCTIONS = 'functions';
const DELETE_TYPE_DEPLOYMENTS = 'deployments';
const DELETE_TYPE_USERS = 'users';
const DELETE_TYPE_TEAM_PROJECTS = 'teams_projects';
const DELETE_TYPE_EXECUTIONS = 'executions';
const DELETE_TYPE_AUDIT = 'audit';
const DELETE_TYPE_ABUSE = 'abuse';
const DELETE_TYPE_USAGE = 'usage';
const DELETE_TYPE_REALTIME = 'realtime';
const DELETE_TYPE_BUCKETS = 'buckets';
const DELETE_TYPE_INSTALLATIONS = 'installations';
const DELETE_TYPE_RULES = 'rules';
const DELETE_TYPE_SESSIONS = 'sessions';
const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp';
const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource';
const DELETE_TYPE_SCHEDULES = 'schedules';
const DELETE_TYPE_TOPIC = 'topic';
const DELETE_TYPE_TARGET = 'target';
const DELETE_TYPE_EXPIRED_TARGETS = 'invalid_targets';
const DELETE_TYPE_SESSION_TARGETS = 'session_targets';
const DELETE_TYPE_MAINTENANCE = 'maintenance';
// Message types
const MESSAGE_SEND_TYPE_INTERNAL = 'internal';
const MESSAGE_SEND_TYPE_EXTERNAL = 'external';
// Mail Types
const MAIL_TYPE_VERIFICATION = 'verification';
const MAIL_TYPE_MAGIC_SESSION = 'magicSession';
const MAIL_TYPE_RECOVERY = 'recovery';
const MAIL_TYPE_INVITATION = 'invitation';
const MAIL_TYPE_CERTIFICATE = 'certificate';
// Auth Types
const APP_AUTH_TYPE_SESSION = 'Session';
const APP_AUTH_TYPE_JWT = 'JWT';
const APP_AUTH_TYPE_KEY = 'Key';
const APP_AUTH_TYPE_ADMIN = 'Admin';
// Response related
const MAX_OUTPUT_CHUNK_SIZE = 10 * 1024 * 1024; // 10MB
// Function headers
const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host'];
const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length'];
// Message types
const MESSAGE_TYPE_EMAIL = 'email';
const MESSAGE_TYPE_SMS = 'sms';
const MESSAGE_TYPE_PUSH = 'push';
// API key types
const API_KEY_STANDARD = 'standard';
const API_KEY_DYNAMIC = 'dynamic';
// Usage metrics
const METRIC_TEAMS = 'teams';
const METRIC_USERS = 'users';
const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent';
const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed';
const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent';
const METRIC_WEBHOOK_ID_FAILED = '{webhookInternalId}.webhooks.events.failed';
const METRIC_AUTH_METHOD_PHONE = 'auth.method.phone';
const METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE = METRIC_AUTH_METHOD_PHONE . '.{countryCode}';
const METRIC_MESSAGES = 'messages';
const METRIC_MESSAGES_SENT = METRIC_MESSAGES . '.sent';
const METRIC_MESSAGES_FAILED = METRIC_MESSAGES . '.failed';
const METRIC_MESSAGES_TYPE = METRIC_MESSAGES . '.{type}';
const METRIC_MESSAGES_TYPE_SENT = METRIC_MESSAGES . '.{type}.sent';
const METRIC_MESSAGES_TYPE_FAILED = METRIC_MESSAGES . '.{type}.failed';
const METRIC_MESSAGES_TYPE_PROVIDER = METRIC_MESSAGES . '.{type}.{provider}';
const METRIC_MESSAGES_TYPE_PROVIDER_SENT = METRIC_MESSAGES . '.{type}.{provider}.sent';
const METRIC_MESSAGES_TYPE_PROVIDER_FAILED = METRIC_MESSAGES . '.{type}.{provider}.failed';
const METRIC_SESSIONS = 'sessions';
const METRIC_DATABASES = 'databases';
const METRIC_COLLECTIONS = 'collections';
const METRIC_DATABASES_STORAGE = 'databases.storage';
const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections';
const METRIC_DATABASE_ID_STORAGE = '{databaseInternalId}.databases.storage';
const METRIC_DOCUMENTS = 'documents';
const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage';
const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads';
const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads';
const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes';
const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes';
const METRIC_BUCKETS = 'buckets';
const METRIC_FILES = 'files';
const METRIC_FILES_STORAGE = 'files.storage';
const METRIC_FILES_TRANSFORMATIONS = 'files.transformations';
const METRIC_BUCKET_ID_FILES_TRANSFORMATIONS = '{bucketInternalId}.files.transformations';
const METRIC_FILES_IMAGES_TRANSFORMED = 'files.imagesTransformed';
const METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED = '{bucketInternalId}.files.imagesTransformed';
const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files';
const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage';
const METRIC_SITES = 'sites';
const METRIC_FUNCTIONS = 'functions';
const METRIC_DEPLOYMENTS = 'deployments';
const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage';
const METRIC_BUILDS = 'builds';
const METRIC_BUILDS_SUCCESS = 'builds.success';
const METRIC_BUILDS_FAILED = 'builds.failed';
const METRIC_BUILDS_STORAGE = 'builds.storage';
const METRIC_BUILDS_COMPUTE = 'builds.compute';
const METRIC_BUILDS_COMPUTE_SUCCESS = 'builds.compute.success';
const METRIC_BUILDS_COMPUTE_FAILED = 'builds.compute.failed';
const METRIC_BUILDS_MB_SECONDS = 'builds.mbSeconds';
const METRIC_EXECUTIONS = 'executions';
const METRIC_EXECUTIONS_COMPUTE = 'executions.compute';
const METRIC_EXECUTIONS_MB_SECONDS = 'executions.mbSeconds';
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS = '{resourceType}.{resourceInternalId}.executions';
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE = '{resourceType}.{resourceInternalId}.executions.compute';
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS = '{resourceType}.{resourceInternalId}.executions.mbSeconds';
const METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS = '{resourceType}.{resourceInternalId}.builds.success';
const METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED = '{resourceType}.{resourceInternalId}.builds.failed';
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE = '{resourceType}.{resourceInternalId}.builds.compute';
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS = '{resourceType}.{resourceInternalId}.builds.compute.success';
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED = '{resourceType}.{resourceInternalId}.builds.compute.failed';
const METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS = '{resourceType}.{resourceInternalId}.builds.mbSeconds';
const METRIC_RESOURCE_TYPE_ID_BUILDS = '{resourceType}.{resourceInternalId}.builds';
const METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE = '{resourceType}.{resourceInternalId}.builds.storage';
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
const METRIC_RESOURCE_TYPE_EXECUTIONS = '{resourceType}.executions';
const METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE = '{resourceType}.executions.compute';
const METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS = '{resourceType}.executions.mbSeconds';
const METRIC_RESOURCE_TYPE_BUILDS_SUCCESS = '{resourceType}.builds.success';
const METRIC_RESOURCE_TYPE_BUILDS_FAILED = '{resourceType}.builds.failed';
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE = '{resourceType}.builds.compute';
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS = '{resourceType}.builds.compute.success';
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED = '{resourceType}.builds.compute.failed';
const METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS = '{resourceType}.builds.mbSeconds';
const METRIC_RESOURCE_TYPE_BUILDS = '{resourceType}.builds';
const METRIC_RESOURCE_TYPE_BUILDS_STORAGE = '{resourceType}.builds.storage';
const METRIC_RESOURCE_TYPE_DEPLOYMENTS = '{resourceType}.deployments';
const METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE = '{resourceType}.deployments.storage';
const METRIC_NETWORK_REQUESTS = 'network.requests';
const METRIC_NETWORK_INBOUND = 'network.inbound';
const METRIC_NETWORK_OUTBOUND = 'network.outbound';
const METRIC_MAU = 'users.mau';
const METRIC_DAU = 'users.dau';
const METRIC_WAU = 'users.wau';
const METRIC_WEBHOOKS = 'webhooks';
const METRIC_PLATFORMS = 'platforms';
const METRIC_PROVIDERS = 'providers';
const METRIC_TOPICS = 'topics';
const METRIC_TARGETS = 'targets';
const METRIC_PROVIDER_TYPE_TARGETS = '{providerType}.targets';
const METRIC_KEYS = 'keys';
const METRIC_DOMAINS = 'domains';
const METRIC_SITES_REQUESTS = 'sites.requests';
const METRIC_SITES_INBOUND = 'sites.inbound';
const METRIC_SITES_OUTBOUND = 'sites.outbound';
const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests';
const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound';
const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound';
// Resource types
const RESOURCE_TYPE_PROJECTS = 'projects';
const RESOURCE_TYPE_FUNCTIONS = 'functions';
const RESOURCE_TYPE_SITES = 'sites';
const RESOURCE_TYPE_DATABASES = 'databases';
const RESOURCE_TYPE_BUCKETS = 'buckets';
const RESOURCE_TYPE_PROVIDERS = 'providers';
const RESOURCE_TYPE_TOPICS = 'topics';
const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers';
const RESOURCE_TYPE_MESSAGES = 'messages';
+404
View File
@@ -0,0 +1,404 @@
<?php
use Appwrite\OpenSSL\OpenSSL;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\System\System;
Database::addFilter(
'casting',
function (mixed $value) {
return json_encode(['value' => $value], JSON_PRESERVE_ZERO_FRACTION);
},
function (mixed $value) {
if (is_null($value)) {
return;
}
return json_decode($value, true)['value'];
}
);
Database::addFilter(
'enum',
function (mixed $value, Document $attribute) {
if ($attribute->isSet('elements')) {
$attribute->removeAttribute('elements');
}
return $value;
},
function (mixed $value, Document $attribute) {
$formatOptions = \json_decode($attribute->getAttribute('formatOptions', '[]'), true);
if (isset($formatOptions['elements'])) {
$attribute->setAttribute('elements', $formatOptions['elements']);
}
return $value;
}
);
Database::addFilter(
'range',
function (mixed $value, Document $attribute) {
if ($attribute->isSet('min')) {
$attribute->removeAttribute('min');
}
if ($attribute->isSet('max')) {
$attribute->removeAttribute('max');
}
return $value;
},
function (mixed $value, Document $attribute) {
$formatOptions = json_decode($attribute->getAttribute('formatOptions', '[]'), true);
if (isset($formatOptions['min']) || isset($formatOptions['max'])) {
$attribute
->setAttribute('min', $formatOptions['min'])
->setAttribute('max', $formatOptions['max']);
}
return $value;
}
);
Database::addFilter(
'subQueryAttributes',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
$attributes = $database->find('attributes', [
Query::equal('collectionInternalId', [$document->getInternalId()]),
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
Query::limit($database->getLimitForAttributes()),
]);
foreach ($attributes as $attribute) {
if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) {
$options = $attribute->getAttribute('options');
foreach ($options as $key => $value) {
$attribute->setAttribute($key, $value);
}
$attribute->removeAttribute('options');
}
}
return $attributes;
}
);
Database::addFilter(
'subQueryIndexes',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return $database
->find('indexes', [
Query::equal('collectionInternalId', [$document->getInternalId()]),
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
Query::limit($database->getLimitForIndexes()),
]);
}
);
Database::addFilter(
'subQueryPlatforms',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return $database
->find('platforms', [
Query::equal('projectInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
);
Database::addFilter(
'subQueryKeys',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return $database
->find('keys', [
Query::equal('projectInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
);
Database::addFilter(
'subQueryWebhooks',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return $database
->find('webhooks', [
Query::equal('projectInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
);
Database::addFilter(
'subQuerySessions',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database->find('sessions', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
);
Database::addFilter(
'subQueryTokens',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('tokens', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
);
Database::addFilter(
'subQueryChallenges',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('challenges', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
);
Database::addFilter(
'subQueryAuthenticators',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('authenticators', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
);
Database::addFilter(
'subQueryMemberships',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('memberships', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
);
Database::addFilter(
'subQueryVariables',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return $database
->find('variables', [
Query::equal('resourceInternalId', [$document->getInternalId()]),
Query::equal('resourceType', ['function', 'site']),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
);
Database::addFilter(
'encrypt',
function (mixed $value) {
$key = System::getEnv('_APP_OPENSSL_KEY_V1');
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
$tag = null;
return json_encode([
'data' => OpenSSL::encrypt($value, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag),
'method' => OpenSSL::CIPHER_AES_128_GCM,
'iv' => \bin2hex($iv),
'tag' => \bin2hex($tag ?? ''),
'version' => '1',
]);
},
function (mixed $value) {
if (is_null($value)) {
return;
}
$value = json_decode($value, true);
$key = System::getEnv('_APP_OPENSSL_KEY_V' . $value['version']);
return OpenSSL::decrypt($value['data'], $value['method'], $key, 0, hex2bin($value['iv']), hex2bin($value['tag']));
}
);
Database::addFilter(
'subQueryProjectVariables',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return $database
->find('variables', [
Query::equal('resourceType', ['project']),
Query::limit(APP_LIMIT_SUBQUERY)
]);
}
);
Database::addFilter(
'userSearch',
function (mixed $value, Document $user) {
$searchValues = [
$user->getId(),
$user->getAttribute('email', ''),
$user->getAttribute('name', ''),
$user->getAttribute('phone', '')
];
foreach ($user->getAttribute('labels', []) as $label) {
$searchValues[] = 'label:' . $label;
}
$search = implode(' ', \array_filter($searchValues));
return $search;
},
function (mixed $value) {
return $value;
}
);
Database::addFilter(
'subQueryTargets',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('targets', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY)
]));
}
);
Database::addFilter(
'subQueryTopicTargets',
function (mixed $value) {
return;
},
function (mixed $value, Document $document, Database $database) {
$targetIds = Authorization::skip(fn () => \array_map(
fn ($document) => $document->getAttribute('targetInternalId'),
$database->find('subscribers', [
Query::equal('topicInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY)
])
));
if (\count($targetIds) > 0) {
return $database->skipValidation(fn () => $database->find('targets', [
Query::equal('$internalId', $targetIds)
]));
}
return [];
}
);
Database::addFilter(
'providerSearch',
function (mixed $value, Document $provider) {
$searchValues = [
$provider->getId(),
$provider->getAttribute('name', ''),
$provider->getAttribute('provider', ''),
$provider->getAttribute('type', '')
];
$search = \implode(' ', \array_filter($searchValues));
return $search;
},
function (mixed $value) {
return $value;
}
);
Database::addFilter(
'topicSearch',
function (mixed $value, Document $topic) {
$searchValues = [
$topic->getId(),
$topic->getAttribute('name', ''),
$topic->getAttribute('description', ''),
];
$search = \implode(' ', \array_filter($searchValues));
return $search;
},
function (mixed $value) {
return $value;
}
);
Database::addFilter(
'messageSearch',
function (mixed $value, Document $message) {
$searchValues = [
$message->getId(),
$message->getAttribute('description', ''),
$message->getAttribute('status', ''),
];
$data = \json_decode($message->getAttribute('data', []), true);
$providerType = $message->getAttribute('providerType', '');
switch ($providerType) {
case MESSAGE_TYPE_EMAIL:
$searchValues[] = $data['subject'];
$searchValues[] = MESSAGE_TYPE_EMAIL;
break;
case MESSAGE_TYPE_SMS:
$searchValues[] = $data['content'];
$searchValues[] = MESSAGE_TYPE_SMS;
break;
case MESSAGE_TYPE_PUSH:
$searchValues[] = $data['title'] ?? '';
$searchValues[] = MESSAGE_TYPE_PUSH;
break;
}
$search = \implode(' ', \array_filter($searchValues));
return $search;
},
function (mixed $value) {
return $value;
}
);
+43
View File
@@ -0,0 +1,43 @@
<?php
use Appwrite\Network\Validator\Email;
use Utopia\Database\Database;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\Structure;
use Utopia\Validator\IP;
use Utopia\Validator\Range;
use Utopia\Validator\URL;
use Utopia\Validator\WhiteList;
Structure::addFormat(APP_DATABASE_ATTRIBUTE_EMAIL, function () {
return new Email();
}, Database::VAR_STRING);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_DATETIME, function () {
return new DatetimeValidator();
}, Database::VAR_DATETIME);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) {
$elements = $attribute['formatOptions']['elements'] ?? [];
return new WhiteList($elements, true);
}, Database::VAR_STRING);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_IP, function () {
return new IP();
}, Database::VAR_STRING);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function () {
return new URL();
}, Database::VAR_STRING);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function ($attribute) {
$min = $attribute['formatOptions']['min'] ?? -INF;
$max = $attribute['formatOptions']['max'] ?? INF;
return new Range($min, $max, Range::TYPE_INTEGER);
}, Database::VAR_INTEGER);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) {
$min = $attribute['formatOptions']['min'] ?? -INF;
$max = $attribute['formatOptions']['max'] ?? INF;
return new Range($min, $max, Range::TYPE_FLOAT);
}, Database::VAR_FLOAT);
+23
View File
@@ -0,0 +1,23 @@
<?php
use Utopia\Config\Config;
use Utopia\Locale\Locale;
Locale::$exceptions = false;
$locales = Config::getParam('locale-codes', []);
foreach ($locales as $locale) {
$code = $locale['code'];
$path = __DIR__ . '/../config/locale/translations/' . $code . '.json';
if (!\file_exists($path)) {
$path = __DIR__ . '/../config/locale/translations/' . \substr($code, 0, 2) . '.json'; // if `ar-ae` doesn't exist, look for `ar`
if (!\file_exists($path)) {
$path = __DIR__ . '/../config/locale/translations/en.json'; // if none translation exists, use default from `en.json`
}
}
Locale::setLanguageFromJSON($code, $path);
}
+340
View File
@@ -0,0 +1,340 @@
<?php
use Appwrite\Extend\Exception;
use Appwrite\GraphQL\Promises\Adapter\Swoole;
use Appwrite\Hooks\Hooks;
use Appwrite\PubSub\Adapter\Redis as PubSub;
use Appwrite\URL\URL as AppwriteURL;
use MaxMind\Db\Reader;
use PHPMailer\PHPMailer\PHPMailer;
use Swoole\Database\PDOProxy;
use Utopia\App;
use Utopia\Cache\Adapter\Redis as RedisCache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Adapter\MariaDB;
use Utopia\Database\Adapter\MySQL;
use Utopia\Database\Adapter\SQL;
use Utopia\Domains\Validator\PublicDomain;
use Utopia\DSN\DSN;
use Utopia\Logger\Adapter\AppSignal;
use Utopia\Logger\Adapter\LogOwl;
use Utopia\Logger\Adapter\Raygun;
use Utopia\Logger\Adapter\Sentry;
use Utopia\Logger\Logger;
use Utopia\Pools\Group;
use Utopia\Pools\Pool;
use Utopia\Queue;
use Utopia\Registry\Registry;
use Utopia\System\System;
$register = new Registry();
App::setMode(System::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION));
if (!App::isProduction()) {
// Allow specific domains to skip public domain validation in dev environment
// Useful for existing tests involving webhooks
PublicDomain::allow(['request-catcher']);
}
$register->set('logger', function () {
// Register error logger
$providerName = System::getEnv('_APP_LOGGING_PROVIDER', '');
$providerConfig = System::getEnv('_APP_LOGGING_CONFIG', '');
if (empty($providerConfig)) {
return;
}
try {
$loggingProvider = new DSN($providerConfig ?? '');
$providerName = $loggingProvider->getScheme();
$providerConfig = match ($providerName) {
'sentry' => ['key' => $loggingProvider->getPassword(), 'projectId' => $loggingProvider->getUser() ?? '', 'host' => 'https://' . $loggingProvider->getHost()],
'logowl' => ['ticket' => $loggingProvider->getUser() ?? '', 'host' => $loggingProvider->getHost()],
default => ['key' => $loggingProvider->getHost()],
};
} catch (Throwable $th) {
// Fallback for older Appwrite versions up to 1.5.x that use _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG environment variables
Console::warning('Using deprecated logging configuration. Please update your configuration to use DSN format.' . $th->getMessage());
$configChunks = \explode(";", $providerConfig);
$providerConfig = match ($providerName) {
'sentry' => [ 'key' => $configChunks[0], 'projectId' => $configChunks[1] ?? '', 'host' => '',],
'logowl' => ['ticket' => $configChunks[0] ?? '', 'host' => ''],
default => ['key' => $providerConfig],
};
}
if (empty($providerName) || empty($providerConfig)) {
return;
}
if (!Logger::hasProvider($providerName)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled");
}
try {
$adapter = match ($providerName) {
'sentry' => new Sentry($providerConfig['projectId'], $providerConfig['key'], $providerConfig['host']),
'logowl' => new LogOwl($providerConfig['ticket'], $providerConfig['host']),
'raygun' => new Raygun($providerConfig['key']),
'appsignal' => new AppSignal($providerConfig['key']),
default => null
};
} catch (Throwable $th) {
$adapter = null;
}
if ($adapter === null) {
Console::error("Logging provider not supported. Logging is disabled");
return;
}
return new Logger($adapter);
});
$register->set('pools', function () {
$group = new Group();
$fallbackForDB = 'db_main=' . AppwriteURL::unparse([
'scheme' => 'mariadb',
'host' => System::getEnv('_APP_DB_HOST', 'mariadb'),
'port' => System::getEnv('_APP_DB_PORT', '3306'),
'user' => System::getEnv('_APP_DB_USER', ''),
'pass' => System::getEnv('_APP_DB_PASS', ''),
'path' => System::getEnv('_APP_DB_SCHEMA', ''),
]);
$fallbackForRedis = 'redis_main=' . AppwriteURL::unparse([
'scheme' => 'redis',
'host' => System::getEnv('_APP_REDIS_HOST', 'redis'),
'port' => System::getEnv('_APP_REDIS_PORT', '6379'),
'user' => System::getEnv('_APP_REDIS_USER', ''),
'pass' => System::getEnv('_APP_REDIS_PASS', ''),
]);
$connections = [
'console' => [
'type' => 'database',
'dsns' => $fallbackForDB,
'multiple' => false,
'schemes' => ['mariadb', 'mysql'],
],
'database' => [
'type' => 'database',
'dsns' => $fallbackForDB,
'multiple' => true,
'schemes' => ['mariadb', 'mysql'],
],
'logs' => [
'type' => 'database',
'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB),
'multiple' => false,
'schemes' => ['mariadb', 'mysql'],
],
'publisher' => [
'type' => 'publisher',
'dsns' => $fallbackForRedis,
'multiple' => false,
'schemes' => ['redis'],
],
'consumer' => [
'type' => 'consumer',
'dsns' => $fallbackForRedis,
'multiple' => false,
'schemes' => ['redis'],
],
'pubsub' => [
'type' => 'pubsub',
'dsns' => $fallbackForRedis,
'multiple' => false,
'schemes' => ['redis'],
],
'cache' => [
'type' => 'cache',
'dsns' => $fallbackForRedis,
'multiple' => true,
'schemes' => ['redis'],
],
];
$maxConnections = System::getEnv('_APP_CONNECTIONS_MAX', 151);
$instanceConnections = $maxConnections / System::getEnv('_APP_POOL_CLIENTS', 14);
$multiprocessing = System::getEnv('_APP_SERVER_MULTIPROCESS', 'disabled') === 'enabled';
if ($multiprocessing) {
$workerCount = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
} else {
$workerCount = 1;
}
if ($workerCount > $instanceConnections) {
throw new \Exception('Pool size is too small. Increase the number of allowed database connections or decrease the number of workers.', 500);
}
$poolSize = (int)($instanceConnections / $workerCount);
foreach ($connections as $key => $connection) {
$type = $connection['type'] ?? '';
$multiple = $connection['multiple'] ?? false;
$schemes = $connection['schemes'] ?? [];
$config = [];
$dsns = explode(',', $connection['dsns'] ?? '');
foreach ($dsns as &$dsn) {
$dsn = explode('=', $dsn);
$name = ($multiple) ? $key . '_' . $dsn[0] : $key;
$dsn = $dsn[1] ?? '';
$config[] = $name;
if (empty($dsn)) {
//throw new Exception(Exception::GENERAL_SERVER_ERROR, "Missing value for DSN connection in {$key}");
continue;
}
$dsn = new DSN($dsn);
$dsnHost = $dsn->getHost();
$dsnPort = $dsn->getPort();
$dsnUser = $dsn->getUser();
$dsnPass = $dsn->getPassword();
$dsnScheme = $dsn->getScheme();
$dsnDatabase = $dsn->getPath();
if (!in_array($dsnScheme, $schemes)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme");
}
/**
* Get Resource
*
* Creation could be reused across connection types like database, cache, queue, etc.
*
* Resource assignment to an adapter will happen below.
*/
$resource = match ($dsnScheme) {
'mysql',
'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array(
PDO::ATTR_TIMEOUT => 3, // Seconds
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_STRINGIFY_FETCHES => true
));
});
},
'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) {
$redis = new \Redis();
@$redis->pconnect($dsnHost, (int)$dsnPort);
if ($dsnPass) {
$redis->auth($dsnPass);
}
$redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
return $redis;
},
default => throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'),
};
$pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) {
// Get Adapter
switch ($type) {
case 'database':
$adapter = match ($dsn->getScheme()) {
'mariadb' => new MariaDB($resource()),
'mysql' => new MySQL($resource()),
default => null
};
$adapter->setDatabase($dsn->getPath());
return $adapter;
case 'pubsub':
return match ($dsn->getScheme()) {
'redis' => new PubSub($resource()),
default => null
};
case 'publisher':
case 'consumer':
return match ($dsn->getScheme()) {
'redis' => new Queue\Broker\Redis(new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort())),
default => null
};
case 'cache':
return match ($dsn->getScheme()) {
'redis' => new RedisCache($resource()),
default => null
};
default:
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation.");
}
});
$group->add($pool);
}
Config::setParam('pools-' . $key, $config);
}
return $group;
});
$register->set('db', function () {
// This is usually for our workers or CLI commands scope
$dbHost = System::getEnv('_APP_DB_HOST', '');
$dbPort = System::getEnv('_APP_DB_PORT', '');
$dbUser = System::getEnv('_APP_DB_USER', '');
$dbPass = System::getEnv('_APP_DB_PASS', '');
$dbScheme = System::getEnv('_APP_DB_SCHEMA', '');
return new PDO(
"mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4",
$dbUser,
$dbPass,
SQL::getPDOAttributes()
);
});
$register->set('smtp', function () {
$mail = new PHPMailer(true);
$mail->isSMTP();
$username = System::getEnv('_APP_SMTP_USERNAME');
$password = System::getEnv('_APP_SMTP_PASSWORD');
$mail->XMailer = 'Appwrite Mailer';
$mail->Host = System::getEnv('_APP_SMTP_HOST', 'smtp');
$mail->Port = System::getEnv('_APP_SMTP_PORT', 25);
$mail->SMTPAuth = !empty($username) && !empty($password);
$mail->Username = $username;
$mail->Password = $password;
$mail->SMTPSecure = System::getEnv('_APP_SMTP_SECURE', '');
$mail->SMTPAutoTLS = false;
$mail->CharSet = 'UTF-8';
$from = \urldecode(System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'));
$email = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
$mail->setFrom($email, $from);
$mail->addReplyTo($email, $from);
$mail->isHTML(true);
return $mail;
});
$register->set('geodb', function () {
return new Reader(__DIR__ . '/../assets/dbip/dbip-country-lite-2024-09.mmdb');
});
$register->set('passwordsDictionary', function () {
$content = \file_get_contents(__DIR__ . '/../assets/security/10k-common-passwords');
$content = explode("\n", $content);
$content = array_flip($content);
return $content;
});
$register->set('promiseAdapter', function () {
return new Swoole();
});
$register->set('hooks', function () {
return new Hooks();
});
+854
View File
@@ -0,0 +1,854 @@
<?php
use Ahc\Jwt\JWT;
use Ahc\Jwt\JWTException;
use Appwrite\Auth\Auth;
use Appwrite\Auth\Key;
use Appwrite\Event\Audit;
use Appwrite\Event\Build;
use Appwrite\Event\Certificate;
use Appwrite\Event\Database as EventDatabase;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Func;
use Appwrite\Event\Mail;
use Appwrite\Event\Messaging;
use Appwrite\Event\Migration;
use Appwrite\Event\Realtime;
use Appwrite\Event\StatsUsage;
use Appwrite\Event\Webhook;
use Appwrite\Extend\Exception;
use Appwrite\GraphQL\Schema;
use Appwrite\Network\Validator\Origin;
use Appwrite\Utopia\Request;
use Executor\Executor;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\App;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\DSN\DSN;
use Utopia\Locale\Locale;
use Utopia\Logger\Log;
use Utopia\Pools\Group;
use Utopia\Queue\Publisher;
use Utopia\Storage\Device;
use Utopia\Storage\Device\AWS;
use Utopia\Storage\Device\Backblaze;
use Utopia\Storage\Device\DOSpaces;
use Utopia\Storage\Device\Linode;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Device\Wasabi;
use Utopia\Storage\Storage;
use Utopia\System\System;
use Utopia\Validator\Hostname;
use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub;
// Runtime Execution
App::setResource('log', fn () => new Log());
App::setResource('logger', function ($register) {
return $register->get('logger');
}, ['register']);
App::setResource('hooks', function ($register) {
return $register->get('hooks');
}, ['register']);
App::setResource('register', fn () => $register);
App::setResource('locale', fn () => new Locale(System::getEnv('_APP_LOCALE', 'en')));
App::setResource('localeCodes', function () {
return array_map(fn ($locale) => $locale['code'], Config::getParam('locale-codes', []));
});
// Queues
App::setResource('publisher', function (Group $pools) {
return $pools->get('publisher')->pop()->getResource();
}, ['pools']);
App::setResource('consumer', function (Group $pools) {
return $pools->get('consumer')->pop()->getResource();
}, ['pools']);
App::setResource('queueForMessaging', function (Publisher $publisher) {
return new Messaging($publisher);
}, ['publisher']);
App::setResource('queueForMails', function (Publisher $publisher) {
return new Mail($publisher);
}, ['publisher']);
App::setResource('queueForBuilds', function (Publisher $publisher) {
return new Build($publisher);
}, ['publisher']);
App::setResource('queueForDatabase', function (Publisher $publisher) {
return new EventDatabase($publisher);
}, ['publisher']);
App::setResource('queueForDeletes', function (Publisher $publisher) {
return new Delete($publisher);
}, ['publisher']);
App::setResource('queueForEvents', function (Publisher $publisher) {
return new Event($publisher);
}, ['publisher']);
App::setResource('queueForWebhooks', function (Publisher $publisher) {
return new Webhook($publisher);
}, ['publisher']);
App::setResource('queueForRealtime', function () {
return new Realtime();
}, []);
App::setResource('queueForStatsUsage', function (Publisher $publisher) {
return new StatsUsage($publisher);
}, ['publisher']);
App::setResource('queueForAudits', function (Publisher $publisher) {
return new Audit($publisher);
}, ['publisher']);
App::setResource('queueForFunctions', function (Publisher $publisher) {
return new Func($publisher);
}, ['publisher']);
App::setResource('queueForCertificates', function (Publisher $publisher) {
return new Certificate($publisher);
}, ['publisher']);
App::setResource('queueForMigrations', function (Publisher $publisher) {
return new Migration($publisher);
}, ['publisher']);
App::setResource('clients', function ($request, $console, $project) {
$console->setAttribute('platforms', [ // Always allow current host
'$collection' => ID::custom('platforms'),
'name' => 'Current Host',
'type' => Origin::CLIENT_TYPE_WEB,
'hostname' => $request->getHostname(),
], Document::SET_TYPE_APPEND);
$hostnames = explode(',', System::getEnv('_APP_CONSOLE_HOSTNAMES', ''));
$validator = new Hostname();
foreach ($hostnames as $hostname) {
$hostname = trim($hostname);
if (!$validator->isValid($hostname)) {
continue;
}
$console->setAttribute('platforms', [
'$collection' => ID::custom('platforms'),
'type' => Origin::CLIENT_TYPE_WEB,
'name' => $hostname,
'hostname' => $hostname,
], Document::SET_TYPE_APPEND);
}
/**
* Get All verified client URLs for both console and current projects
* + Filter for duplicated entries
*/
$clientsConsole = \array_map(
fn ($node) => $node['hostname'],
\array_filter(
$console->getAttribute('platforms', []),
fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && !empty($node['hostname']))
)
);
$clients = $clientsConsole;
$platforms = $project->getAttribute('platforms', []);
foreach ($platforms as $node) {
if (
isset($node['type']) &&
($node['type'] === Origin::CLIENT_TYPE_WEB ||
$node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) &&
!empty($node['hostname'])
) {
$clients[] = $node['hostname'];
}
}
return \array_unique($clients);
}, ['request', 'console', 'project']);
App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform) {
/** @var Appwrite\Utopia\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Database $dbForPlatform */
/** @var string $mode */
Authorization::setDefaultStatus(true);
Auth::setCookieName('a_session_' . $project->getId());
if (APP_MODE_ADMIN === $mode) {
Auth::setCookieName('a_session_' . $console->getId());
}
$session = Auth::decodeSession(
$request->getCookie(
Auth::$cookieName, // Get sessions
$request->getCookie(Auth::$cookieName . '_legacy', '')
)
);
// Get session from header for SSR clients
if (empty($session['id']) && empty($session['secret'])) {
$sessionHeader = $request->getHeader('x-appwrite-session', '');
if (!empty($sessionHeader)) {
$session = Auth::decodeSession($sessionHeader);
}
}
// Get fallback session from old clients (no SameSite support) or clients who block 3rd-party cookies
if ($response) {
$response->addHeader('X-Debug-Fallback', 'false');
}
if (empty($session['id']) && empty($session['secret'])) {
if ($response) {
$response->addHeader('X-Debug-Fallback', 'true');
}
$fallback = $request->getHeader('x-fallback-cookies', '');
$fallback = \json_decode($fallback, true);
$session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : ''));
}
Auth::$unique = $session['id'] ?? '';
Auth::$secret = $session['secret'] ?? '';
if (APP_MODE_ADMIN !== $mode) {
if ($project->isEmpty()) {
$user = new Document([]);
} else {
if ($project->getId() === 'console') {
$user = $dbForPlatform->getDocument('users', Auth::$unique);
} else {
$user = $dbForProject->getDocument('users', Auth::$unique);
}
}
} else {
$user = $dbForPlatform->getDocument('users', Auth::$unique);
}
if (
$user->isEmpty() // Check a document has been found in the DB
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret)
) { // Validate user has valid login token
$user = new Document([]);
}
// if (APP_MODE_ADMIN === $mode) {
// if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) {
// Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
// } else {
// $user = new Document([]);
// }
// }
$authJWT = $request->getHeader('x-appwrite-jwt', '');
if (!empty($authJWT) && !$project->isEmpty()) { // JWT authentication
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0);
try {
$payload = $jwt->decode($authJWT);
} catch (JWTException $error) {
throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. ' . $error->getMessage());
}
$jwtUserId = $payload['userId'] ?? '';
if (!empty($jwtUserId)) {
$user = $dbForProject->getDocument('users', $jwtUserId);
}
$jwtSessionId = $payload['sessionId'] ?? '';
if (!empty($jwtSessionId)) {
if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token
$user = new Document([]);
}
}
}
$dbForProject->setMetadata('user', $user->getId());
$dbForPlatform->setMetadata('user', $user->getId());
return $user;
}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform']);
App::setResource('project', function ($dbForPlatform, $request, $console) {
/** @var Appwrite\Utopia\Request $request */
/** @var Utopia\Database\Database $dbForPlatform */
/** @var Utopia\Database\Document $console */
$projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', ''));
if (empty($projectId) || $projectId === 'console') {
return $console;
}
$project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
return $project;
}, ['dbForPlatform', 'request', 'console']);
App::setResource('session', function (Document $user) {
if ($user->isEmpty()) {
return;
}
$sessions = $user->getAttribute('sessions', []);
$sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret);
if (!$sessionId) {
return;
}
foreach ($sessions as $session) {/** @var Document $session */
if ($sessionId === $session->getId()) {
return $session;
}
}
return;
}, ['user']);
App::setResource('console', function () {
return new Document(Config::getParam('console'));
}, []);
App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForPlatform;
}
try {
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$dbAdapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$database
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
return $database;
}, ['pools', 'dbForPlatform', 'cache', 'project']);
App::setResource('dbForPlatform', function (Group $pools, Cache $cache) {
$dbAdapter = $pools
->get('console')
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$database
->setNamespace('_console')
->setMetadata('host', \gethostname())
->setMetadata('project', 'console')
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
return $database;
}, ['pools', 'cache']);
App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) {
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForPlatform;
}
try {
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$configure = (function (Database $database) use ($project, $dsn) {
$database
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
});
if (isset($databases[$dsn->getHost()])) {
$database = $databases[$dsn->getHost()];
$configure($database);
return $database;
}
$dbAdapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$databases[$dsn->getHost()] = $database;
$configure($database);
return $database;
};
}, ['pools', 'dbForPlatform', 'cache']);
App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
$database = null;
return function (?Document $project = null) use ($pools, $cache, $database) {
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
return $database;
}
$dbAdapter = $pools
->get('logs')
->pop()
->getResource();
$database = new Database(
$dbAdapter,
$cache
);
$database
->setSharedTables(true)
->setNamespace('logsV1')
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
// set tenant
if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
}
return $database;
};
}, ['pools', 'cache']);
App::setResource('cache', function (Group $pools) {
$list = Config::getParam('pools-cache', []);
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
}
return new Cache(new Sharding($adapters));
}, ['pools']);
App::setResource('redis', function () {
$host = System::getEnv('_APP_REDIS_HOST', 'localhost');
$port = System::getEnv('_APP_REDIS_PORT', 6379);
$pass = System::getEnv('_APP_REDIS_PASS', '');
$redis = new \Redis();
@$redis->pconnect($host, (int)$port);
if ($pass) {
$redis->auth($pass);
}
$redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
return $redis;
});
App::setResource('timelimit', function (\Redis $redis) {
return function (string $key, int $limit, int $time) use ($redis) {
return new TimeLimitRedis($key, $limit, $time, $redis);
};
}, ['redis']);
App::setResource('deviceForLocal', function () {
return new Local();
});
App::setResource('deviceForFiles', function ($project) {
return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForSites', function ($project) {
return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForImports', function (Document $project) {
return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForFunctions', function ($project) {
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForBuilds', function ($project) {
return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId());
}, ['project']);
function getDevice(string $root, string $connection = ''): Device
{
$connection = !empty($connection) ? $connection : System::getEnv('_APP_CONNECTIONS_STORAGE', '');
if (!empty($connection)) {
$acl = 'private';
$device = Storage::DEVICE_LOCAL;
$accessKey = '';
$accessSecret = '';
$bucket = '';
$region = '';
$url = System::getEnv('_APP_STORAGE_S3_ENDPOINT', '');
try {
$dsn = new DSN($connection);
$device = $dsn->getScheme();
$accessKey = $dsn->getUser() ?? '';
$accessSecret = $dsn->getPassword() ?? '';
$bucket = $dsn->getPath() ?? '';
$region = $dsn->getParam('region');
} catch (\Throwable $e) {
Console::warning($e->getMessage() . 'Invalid DSN. Defaulting to Local device.');
}
switch ($device) {
case Storage::DEVICE_S3:
if (!empty($url)) {
return new S3($root, $accessKey, $accessSecret, $url, $region, $acl);
} else {
return new AWS($root, $accessKey, $accessSecret, $bucket, $region, $acl);
}
// no break
case STORAGE::DEVICE_DO_SPACES:
$device = new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl);
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
return $device;
case Storage::DEVICE_BACKBLAZE:
return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_LINODE:
return new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_WASABI:
return new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_LOCAL:
default:
return new Local($root);
}
} else {
switch (strtolower(System::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '')) {
case Storage::DEVICE_LOCAL:
default:
return new Local($root);
case Storage::DEVICE_S3:
$s3AccessKey = System::getEnv('_APP_STORAGE_S3_ACCESS_KEY', '');
$s3SecretKey = System::getEnv('_APP_STORAGE_S3_SECRET', '');
$s3Region = System::getEnv('_APP_STORAGE_S3_REGION', '');
$s3Bucket = System::getEnv('_APP_STORAGE_S3_BUCKET', '');
$s3Acl = 'private';
$s3EndpointUrl = System::getEnv('_APP_STORAGE_S3_ENDPOINT', '');
if (!empty($s3EndpointUrl)) {
return new S3($root, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl);
} else {
return new AWS($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
}
// no break
case Storage::DEVICE_DO_SPACES:
$doSpacesAccessKey = System::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', '');
$doSpacesSecretKey = System::getEnv('_APP_STORAGE_DO_SPACES_SECRET', '');
$doSpacesRegion = System::getEnv('_APP_STORAGE_DO_SPACES_REGION', '');
$doSpacesBucket = System::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', '');
$doSpacesAcl = 'private';
$device = new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl);
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
return $device;
case Storage::DEVICE_BACKBLAZE:
$backblazeAccessKey = System::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', '');
$backblazeSecretKey = System::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', '');
$backblazeRegion = System::getEnv('_APP_STORAGE_BACKBLAZE_REGION', '');
$backblazeBucket = System::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', '');
$backblazeAcl = 'private';
return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl);
case Storage::DEVICE_LINODE:
$linodeAccessKey = System::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', '');
$linodeSecretKey = System::getEnv('_APP_STORAGE_LINODE_SECRET', '');
$linodeRegion = System::getEnv('_APP_STORAGE_LINODE_REGION', '');
$linodeBucket = System::getEnv('_APP_STORAGE_LINODE_BUCKET', '');
$linodeAcl = 'private';
return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl);
case Storage::DEVICE_WASABI:
$wasabiAccessKey = System::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', '');
$wasabiSecretKey = System::getEnv('_APP_STORAGE_WASABI_SECRET', '');
$wasabiRegion = System::getEnv('_APP_STORAGE_WASABI_REGION', '');
$wasabiBucket = System::getEnv('_APP_STORAGE_WASABI_BUCKET', '');
$wasabiAcl = 'private';
return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl);
}
}
}
App::setResource('mode', function ($request) {
/** @var Appwrite\Utopia\Request $request */
/**
* Defines the mode for the request:
* - 'default' => Requests for Client and Server Side
* - 'admin' => Request from the Console on non-console projects
*/
return $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT));
}, ['request']);
App::setResource('geodb', function ($register) {
/** @var Utopia\Registry\Registry $register */
return $register->get('geodb');
}, ['register']);
App::setResource('passwordsDictionary', function ($register) {
/** @var Utopia\Registry\Registry $register */
return $register->get('passwordsDictionary');
}, ['register']);
App::setResource('servers', function () {
$platforms = Config::getParam('platforms');
$server = $platforms[APP_PLATFORM_SERVER];
$languages = array_map(function ($language) {
return strtolower($language['name']);
}, $server['sdks']);
return $languages;
});
App::setResource('promiseAdapter', function ($register) {
return $register->get('promiseAdapter');
}, ['register']);
App::setResource('schema', function ($utopia, $dbForProject) {
$complexity = function (int $complexity, array $args) {
$queries = Query::parseQueries($args['queries'] ?? []);
$query = Query::getByType($queries, [Query::TYPE_LIMIT])[0] ?? null;
$limit = $query ? $query->getValue() : APP_LIMIT_LIST_DEFAULT;
return $complexity * $limit;
};
$attributes = function (int $limit, int $offset) use ($dbForProject) {
$attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [
Query::limit($limit),
Query::offset($offset),
]));
return \array_map(function ($attr) {
return $attr->getArrayCopy();
}, $attrs);
};
$urls = [
'list' => function (string $databaseId, string $collectionId, array $args) {
return "/v1/databases/$databaseId/collections/$collectionId/documents";
},
'create' => function (string $databaseId, string $collectionId, array $args) {
return "/v1/databases/$databaseId/collections/$collectionId/documents";
},
'read' => function (string $databaseId, string $collectionId, array $args) {
return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}";
},
'update' => function (string $databaseId, string $collectionId, array $args) {
return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}";
},
'delete' => function (string $databaseId, string $collectionId, array $args) {
return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}";
},
];
$params = [
'list' => function (string $databaseId, string $collectionId, array $args) {
return [ 'queries' => $args['queries']];
},
'create' => function (string $databaseId, string $collectionId, array $args) {
$id = $args['id'] ?? 'unique()';
$permissions = $args['permissions'] ?? null;
unset($args['id']);
unset($args['permissions']);
// Order must be the same as the route params
return [
'databaseId' => $databaseId,
'documentId' => $id,
'collectionId' => $collectionId,
'data' => $args,
'permissions' => $permissions,
];
},
'update' => function (string $databaseId, string $collectionId, array $args) {
$documentId = $args['id'];
$permissions = $args['permissions'] ?? null;
unset($args['id']);
unset($args['permissions']);
// Order must be the same as the route params
return [
'databaseId' => $databaseId,
'collectionId' => $collectionId,
'documentId' => $documentId,
'data' => $args,
'permissions' => $permissions,
];
},
];
return Schema::build(
$utopia,
$complexity,
$attributes,
$urls,
$params,
);
}, ['utopia', 'dbForProject']);
App::setResource('contributors', function () {
$path = 'app/config/contributors.json';
$list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : [];
return $list;
});
App::setResource('employees', function () {
$path = 'app/config/employees.json';
$list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : [];
return $list;
});
App::setResource('heroes', function () {
$path = 'app/config/heroes.json';
$list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : [];
return $list;
});
App::setResource('gitHub', function (Cache $cache) {
return new VcsGitHub($cache);
}, ['cache']);
App::setResource('requestTimestamp', function ($request) {
//TODO: Move this to the Request class itself
$timestampHeader = $request->getHeader('x-appwrite-timestamp');
$requestTimestamp = null;
if (!empty($timestampHeader)) {
try {
$requestTimestamp = new \DateTime($timestampHeader);
} catch (\Throwable $e) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid X-Appwrite-Timestamp header value');
}
}
return $requestTimestamp;
}, ['request']);
App::setResource('plan', function (array $plan = []) {
return [];
});
App::setResource('smsRates', function () {
return [];
});
App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) {
$teamInternalId = '';
if ($project->getId() !== 'console') {
$teamInternalId = $project->getAttribute('teamInternalId', '');
} else {
$route = $utopia->match($request);
$path = $route->getPath();
if (str_starts_with($path, '/v1/projects/:projectId')) {
$uri = $request->getURI();
$pid = explode('/', $uri)[3];
$p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid));
$teamInternalId = $p->getAttribute('teamInternalId', '');
} elseif ($path === '/v1/projects') {
$teamId = $request->getParam('teamId', '');
$team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId));
return $team;
}
}
$team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) {
return $dbForPlatform->findOne('teams', [
Query::equal('$internalId', [$teamInternalId]),
]);
});
return $team;
}, ['project', 'dbForPlatform', 'utopia', 'request']);
App::setResource(
'isResourceBlocked',
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
);
App::setResource('previewHostname', function (Request $request, ?Key $apiKey) {
$allowed = false;
if (App::isDevelopment()) {
$allowed = true;
} elseif (!\is_null($apiKey) && $apiKey->getHostnameOverride() === true) {
$allowed = true;
}
if ($allowed) {
$host = $request->getQuery('appwrite-hostname', $request->getHeader('x-appwrite-hostname', '')) ?? '';
if (!empty($host)) {
return $host;
}
}
return '';
}, ['request', 'apiKey']);
App::setResource('apiKey', function (Request $request, Document $project): ?Key {
$key = $request->getHeader('x-appwrite-key');
if (empty($key)) {
return null;
}
return Key::decode($project, $key);
}, ['request', 'project']);
App::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
+6 -4
View File
@@ -7,6 +7,8 @@
<title>404 Not Found</title>
<style>
@import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400);
* {
margin: 0;
padding: 0;
@@ -36,7 +38,7 @@
background: var(--color-overlay-on-neutral, rgba(0, 0, 0, 0.06));
color: var(--color-fgColor-neutral-secondary, #56565C);
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-style: normal;
font-weight: 400;
@@ -47,7 +49,7 @@
h1 {
color: var(--color-fgColor-neutral-primary, #2D2D31);
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-style: normal;
font-weight: 400;
@@ -59,7 +61,7 @@
button {
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-style: normal;
font-weight: 500;
@@ -88,7 +90,7 @@
}
.brand p {
font-family: var(--font-family-monospace, "Aeonik Fono");
font-family: var(--font-family-monospace, "Fira Code"), monospace;
font-size: var(--font-size-XS, 12px);
font-style: normal;
font-weight: 400;
+492 -90
View File
@@ -2,21 +2,98 @@
$development = $this->getParam('development', false);
$type = $this->getParam('type', 'general_server_error');
$code = $this->getParam('code', 500);
$errorID = $this->getParam('errorID', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
$message = $this->getParam('message', '');
$trace = $this->getParam('trace', []);
$projectName = $this->getParam('projectName', '');
$projectURL = $this->getParam('projectURL', '');
$title = $this->getParam('title', '')
$title = $this->getParam('title', 'Error');
$exception = $this->getParam('exception', null);
$isSimpleMessage = true;
$label = '';
$labelClass = '';
$buttons = [];
if($exception !== null && method_exists($exception, 'getCTAs')) {
foreach ($exception->getCTAs() as $index => $cta) {
$class = ($index === 0) ? 'bordered-button' : 'button';
$buttons[] = [
'text' => $cta['label'],
'url' => $cta['url'],
'class' => $class
];
}
}
switch ($type) {
case 'proxy_error_override':
$type = '';
$label = 'Error ' . $code;
$message = $code >= 500 ? 'An unexpected server error occured.' : 'An unexpected client error occured.';
switch($code) {
case 401:
$message = 'You must sign in to access this page.';
break;
case 403:
$message = 'You are not authorized to access this page.';
break;
case 404:
$message = 'The page you are looking for does not exist.';
break;
case 504:
$message = 'The server did not respond in time.';
break;
case 501:
$message = 'This page is not implemented yet.';
break;
}
break;
case 'function_execute_permission_missing':
$label = 'Execution not permitted';
$labelClass = 'warning';
break;
case 'build_not_ready':
$label = 'Deployment is still building';
$message = 'The page will update after the build completes.';
$labelClass = 'warning';
break;
case 'build_failed':
$label = 'Deployment build failed';
$message = 'An error occurred during the build process.';
$labelClass = 'error';
break;
case 'rule_not_found':
$label = 'Nothing is here yet';
$message = 'This page is empty, but you can make it yours.';
break;
case 'deployment_not_found':
$label = 'No active deployments';
$message = 'This page is empty, activate a deployment to make it live.';
break;
case 'build_canceled':
$label = 'Deployment build canceled';
$message = 'This build was canceled and won\'t be deployed.';
break;
case 'general_route_not_found':
$label = 'Page not found';
$message = 'The page you\'re looking for doesn\'t exist.';
break;
default:
$label = 'Error ' . $code;
$message = $message;
$isSimpleMessage = false;
break;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="" />
<link rel="icon" href="/favicon.png" />
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
<link
rel="preload"
href="/fonts/inter/inter-v8-latin-600.woff2"
@@ -29,102 +106,427 @@ $title = $this->getParam('title', '')
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="/fonts/poppins/poppins-v19-latin-500.woff2"
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="/fonts/poppins/poppins-v19-latin-600.woff2"
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="/fonts/poppins/poppins-v19-latin-700.woff2"
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="/fonts/source-code-pro/source-code-pro-v20-latin-regular.woff2"
as="font"
type="font/woff2"
crossorigin />
<link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink" />
<link rel="preload" as="style" type="text/css" href="/fonts/main.css" />
<link rel="stylesheet" href="/fonts/main.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-security-policy" content="">
<title><?php echo $this->print($title); ?></title>
<style>
@media(min-width:768px) {
article.card {
padding: 2rem !important;
@import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400);
* {
margin: 0;
padding: 0;
}
body {
background-color: #FFFFFF;
}
.main {
display: flex;
min-height: 100vh;
width: 100vw;
align-items: center;
justify-content: center;
}
.content {
margin-left: auto;
margin-right: auto;
max-width: 400px;
}
span {
padding: var(--space-1, 2px) var(--space-3, 6px);
border-radius: var(--border-radius-XS, 6px);
background: var(--color-overlay-on-neutral, rgba(0, 0, 0, 0.06));
color: var(--color-fgColor-neutral-secondary, #56565C);
text-align: center;
font-family: var(--font-family-sansSerif, Inter), sans-serif;
font-size: var(--font-size-S, 14px);
font-style: normal;
font-weight: 400;
line-height: 140%;
letter-spacing: -0.063px;
}
h1 {
color: var(--color-fgColor-neutral-primary, #2D2D31);
text-align: center;
font-family: var(--font-family-sansSerif, Inter), sans-serif;
font-size: var(--font-size-XXXL, 32px);
font-style: normal;
font-weight: 400;
line-height: 140%;
letter-spacing: -0.144px;
margin-top: 8px;
margin-bottom: 32px;
}
.content h1 {
margin-bottom: 20px;
}
.content.small-error h1 {
font-size: var(--font-size-M, 20px);
}
.content.large-error h1 {
font-size: var(--font-size-XXXL, 32px);
}
.bordered-button {
border-radius: var(--border-radius-S, 8px);
font-family: var(--font-family-sansSerif, Inter), sans-serif;
font-size: var(--font-size-S, 14px);
font-style: normal;
font-weight: 500;
line-height: 140%;
letter-spacing: -0.063px;
padding: var(--space-3, 6px) var(--space-5, 10px);
cursor: pointer;
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #D8D8DB);
background: var(--color-bgColor-neutral-primary, #FFF);
color: var(--color-fgColor-neutral-secondary, #56565C);
}
button {
border-radius: var(--border-radius-S, 8px);
font-family: var(--font-family-sansSerif, Inter), sans-serif;
font-size: var(--font-size-S, 14px);
font-style: normal;
font-weight: 500;
line-height: 140%;
letter-spacing: -0.063px;
padding: var(--space-3, 6px) var(--space-5, 10px);
cursor: pointer;
border: var(--border-width-S, 1px) solid transparent;
background: var(--color-bgColor-neutral-primary, #FFF);
color: var(--color-fgColor-neutral-secondary, #56565C);
}
.center {
display: flex;
justify-content: center;
gap: 8px;
}
.brand {
position: absolute;
width: 100%;
bottom: 32px;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
.brand p {
font-family: var(--font-family-monospace, "Fira Code"), monospace;
font-size: var(--font-size-XS, 12px);
font-style: normal;
font-weight: 400;
line-height: 130%;
letter-spacing: 0.96px;
text-transform: uppercase;
color: var(--color-fgColor-neutral-secondary, #56565C);
}
.brand svg {
height: 20px;
}
.warning {
background: var(--color-overlay-on-neutral, rgba(254, 124, 67, 0.16));
color: var(--color-fgColor-neutral-secondary, #61250A);
}
.error {
background: var(--color-overlay-on-neutral, rgba(255, 69, 58, 0.16));
color: var(--color-fgColor-neutral-secondary, #B31212);
}
.logo-dark {
display: none;
}
.logo-light {
display: block;
}
.type {
padding: var(--space-1, 2px) var(--space-3, 6px);
border-radius: var(--border-radius-XS, 6px);
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #EDEDF0);
background: var(--color-overlay-on-neutral, rgba(250, 250, 251, 1));
color: var(--color-fgColor-neutral-secondary, #56565C);
text-align: center;
font-family: var(--font-family-monospace, "Fira Code"), monospace;
font-size: var(--font-size-XS, 12px);
font-style: normal;
font-weight: 400;
line-height: 140%;
letter-spacing: 0px;
}
.error-trace {
max-width: 900px;
padding: 20px;
font-family: var(--font-family-sansSerif, Inter), sans-serif;
}
.back-button {
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
color: var(--color-fgColor-neutral-secondary, #56565C);
font-family: var(--font-family-sansSerif, Inter), sans-serif;
font-size: var(--font-size-S, 14px);
font-style: normal;
font-weight: 500;
line-height: 140%;
letter-spacing: -0.45px;
}
.back-button:hover {
text-decoration: underline;
}
.trace-grid {
display: grid;
grid-template-columns: auto 1fr;
gap: 16px;
background: var(--color-bgColor-neutral-secondary, #FFFFFF);
padding: 10px 12px;
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #EDEDF0);
}
.trace-grid-header {
display: flex;
align-items: center;
padding: 10px 12px;
background: var(--color-bgColor-neutral-secondary, #FAFAFB);
border-radius: 8px 8px 0 0;
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #EDEDF0);
font-family: var(--font-family-sansSerif, Inter), sans-serif;
font-size: var(--font-size-S, 14px);
font-weight: 400;
line-height: 140%;
letter-spacing: -0.45px;
color: var(--color-fgColor-neutral-secondary, #56565C);
}
.trace-label {
font-family: var(--font-family-sansSerif, Inter), sans-serif;
font-size: var(--font-size-S, 14px);
font-weight: 400;
line-height: 140%;
letter-spacing: -0.45px;
color: var(--color-fgColor-neutral-secondary, #56565C);
}
.trace-value {
color: var(--color-fgColor-neutral-secondary, #56565C);
font-family: var(--font-family-monospace, "Fira Code"), monospace;
font-size: var(--font-size-S, 14px);
font-weight: 400;
line-height: 140%;
letter-spacing: 0px;
}
.trace-args {
/* grid-column: 1 / -1; */
padding: 10px 12px;
/* white-space: pre-wrap; */
overflow-x: auto;
font-family: var(--font-family-monospace, "Fira Code"), monospace;
font-size: var(--font-size-S, 14px);
font-weight: 400;
line-height: 140%;
color: var(--color-fgColor-neutral-secondary, #56565C);
}
@media (max-width: 768px) {
.content {
margin-left: 16px;
margin-right: 16px;
}
h1 {
font-size: 28px;
}
}
@media (prefers-color-scheme: dark) {
body {
background-color: #1D1D21;
}
h1 {
color: var(--color-fgColor-neutral-primary, #EDEDF0);
}
span {
background: var(--color-overlay-on-neutral, rgba(255, 255, 255, 0.2));
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
.bordered-button {
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #414146);
background: var(--color-bgColor-neutral-primary, #1D1D21);
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
button {
background: var(--color-bgColor-neutral-primary, #1D1D21);
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
.brand p {
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
.warning {
background: var(--color-overlay-on-neutral, rgba(254, 124, 67, 0.24));
color: var(--color-fgColor-neutral-secondary, #FFD5C2);
}
.error {
background: var(--color-overlay-on-neutral, rgba(255, 69, 58, 0.28));
color: var(--color-fgColor-neutral-secondary, #FFD5D4);
}
.logo-light {
display: none;
}
.logo-dark {
display: block;
}
.type {
background: var(--color-overlay-on-neutral, rgba(25, 25, 28, 1));
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #414146);
}
.back-button {
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
.trace-grid {
background: var(--color-bgColor-neutral-secondary, #1D1D21);
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #2D2D31);
}
.trace-grid-header {
background: var(--color-bgColor-neutral-secondary, #19191C);
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #2D2D31);
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
.trace-label {
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
.trace-value {
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
.trace-args {
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
}
}
</style>
</head>
<body>
<div class="container u-margin-block-start-24">
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<h1 class="heading-level-4 u-trim-1">Error <?php echo $this->print($code); ?></h1>
<p class="text"><?php echo $this->print($message); ?></p>
<div class="u-flex u-flex-vertical u-gap-8">
<p class="text">Type</p>
<p><code class="inline-code"><?php echo $this->print($type); ?></code></p>
<body x-data="{ page: 'error' }">
<div class="main">
<div x-show="page === 'error'" class="content <?php echo $isSimpleMessage ? 'large-error' : 'small-error' ?>">
<div class="center"><span class="<?php echo $this->print($labelClass); ?>"><?php echo $this->print($label); ?></span></div>
<h1><?php echo $this->print($message); ?></h1>
<?php if (!empty($type)): ?>
<div class="center">
<span class='type'><?php echo $this->print($type); ?></span>
</div>
<?php if ($development) : ?>
<h2 class="heading-level-5 u-trim-1">Error Trace</h2>
<?php foreach ($trace as $log) : ?>
<div class="table-with-scroll">
<div class="table-wrapper">
<table class="table is-remove-outer-styles">
<tbody class="table-tbody">
<?php foreach ($log as $key => $value) : ?>
<tr>
<td class="table-col" style="width: 120px"><?php echo $this->print($key, self::FILTER_ESCAPE); ?></td>
<td class="table-col"><code class="grid-code u-max-height-200 u-overflow-x-auto u-overflow-y-auto">
<?php if (is_array($value)) : ?>
<pre><?php echo $this->print(var_export($value, true), self::FILTER_ESCAPE); ?></pre>
<?php else : ?>
<pre><?php echo $this->print($value, self::FILTER_ESCAPE); ?></pre>
<?php endif; ?>
</code>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
<div class="center" style="margin-top: 20px;">
<?php if (!empty($buttons)): ?>
<?php foreach ($buttons as $button): ?>
<a href="<?php echo htmlspecialchars($button['url']); ?>">
<button class="<?php echo htmlspecialchars($button['class']); ?>">
<?php echo htmlspecialchars($button['text']); ?>
</button>
</a>
<?php endforeach; ?>
<?php endif; ?>
<?php if ($development) : ?>
<button class="<?php echo count($buttons) === 0 ? 'bordered-button' : 'button' ?>" x-on:click="page = 'trace'">View error trace</button>
<?php endif; ?>
</div>
</article>
</div>
<div x-show="page === 'trace'" class="error-trace">
<button class="back-button" x-on:click="page = 'error'">
Back
</button>
<div class="trace-grid-header">Error trace</div>
<?php foreach ($trace as $index => $traceItem): ?>
<div class="trace-grid">
<?php if (isset($traceItem['file'])): ?>
<div class="trace-label">file</div>
<div class="trace-value"><?php echo $this->print($traceItem['file']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['line'])): ?>
<div class="trace-label">line</div>
<div class="trace-value"><?php echo $this->print($traceItem['line']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['function'])): ?>
<div class="trace-label">function</div>
<div class="trace-value"><?php echo $this->print($traceItem['function']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['args'])): ?>
<div class="trace-label">args</div>
<div class="trace-args"><pre><?php echo $this->print(\var_export($traceItem['args'], true)); ?></pre></div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
<div x-show="page === 'error'" class="brand">
<p>Powered by</p>
<svg class="logo-dark" width="110" height="20" viewBox="0 0 110 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M31.8649 16.2461C33.6492 16.2461 34.5511 15.3184 34.9433 14.6867H35.1197C35.1981 15.3578 35.6687 15.9895 36.5903 15.9895H38.3353V14.0156H37.8843C37.5706 14.0156 37.4138 13.838 37.4138 13.5617V5.64661H35.1001V6.90986H34.9236C34.4727 6.27823 33.5315 5.39001 31.8061 5.39001C29.0611 5.39001 27.022 7.67965 27.022 10.818C27.022 13.9564 29.1003 16.2461 31.8649 16.2461ZM32.2767 13.9959C30.6493 13.9959 29.3748 12.7919 29.3748 10.8378C29.3748 8.92316 30.6101 7.62044 32.2571 7.62044C33.8256 7.62044 35.1393 8.86395 35.1393 10.8378C35.1393 12.5945 34.0217 13.9959 32.2767 13.9959Z" fill="#EDEDF0" />
<path d="M39.7013 20H42.0149V14.6867H42.1914C42.6227 15.3184 43.5443 16.2461 45.3677 16.2461C48.1127 16.2461 50.1127 13.9169 50.1127 10.818C50.1127 7.69939 47.9755 5.39001 45.2109 5.39001C43.4462 5.39001 42.5835 6.35719 42.1718 6.89012H41.9953V5.63019H39.7013V20ZM44.8776 14.0551C43.2894 14.0551 41.9757 12.8708 41.9757 10.818C41.9757 9.06133 43.0933 7.58096 44.8383 7.58096C46.4657 7.58096 47.7402 8.86395 47.7402 10.818C47.7402 12.7326 46.5049 14.0551 44.8776 14.0551Z" fill="#EDEDF0" />
<path d="M51.3065 20H53.6202V14.6867H53.7966C54.228 15.3184 55.1495 16.2461 56.973 16.2461C59.718 16.2461 61.5273 13.9169 61.5273 10.818C61.5273 7.69939 59.5807 5.39001 56.8161 5.39001C55.0515 5.39001 54.1888 6.35719 53.777 6.89012H53.6005V5.64661H51.3065V20ZM56.4828 14.0551C54.8946 14.0551 53.5809 12.8708 53.5809 10.818C53.5809 9.06133 54.6985 7.58096 56.4436 7.58096C58.071 7.58096 59.3454 8.86395 59.3454 10.818C59.3454 12.7326 58.1102 14.0551 56.4828 14.0551Z" fill="#EDEDF0" />
<path d="M64.5857 16.2296H67.8601L69.7227 8.11721H69.8404L71.7031 16.2296H74.9579L77.5642 5.88678H75.2323L73.3697 14.0189H73.1932L71.3305 5.88678H68.2522L66.3699 14.0189H66.1935L64.3504 5.88678H61.8799L64.5857 16.2296Z" fill="#EDEDF0" />
<path d="M78.7363 16.2296H81.0499V11.1174C81.0499 9.16334 81.9519 7.9593 83.6381 7.9593H84.6576V5.63019H83.893C82.5793 5.63019 81.5793 6.53815 81.1872 7.40663H81.0303V5.88678H78.7363V16.2296Z" fill="#EDEDF0" />
<path d="M96.1391 16.2296H97.943V14.1571H96.1587C95.4529 14.1571 95.1588 13.8413 95.1588 13.111V7.93956H98.0606V5.88678H95.1588V2.98526H92.9628V5.88678H91.0413V7.93956H92.8255V13.1307C92.8255 15.3217 94.1392 16.2296 96.1391 16.2296Z" fill="#EDEDF0" />
<path d="M104.15 16.2461C106.287 16.2461 108.17 15.1802 108.836 13.0287L106.719 12.5155C106.346 13.6603 105.268 14.2525 104.13 14.2525C102.444 14.2525 101.327 13.1472 101.307 11.4102H109.091V10.7588C109.091 7.67965 107.189 5.39001 104.052 5.39001C101.287 5.39001 98.915 7.58096 98.915 10.8378C98.915 13.9959 101.013 16.2461 104.15 16.2461ZM101.327 9.71269C101.464 8.46918 102.581 7.42305 104.052 7.42305C105.464 7.42305 106.621 8.31128 106.738 9.71269H101.327Z" fill="#EDEDF0" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.0125 16.2296H87.6989V7.93956H85.895V5.88678H90.0125V16.2296Z" fill="#EDEDF0" />
<path d="M88.6834 4.45145C89.5265 4.45145 90.154 3.81983 90.154 2.99082C90.154 2.18155 89.5265 1.54993 88.6834 1.54993C87.8403 1.54993 87.2129 2.18155 87.2129 2.99082C87.2129 3.81983 87.8403 4.45145 88.6834 4.45145Z" fill="#EDEDF0" />
<path d="M20.2007 13.6935V18.258H8.88588C5.5894 18.258 2.71111 16.4222 1.17116 13.6935C0.947288 13.2968 0.751353 12.8806 0.586995 12.4486C0.26435 11.6021 0.0615332 10.6938 0 9.74603V8.51195C0.0133592 8.30074 0.03441 8.09119 0.0619381 7.88413C0.118209 7.45921 0.203222 7.04343 0.314953 6.63926C1.37195 2.80758 4.8089 0 8.88588 0C12.9629 0 16.3994 2.80758 17.4564 6.63926H12.6184C11.8241 5.39025 10.4493 4.5645 8.88588 4.5645C7.32245 4.5645 5.94767 5.39025 5.15341 6.63926C4.91132 7.01895 4.72349 7.43764 4.60042 7.88413C4.49112 8.27999 4.43282 8.69744 4.43282 9.12899C4.43282 10.4373 4.96962 11.6166 5.83027 12.4486C6.62778 13.2209 7.70299 13.6935 8.88588 13.6935H20.2007Z" fill="#FD366E" />
<path d="M20.2006 7.88412V12.4486H11.9414C12.8021 11.6166 13.3389 10.4373 13.3389 9.12899C13.3389 8.69744 13.2806 8.27999 13.1713 7.88412H20.2006Z" fill="#FD366E" />
</svg>
<svg class="logo-light" width="110" height="20" viewBox="0 0 110 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M31.8648 16.2461C33.649 16.2461 34.5509 15.3184 34.9431 14.6867H35.1195C35.198 15.3578 35.6685 15.9895 36.5901 15.9895H38.3351V14.0156H37.8841C37.5704 14.0156 37.4136 13.838 37.4136 13.5617V5.64661H35.0999V6.90986H34.9235C34.4725 6.27823 33.5314 5.39001 31.8059 5.39001C29.0609 5.39001 27.0218 7.67965 27.0218 10.818C27.0218 13.9564 29.1001 16.2461 31.8648 16.2461ZM32.2765 13.9959C30.6491 13.9959 29.3746 12.7919 29.3746 10.8378C29.3746 8.92316 30.6099 7.62044 32.2569 7.62044C33.8255 7.62044 35.1391 8.78499 35.1391 10.8378C35.1391 12.5945 34.0215 13.9959 32.2765 13.9959Z" fill="#2D2D31" />
<path d="M39.7011 20H42.0147V14.6867H42.1912C42.6226 15.3184 43.5441 16.2461 45.3676 16.2461C48.1126 16.2461 50.1125 13.9169 50.1125 10.818C50.1125 7.69939 47.9753 5.39001 45.2107 5.39001C43.4461 5.39001 42.5833 6.35719 42.1716 6.89012H41.9951V5.64661H39.7011V20ZM44.8774 14.0551C43.2892 14.0551 41.9755 12.8708 41.9755 10.818C41.9755 9.06133 43.0931 7.58096 44.8382 7.58096C46.4656 7.58096 47.74 8.86395 47.74 10.818C47.74 12.7326 46.5048 14.0551 44.8774 14.0551Z" fill="#2D2D31" />
<path d="M51.3063 20H53.62V14.6867H53.7964C54.2278 15.3184 55.1493 16.2461 56.9728 16.2461C59.7178 16.2461 61.5271 13.9169 61.5271 10.818C61.5271 7.69939 59.5805 5.39001 56.8159 5.39001C55.0513 5.39001 54.1886 6.35719 53.7768 6.89012H53.6004V5.64661H51.3063V20ZM56.4826 14.0551C54.8944 14.0551 53.5808 12.8708 53.5808 10.818C53.5808 9.06133 54.6984 7.58096 56.4434 7.58096C58.0708 7.58096 59.3453 8.86395 59.3453 10.818C59.3453 12.7326 58.11 14.0551 56.4826 14.0551Z" fill="#2D2D31" />
<path d="M64.5855 16.2296H67.8599L69.7226 8.11721H69.8402L71.7029 16.2296H74.9577L77.564 5.88678H75.2322L73.3695 14.0189H73.193L71.3303 5.88678H68.252L66.3697 14.0189H66.1933L64.3502 5.88678H61.8797L64.5855 16.2296Z" fill="#2D2D31" />
<path d="M78.7361 16.2296H81.0498V11.1174C81.0498 9.16334 81.9517 7.9593 83.6379 7.9593H84.6575V5.63019H83.8928C82.5791 5.63019 81.5791 6.53815 81.187 7.40663H81.0301V5.88678H78.7361V16.2296Z" fill="#2D2D31" />
<path d="M96.1389 16.2296H97.9428V14.1571H96.1585C95.4527 14.1571 95.1586 13.8413 95.1586 13.111V7.93956H98.0604V5.88678H95.1586V2.98526H92.9626V5.88678H91.0411V7.93956H92.8253V13.1307C92.8253 15.3217 94.139 16.2296 96.1389 16.2296Z" fill="#2D2D31" />
<path d="M104.15 16.2461C106.287 16.2461 108.169 15.1802 108.836 13.0287L106.718 12.5155C106.346 13.6603 105.268 14.2525 104.13 14.2525C102.444 14.2525 101.326 13.1472 101.307 11.4102H109.091V10.7588C109.091 7.67965 107.189 5.39001 104.052 5.39001C101.287 5.39001 98.9148 7.58096 98.9148 10.8378C98.9148 13.9959 101.013 16.2461 104.15 16.2461ZM101.326 9.71269C101.464 8.46918 102.581 7.42305 104.052 7.42305C105.464 7.42305 106.62 8.31128 106.738 9.71269H101.326Z" fill="#2D2D31" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.0123 16.2296H87.6987V7.93956H85.8948V5.88678H90.0123V16.2296Z" fill="#2D2D31" />
<path d="M88.6835 4.45145C89.5266 4.45145 90.154 3.81983 90.154 2.99082C90.154 2.18155 89.5266 1.54993 88.6835 1.54993C87.8404 1.54993 87.213 2.18155 87.213 2.99082C87.213 3.81983 87.8404 4.45145 88.6835 4.45145Z" fill="#2D2D31" />
<path d="M20.2007 13.6935V18.258H8.88588C5.5894 18.258 2.71111 16.4222 1.17116 13.6935C0.947288 13.2968 0.751353 12.8806 0.586995 12.4486C0.26435 11.6021 0.0615332 10.6938 0 9.74603V8.51195C0.0133592 8.30074 0.03441 8.09119 0.0619381 7.88413C0.118209 7.45921 0.203222 7.04343 0.314953 6.63926C1.37195 2.80758 4.8089 0 8.88588 0C12.9629 0 16.3994 2.80758 17.4564 6.63926H12.6184C11.8241 5.39025 10.4493 4.5645 8.88588 4.5645C7.32245 4.5645 5.94767 5.39025 5.15341 6.63926C4.91132 7.01895 4.72349 7.43764 4.60042 7.88413C4.49112 8.27999 4.43282 8.69744 4.43282 9.12899C4.43282 10.4373 4.96962 11.6166 5.83027 12.4486C6.62778 13.2209 7.70299 13.6935 8.88588 13.6935H20.2007Z" fill="#FD366E" />
<path d="M20.2007 7.88412V12.4486H11.9415C12.8022 11.6166 13.339 10.4373 13.339 9.12899C13.339 8.69744 13.2807 8.27999 13.1714 7.88412H20.2007Z" fill="#FD366E" />
</svg>
</div>
<script type="text/javascript">
const app = (JSON.parse(localStorage.getItem('appwrite')) ?? {});
const theme = app.theme ?? 'auto';
if (theme === 'auto') {
const darkThemeMq = window.matchMedia('(prefers-color-scheme: dark)');
if (darkThemeMq.matches) {
document.body.setAttribute('class', `theme-dark`);
} else {
document.body.setAttribute('class', `theme-light`);
}
} else {
document.body.setAttribute('class', `theme-${theme}`);
}
</script>
</body>
</html>
+46 -14
View File
@@ -65,6 +65,8 @@ $image = $this->getParam('image', '');
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
- appwrite-functions:/storage/functions:rw
- appwrite-sites:/storage/sites:rw
- appwrite-builds:/storage/builds:rw
depends_on:
- mariadb
- redis
@@ -86,10 +88,12 @@ $image = $this->getParam('image', '');
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -134,13 +138,14 @@ $image = $this->getParam('image', '');
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_COMPUTE_SIZE_LIMIT
- _APP_COMPUTE_TIMEOUT
- _APP_FUNCTIONS_TIMEOUT
- _APP_SITES_TIMEOUT
- _APP_COMPUTE_BUILD_TIMEOUT
- _APP_COMPUTE_CPUS
- _APP_COMPUTE_MEMORY
- _APP_FUNCTIONS_RUNTIMES
- _APP_SITES_FRAMEWORKS
- _APP_SITES_RUNTIMES
- _APP_DOMAIN_SITES
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_LOGGING_CONFIG
@@ -150,6 +155,7 @@ $image = $this->getParam('image', '');
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_SMS_PROVIDER
@@ -166,11 +172,10 @@ $image = $this->getParam('image', '');
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
- _APP_ASSISTANT_OPENAI_API_KEY
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: <?php echo $organization; ?>/console:5.2.27
image: <?php echo $organization; ?>/console:5.2.53
restart: unless-stopped
networks:
- appwrite
@@ -301,6 +306,7 @@ $image = $this->getParam('image', '');
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
- appwrite-functions:/storage/functions:rw
- appwrite-sites:/storage/sites:rw
- appwrite-builds:/storage/builds:rw
- appwrite-certificates:/storage/certificates:rw
environment:
@@ -343,7 +349,10 @@ $image = $this->getParam('image', '');
- _APP_EXECUTOR_HOST
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_EMAIL_CERTIFICATES
appwrite-worker-databases:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
@@ -384,7 +393,9 @@ $image = $this->getParam('image', '');
- mariadb
volumes:
- appwrite-functions:/storage/functions:rw
- appwrite-sites:/storage/sites:rw
- appwrite-builds:/storage/builds:rw
- appwrite-uploads:/storage/uploads:rw
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -404,13 +415,14 @@ $image = $this->getParam('image', '');
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_COMPUTE_TIMEOUT
- _APP_FUNCTIONS_TIMEOUT
- _APP_SITES_TIMEOUT
- _APP_COMPUTE_BUILD_TIMEOUT
- _APP_COMPUTE_CPUS
- _APP_COMPUTE_MEMORY
- _APP_COMPUTE_SIZE_LIMIT
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
- _APP_DOMAIN
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
@@ -434,6 +446,7 @@ $image = $this->getParam('image', '');
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_DOMAIN_SITES
appwrite-worker-certificates:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
@@ -454,7 +467,9 @@ $image = $this->getParam('image', '');
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_FUNCTIONS
- _APP_EMAIL_CERTIFICATES
- _APP_REDIS_HOST
@@ -495,7 +510,8 @@ $image = $this->getParam('image', '');
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_COMPUTE_TIMEOUT
- _APP_FUNCTIONS_TIMEOUT
- _APP_SITES_TIMEOUT
- _APP_COMPUTE_BUILD_TIMEOUT
- _APP_COMPUTE_CPUS
- _APP_COMPUTE_MEMORY
@@ -606,7 +622,9 @@ $image = $this->getParam('image', '');
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_EMAIL_SECURITY
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -635,7 +653,9 @@ $image = $this->getParam('image', '');
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
@@ -652,6 +672,7 @@ $image = $this->getParam('image', '');
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
@@ -854,6 +875,14 @@ $image = $this->getParam('image', '');
- appwrite
environment:
- _APP_ASSISTANT_OPENAI_API_KEY
appwrite-browser:
image: appwrite/browser:0.2.2
container_name: appwrite-browser
<<: *x-logging
restart: unless-stopped
networks:
- appwrite
openruntimes-executor:
container_name: openruntimes-executor
@@ -861,7 +890,7 @@ $image = $this->getParam('image', '');
<<: *x-logging
restart: unless-stopped
stop_signal: SIGINT
image: openruntimes/executor:0.7.0
image: openruntimes/executor:0.7.13
networks:
- appwrite
- runtimes
@@ -869,6 +898,7 @@ $image = $this->getParam('image', '');
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-builds:/storage/builds:rw
- appwrite-functions:/storage/functions:rw
- appwrite-sites:/storage/sites:rw
# Host mount nessessary to share files between executor and runtimes.
# It's not possible to share mount file between 2 containers without host mount (copying is too slow)
- /tmp:/tmp:rw
@@ -879,8 +909,9 @@ $image = $this->getParam('image', '');
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
- OPR_EXECUTOR_ENV=$_APP_ENV
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES,$_APP_SITES_RUNTIMES
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
- OPR_EXECUTOR_RUNTIME_VERSIONS=v5
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
@@ -961,5 +992,6 @@ volumes:
appwrite-uploads:
appwrite-certificates:
appwrite-functions:
appwrite-sites:
appwrite-builds:
appwrite-config:
+22 -10
View File
@@ -16,10 +16,9 @@ use Appwrite\Event\Migration;
use Appwrite\Event\Realtime;
use Appwrite\Event\StatsUsage;
use Appwrite\Event\StatsUsageDump;
/** remove */
/** /remove */
use Appwrite\Event\Webhook;
use Appwrite\Platform\Appwrite;
use Executor\Executor;
use Swoole\Runtime;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\Cache\Adapter\Sharding;
@@ -112,6 +111,8 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register,
->setNamespace('_' . $project->getInternalId());
}
$database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
return $database;
}, ['cache', 'register', 'message', 'project', 'dbForPlatform']);
@@ -173,6 +174,8 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf
->setNamespace('_' . $project->getInternalId());
}
$database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
return $database;
};
}, ['pools', 'dbForPlatform', 'cache']);
@@ -198,7 +201,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
$database
->setSharedTables(true)
->setNamespace('logsV1')
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS)
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
// set tenant
@@ -211,15 +214,18 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
}, ['pools', 'cache']);
Server::setResource('abuseRetention', function () {
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400);
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day
});
Server::setResource('auditRetention', function () {
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600));
});
Server::setResource('auditRetention', function (Document $project) {
if ($project->getId() === 'console') {
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE', 15778800)); // 6 months
}
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600)); // 14 days
}, ['project']);
Server::setResource('executionRetention', function () {
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600));
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600)); // 14 days
});
Server::setResource('cache', function (Registry $register) {
@@ -337,6 +343,10 @@ Server::setResource('deviceForSites', function (Document $project) {
return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId());
}, ['project']);
Server::setResource('deviceForImports', function (Document $project) {
return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId());
}, ['project']);
Server::setResource('deviceForFunctions', function (Document $project) {
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
}, ['project']);
@@ -368,7 +378,7 @@ Server::setResource('certificates', function () {
});
Server::setResource('logError', function (Registry $register, Document $project) {
return function (Throwable $error, string $namespace, string $action, ?array $extras) use ($register, $project) {
return function (Throwable $error, string $namespace, string $action, ?array $extras = null) use ($register, $project) {
$logger = $register->get('logger');
if ($logger) {
@@ -390,7 +400,7 @@ Server::setResource('logError', function (Registry $register, Document $project)
$log->addExtra('trace', $error->getTraceAsString());
foreach ($extras as $key => $value) {
foreach (($extras ?? []) as $key => $value) {
$log->addExtra($key, $value);
}
@@ -412,6 +422,8 @@ Server::setResource('logError', function (Registry $register, Document $project)
};
}, ['register', 'project']);
Server::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
$pools = $register->get('pools');
$platform = new Appwrite();
$args = $platform->getEnv('argv');
+11 -11
View File
@@ -44,37 +44,37 @@
"ext-openssl": "*",
"ext-zlib": "*",
"ext-sockets": "*",
"appwrite/php-runtimes": "0.18.*",
"appwrite/php-runtimes": "0.19.*",
"appwrite/php-clamav": "2.0.*",
"utopia-php/abuse": "0.51.*",
"utopia-php/abuse": "0.52.*",
"utopia-php/analytics": "0.10.*",
"utopia-php/audit": "0.54.0",
"utopia-php/audit": "0.55.*",
"utopia-php/cache": "0.12.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/detector": "0.1.*",
"utopia-php/database": "0.60.*",
"utopia-php/database": "0.66.*",
"utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
"utopia-php/fetch": "0.3.*",
"utopia-php/fetch": "0.4.*",
"utopia-php/image": "0.8.*",
"utopia-php/locale": "0.4.*",
"utopia-php/logger": "0.6.*",
"utopia-php/messaging": "0.16.*",
"utopia-php/migration": "0.6.*",
"utopia-php/migration": "0.9.1",
"utopia-php/orchestration": "0.9.*",
"utopia-php/platform": "0.7.3",
"utopia-php/pools": "0.5.*",
"utopia-php/platform": "0.7.*",
"utopia-php/pools": "0.8.*",
"utopia-php/preloader": "0.2.*",
"utopia-php/queue": "0.8.*",
"utopia-php/queue": "0.9.*",
"utopia-php/registry": "0.5.*",
"utopia-php/storage": "0.18.*",
"utopia-php/swoole": "0.8.*",
"utopia-php/system": "0.9.*",
"utopia-php/telemetry": "0.1.*",
"utopia-php/vcs": "0.9.*",
"utopia-php/websocket": "0.1.*",
"utopia-php/vcs": "0.10.*",
"utopia-php/websocket": "0.3.*",
"matomo/device-detector": "6.1.*",
"dragonmantank/cron-expression": "3.3.2",
"phpmailer/phpmailer": "6.9.1",
Generated
+165 -442
View File
File diff suppressed because it is too large Load Diff
+37 -16
View File
@@ -72,6 +72,7 @@ services:
- traefik.http.routers.appwrite_api_https.tls=true
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-imports:/storage/imports:rw
- appwrite-cache:/storage/cache:rw
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
@@ -112,10 +113,12 @@ services:
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -160,13 +163,13 @@ services:
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_COMPUTE_SIZE_LIMIT
- _APP_COMPUTE_TIMEOUT
- _APP_FUNCTIONS_TIMEOUT
- _APP_SITES_TIMEOUT
- _APP_COMPUTE_BUILD_TIMEOUT
- _APP_COMPUTE_CPUS
- _APP_COMPUTE_MEMORY
- _APP_FUNCTIONS_RUNTIMES
- _APP_SITES_RUNTIMES
- _APP_SITES_FRAMEWORKS
- _APP_DOMAIN_SITES
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
@@ -176,6 +179,7 @@ services:
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_SMS_PROVIDER
@@ -202,11 +206,13 @@ services:
- _APP_DATABASE_SHARED_TABLES_V1
- _APP_DATABASE_SHARED_NAMESPACE
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
extra_hosts:
- "host.docker.internal:host-gateway"
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: appwrite/console:5.3.0-sites-rc.24
image: appwrite/console:5.3.0-sites-rc.40
restart: unless-stopped
networks:
- appwrite
@@ -395,6 +401,8 @@ services:
- _APP_DATABASE_SHARED_TABLES
- _APP_DATABASE_SHARED_TABLES_V1
- _APP_EMAIL_CERTIFICATES
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
appwrite-worker-databases:
entrypoint: worker-databases
@@ -463,13 +471,14 @@ services:
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_COMPUTE_TIMEOUT
- _APP_FUNCTIONS_TIMEOUT
- _APP_SITES_TIMEOUT
- _APP_COMPUTE_BUILD_TIMEOUT
- _APP_COMPUTE_CPUS
- _APP_COMPUTE_MEMORY
- _APP_COMPUTE_SIZE_LIMIT
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
- _APP_DOMAIN
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
@@ -495,6 +504,8 @@ services:
- _APP_STORAGE_WASABI_BUCKET
- _APP_DATABASE_SHARED_TABLES
- _APP_DOMAIN_SITES
extra_hosts:
- "host.docker.internal:host-gateway"
appwrite-worker-certificates:
entrypoint: worker-certificates
@@ -516,7 +527,9 @@ services:
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_FUNCTIONS
- _APP_EMAIL_CERTIFICATES
- _APP_REDIS_HOST
@@ -560,7 +573,8 @@ services:
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_COMPUTE_TIMEOUT
- _APP_FUNCTIONS_TIMEOUT
- _APP_SITES_TIMEOUT
- _APP_COMPUTE_BUILD_TIMEOUT
- _APP_COMPUTE_CPUS
- _APP_COMPUTE_MEMORY
@@ -671,6 +685,7 @@ services:
networks:
- appwrite
volumes:
- appwrite-imports:/storage/imports:rw
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
- ./tests:/usr/src/code/tests
@@ -681,7 +696,9 @@ services:
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_EMAIL_SECURITY
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -713,7 +730,9 @@ services:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
@@ -730,6 +749,7 @@ services:
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_MAINTENANCE_DELAY
@@ -765,7 +785,7 @@ services:
- _APP_LOGGING_CONFIG
- _APP_DATABASE_SHARED_TABLES
- _APP_STATS_RESOURCES_INTERVAL
appwrite-worker-stats-resources:
entrypoint: worker-stats-resources
<<: *x-logging
@@ -796,7 +816,7 @@ services:
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
- _APP_DATABASE_SHARED_TABLES
appwrite-worker-stats-usage:
entrypoint: worker-stats-usage
<<: *x-logging
@@ -859,7 +879,7 @@ services:
- _APP_USAGE_AGGREGATION_INTERVAL
- _APP_DATABASE_SHARED_TABLES
- _APP_STATS_USAGE_DUAL_WRITING_DBS
appwrite-task-scheduler-functions:
entrypoint: schedule-functions
<<: *x-logging
@@ -962,7 +982,7 @@ services:
hostname: exc1
<<: *x-logging
stop_signal: SIGINT
image: openruntimes/executor:0.7.10
image: openruntimes/executor:0.7.13
restart: unless-stopped
networks:
- appwrite
@@ -1141,8 +1161,9 @@ volumes:
appwrite-redis:
appwrite-cache:
appwrite-uploads:
appwrite-imports:
appwrite-certificates:
appwrite-functions:
appwrite-sites:
appwrite-builds:
appwrite-config:
appwrite-config:
@@ -0,0 +1 @@
Import documents from a CSV file into your Appwrite database. This endpoint allows you to import documents from a CSV file uploaded to Appwrite Storage bucket.
+4 -4
View File
@@ -59,7 +59,7 @@ My Awesome Function
You can now deploy this function using
```sh
$ appwrite deploy function
$ appwrite push function
? Which functions would you like to deploy? My Awesome Function (61d1a4c81dfcd95bc834)
Info Deploying function My Awesome Function ( 61d1a4c81dfcd95bc834 )
@@ -73,7 +73,7 @@ Your function has now been deployed on your Appwrite server! As soon as the buil
Similarly, you can deploy all your collections to your Appwrite server using
```sh
appwrite deploy collections
appwrite push collections
```
> ### Note
@@ -98,7 +98,7 @@ $ appwrite users list
To create a document you can use the following command
```sh
$ appwrite database createDocument --collectionId <ID> --documentId 'unique()' --data '{ "Name": "Iron Man" }' --permissions 'read("any")' 'read("team:abc")'
$ appwrite databases create-document --database-id <DATABASE_ID> --collection-id <COLLECTION_ID> --document-id "unique()" --data '{"name": "Walter O Brein"}' --permissions 'read("any")' 'read("team:abc")'
```
### Some Gotchas
@@ -140,4 +140,4 @@ The Appwrite CLI can also work in a CI environment. The initialisation of the CL
```sh
appwrite client --endpoint http://localhost/v1 --projectId <PROJECT_ID> --key <API KEY>
```
```
+12
View File
@@ -1,3 +1,15 @@
## 14.0.0
* Breaking changes:
* Changed the typing of `AppwriteException`'s response parameter from a `dynamic` object to an optional string (`?String`).
## 13.0.0
* Fixed realtime pong response.
* Fixed issues with `chunkedUpload` method.
* Fixed type mismatch bug where `List<dynamic>` was incorrectly causing runtime type errors.
* Updated return type of `updateMfaChallenge()` from raw data to properly typed `models.Session` object.
## 12.0.0
* Support for Appwrite 1.6
+10
View File
@@ -1,3 +1,13 @@
## 15.0.0
* Breaking changes:
* Changed the typing of `AppwriteException`'s response parameter from a `dynamic` object to an optional string (`?String`).
## 14.0.0
* Fixed realtime pong response.
* Fixed issues with `chunkedUpload` method.
## 13.0.0
* Fixed realtime reconnection issues
+1 -1
View File
@@ -6,7 +6,7 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
stopOnFailure="true"
>
<extensions>
<extension class="Appwrite\Tests\TestHook" />
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Some files were not shown because too many files have changed in this diff Show More