Compare commits

...
Author SHA1 Message Date
Jake BarnbyandGitHub c3e338ca00 Merge pull request #11389 from appwrite/multitypedb-with-dedicated-db 2026-02-27 07:09:09 +00:00
ArnabChatterjee20k 8d028066ae update transaction not to start if there is no operation in the logs 2026-02-25 15:44:14 +05:30
ArnabChatterjee20k bd4adad545 refractored transaction update 2026-02-25 12:49:27 +05:30
ArnabChatterjee20k c40f9b1de0 addressed comments 2026-02-24 18:23:52 +05:30
ArnabChatterjee20k 8237250453 refactor: streamline database DSN handling and remove deprecated attributes 2026-02-24 17:40:50 +05:30
ArnabChatterjee20k c8a7ed2022 updated migration to remove the dependency on dsn at project level attribute 2026-02-24 10:43:10 +05:30
ArnabChatterjee20k 4847c5a308 changed deps so that create document depends on test create collection 2026-02-23 13:27:01 +05:30
ArnabChatterjee20k f6985bae41 updated lock 2026-02-23 13:15:52 +05:30
ArnabChatterjee20k cc9df4f5c5 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-23 13:09:49 +05:30
ArnabChatterjee20k 83b7b4e599 updated 2026-02-23 13:05:12 +05:30
ArnabChatterjee20k fdc573009c updated tests 2026-02-20 16:53:46 +05:30
ArnabChatterjee20k 51d769b0a1 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-20 13:58:56 +05:30
ArnabChatterjee20k f6b04d05b2 updated composer lock 2026-02-18 16:10:13 +05:30
ArnabChatterjee20k 2926412604 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-18 16:07:44 +05:30
ArnabChatterjee20k ee21b1feda updated composer 2026-02-18 16:06:31 +05:30
ArnabChatterjee20k 2d0140f705 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-18 16:01:55 +05:30
ArnabChatterjee20k 183bd4143c updated tests 2026-02-16 18:36:42 +05:30
ArnabChatterjee20k 57ac67a106 linting and updated timeouts 2026-02-16 16:23:38 +05:30
ArnabChatterjee20k 4b6d809a3b updated docker compose 2026-02-16 16:09:15 +05:30
ArnabChatterjee20k 0221556ae7 Merge remote-tracking branch 'origin/documents-db-api' into documents-db-api 2026-02-16 15:16:51 +05:30
ArnabChatterjee20k 6a1955d20d updated tests 2026-02-16 15:16:04 +05:30
ArnabChatterjee20kandGitHub 8c7d2c58f5 Merge branch '1.8.x' into documents-db-api 2026-02-16 14:30:53 +05:30
ArnabChatterjee20k 5b7746b464 empty 2026-02-16 14:12:46 +05:30
ArnabChatterjee20k e6e0cef91e linting 2026-02-16 13:55:34 +05:30
ArnabChatterjee20k bdc4c4a18d Merge remote-tracking branch 'origin/documents-db-api' into documents-db-api 2026-02-16 13:53:21 +05:30
ArnabChatterjee20k 49efa02e09 synced documents db and vectordb with 1.8.x 2026-02-16 13:52:16 +05:30
ArnabChatterjee20k fd96bcbd3f Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-16 12:20:53 +05:30
Jake BarnbyandGitHub 9647c3fa7d Merge pull request #11310 from appwrite/database-type-filters 2026-02-12 09:38:45 +00:00
Darshan 1e411bbef5 update: lint. 2026-02-12 13:25:44 +05:30
Darshan 7c47a4db72 add: filtering. 2026-02-12 13:22:07 +05:30
ArnabChatterjee20k ae33104ecf added admin auth to the index creation 2026-02-11 18:19:46 +05:30
ArnabChatterjee20k b90a9e8cab added admin auth to the index creation 2026-02-11 16:49:33 +05:30
ArnabChatterjee20k 4024cf0492 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-11 16:22:37 +05:30
ArnabChatterjee20k e07f9a7b49 added admin auth to vector db 2026-02-11 14:04:14 +05:30
ArnabChatterjee20k 61f778196b Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-11 13:58:43 +05:30
ArnabChatterjee20k 93897f86d0 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-02-10 15:34:51 +05:30
ArnabChatterjee20k 095e08441f added get databases db in the document logs 2026-02-10 13:33:29 +05:30
ArnabChatterjee20k da63463a3c updated migration 2026-02-10 11:20:53 +05:30
ArnabChatterjee20k 8e140bae6c updated project and migraiton worker 2026-02-09 17:43:42 +05:30
ArnabChatterjee20k 3b2eb02f8a Merge branch '1.8.x' into documents-db-api 2026-02-09 17:27:09 +05:30
ArnabChatterjee20k e53f5b4023 add admin permission to create 2026-01-28 19:06:19 +05:30
ArnabChatterjee20k 02cddb5c08 updated the format specs 2026-01-28 10:55:19 +05:30
ArnabChatterjee20k cb4d11a1d4 updated 2026-01-27 18:13:27 +05:30
ArnabChatterjee20k 139535e83c updated 2026-01-27 17:18:24 +05:30
ArnabChatterjee20k b9e95f6d82 updated 2026-01-27 17:17:23 +05:30
ArnabChatterjee20k 79cb668a50 updated composer lock 2026-01-27 16:34:34 +05:30
ArnabChatterjee20k 8078516e2f fixed composer lock 2026-01-27 16:32:59 +05:30
ArnabChatterjee20k 1729bd23b2 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-01-27 16:29:25 +05:30
ArnabChatterjee20k ac7fc7ae69 linting 2026-01-22 12:47:26 +05:30
ArnabChatterjee20k 4b570dc3f0 updetad pools 2026-01-22 12:41:18 +05:30
ArnabChatterjee20k aa3d66df7b Merge branch 'new-pool-adapter' into documents-db-api 2026-01-22 12:34:22 +05:30
ArnabChatterjee20k a16e05ed4d updated timeout 2026-01-21 13:36:35 +05:30
ArnabChatterjee20k 84dc5682d5 updated auth param 2026-01-21 12:31:42 +05:30
ArnabChatterjee20k a112de41c5 updated ollama timeout 2026-01-21 12:23:29 +05:30
ArnabChatterjee20k 02bba85fe7 updated migration tests for adding endpoint 2026-01-21 12:21:37 +05:30
ArnabChatterjee20k 56f68d33df updated migration 2026-01-21 11:44:13 +05:30
ArnabChatterjee20k d4edf9ed13 updated vectordb test 2026-01-20 20:10:57 +05:30
ArnabChatterjee20k 12b38e2a27 commenting mongodb out for now to check the issues on the ci 2026-01-20 19:45:19 +05:30
ArnabChatterjee20k 9f1807a128 linting and fixing resources timeout and validator 2026-01-20 19:41:52 +05:30
ArnabChatterjee20k 6bdfcc3fb5 fixed endpoint in migration 2026-01-20 18:44:54 +05:30
ArnabChatterjee20k d8dd1918c4 synced vectordb 2026-01-20 15:45:12 +05:30
ArnabChatterjee20k 376c5e47f5 added missing injections 2026-01-20 14:01:37 +05:30
ArnabChatterjee20k edfb9e0bd7 updated resources to use the listeners based on the databasetype 2026-01-20 13:56:52 +05:30
ArnabChatterjee20k eab4c7f28a Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-01-20 13:56:32 +05:30
ArnabChatterjee20k c361340252 linting 2026-01-19 18:45:05 +05:30
ArnabChatterjee20k 41e197003e fixed merge conflicts 2026-01-19 18:43:30 +05:30
ArnabChatterjee20k c7ba37ec49 fixed merge conflicts 2026-01-19 14:35:31 +05:30
ArnabChatterjee20k ba82aab563 Merge remote-tracking branch 'origin/1.8.x' into documents-db-api 2026-01-19 13:22:53 +05:30
ArnabChatterjee20k f580dc9145 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2026-01-13 14:32:46 +05:30
Jake BarnbyandGitHub 421dca2f99 Merge pull request #10653 from appwrite/vector-db-api
vectordb api endpoints
2025-12-10 10:59:58 +00:00
ArnabChatterjee20k 991b2b1c3b updated delete worker for vectordb and updated tests 2025-12-09 18:44:26 +05:30
ArnabChatterjee20k d22743a1cf Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-12-09 18:37:09 +05:30
ArnabChatterjee20k a2039c0b76 added deletion test for multidb 2025-12-09 18:34:25 +05:30
ArnabChatterjee20k c549ddd149 updated project deletion worker to delete per database 2025-12-09 18:27:10 +05:30
ArnabChatterjee20k f3721f712a fixed missing project usage fields 2025-12-09 15:38:43 +05:30
ArnabChatterjee20k 480757dcfe added usage test for the vectordb 2025-12-09 12:07:26 +05:30
ArnabChatterjee20k fbaeff8920 Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-12-08 20:31:07 +05:30
ArnabChatterjee20k de88ec4065 updated missing skip metrics and tablesdb tests 2025-12-08 20:30:37 +05:30
ArnabChatterjee20k f149ba33d4 updated stats for vectordb 2025-12-08 20:27:30 +05:30
ArnabChatterjee20k b15f2eed8f Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-12-08 19:32:21 +05:30
ArnabChatterjee20k ec63dc22d4 updated controllers 2025-12-08 19:09:54 +05:30
ArnabChatterjee20k 7c7b98399c linting 2025-12-08 17:51:01 +05:30
ArnabChatterjee20k 9d679e726e updated composer lock 2025-12-08 17:46:00 +05:30
ArnabChatterjee20k 070ec03c0c Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-12-08 17:31:04 +05:30
ArnabChatterjee20k be89224c36 updated console client test 2025-12-05 19:14:29 +05:30
ArnabChatterjee20k 8edd3c87cb added documentsdb total reads and writes in the project response 2025-12-05 19:09:35 +05:30
ArnabChatterjee20k 9ac3cd73a8 Refactor database metrics handling for DocumentsDB
- Introduced new methods to retrieve metrics for write and read operations based on database type.
- Updated bulk delete, update, upsert, and create actions to use the new metric methods.
- Enhanced document retrieval and update actions to utilize the new metric structure.
- Added support for DocumentsDB metrics in usage statistics and response models.
- Created new response models for DocumentsDB usage and updated existing models to accommodate new metrics.
- Adjusted migration and stats resources to include DocumentsDB metrics.
- Updated tests to validate the new metrics and ensure correct functionality for DocumentsDB usage.
2025-12-05 18:58:13 +05:30
ArnabChatterjee20k 203170c36d updated database and collection stats 2025-12-04 15:57:18 +05:30
ArnabChatterjee20k 6f5bfdb726 updated stats 2025-12-03 20:18:53 +05:30
b499857871 Update src/Appwrite/Utopia/Database/Validator/Queries/Base.php
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2025-12-03 19:12:56 +05:30
1388b0ca21 Update app/config/variables.php
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2025-12-03 19:12:38 +05:30
ArnabChatterjee20k af095bdf4a updated stats 2025-12-03 19:11:46 +05:30
ArnabChatterjee20k 7af361fa16 * added logger in the create text embedding
* aadded error text metric
2025-12-03 13:38:24 +05:30
ArnabChatterjee20k 069f231b3a updated composer lock 2025-12-02 18:40:28 +05:30
ArnabChatterjee20k def028e970 Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-12-02 18:38:21 +05:30
ArnabChatterjee20k 16f49d13c8 updated composer lock 2025-12-02 18:36:29 +05:30
ArnabChatterjee20k e72d7979e0 updated composer lock 2025-12-02 18:31:44 +05:30
ArnabChatterjee20k ca4c7b5361 added stats usage for text embeddings 2025-12-02 18:13:49 +05:30
ArnabChatterjee20k 7ad6bb048c merged 1.8.x 2025-12-02 16:35:40 +05:30
ArnabChatterjee20k d2c9ac079a Refactor VectorDB Embeddings API and Update Dimension Handling
- Updated the Create.php file to streamline the embedding creation process by removing unnecessary authentication checks and simplifying the parameter structure.
- Changed the parameter from 'documents' to 'texts' for clarity and adjusted the embedding model handling.
- Modified the response model to include error handling for embedding generation.
- Updated the Embedding response model to reflect changes in dimension naming and added error message handling.
- Refactored VectorDBCollection model to replace 'dimensions' with 'dimension' for consistency across the codebase.
- Adjusted all relevant tests to accommodate the new parameter names and response structures, ensuring comprehensive coverage for the updated functionality.
2025-12-02 14:20:25 +05:30
ArnabChatterjee20k abe1257bd5 Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-11-21 20:17:59 +05:30
ArnabChatterjee20k 3db22fd2db fixed enum route 2025-11-21 20:03:44 +05:30
ArnabChatterjee20k a423067b36 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-11-21 19:53:52 +05:30
ArnabChatterjee20k 33aab0357f updated tests 2025-11-21 19:52:28 +05:30
ArnabChatterjee20k 34e9c69a62 updated tests condition 2025-11-21 19:11:26 +05:30
ArnabChatterjee20k fdf5ca0067 updated tests condition 2025-11-21 19:08:35 +05:30
ArnabChatterjee20k 6eb17b847f updated composer 2025-11-21 18:06:32 +05:30
ArnabChatterjee20k 918ebb8ecc Add VectorDB text embedding creation endpoint and update related tests 2025-11-21 18:00:51 +05:30
ArnabChatterjee20k c0ac52810e Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-11-21 17:25:18 +05:30
ArnabChatterjee20k b658cddc71 updated get project dsn to be of the project db type(dedicate, shared) so that databasesdb and projectdb are not in conflict 2025-11-21 17:22:19 +05:30
ArnabChatterjee20k fe753db78c Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-11-20 18:57:38 +05:30
ArnabChatterjee20k 2f1e47e35a updated migrations 2025-11-20 18:56:14 +05:30
ArnabChatterjee20k c3ad337398 updated migrations for vectordb importing/exporting in csv endpoints 2025-11-20 18:54:41 +05:30
ArnabChatterjee20k cc759868b8 Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-11-20 15:51:01 +05:30
ArnabChatterjee20k 1004435e9e skipped operator tests for mongodb 2025-11-20 14:07:05 +05:30
ArnabChatterjee20k a9e749a81f updated migration service extractor for csv import/export 2025-11-20 14:06:42 +05:30
ArnabChatterjee20k 553fe15ba9 resolved merge conflicts 2025-11-19 20:01:02 +05:30
ArnabChatterjee20k fec758d237 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-11-19 20:00:17 +05:30
ArnabChatterjee20k 70a1d5d0f7 updated composer lock 2025-11-14 21:33:17 +05:30
ArnabChatterjee20k c66308e4e9 Merge remote-tracking branch 'upstream/documents-db-api' into vector-db-api 2025-11-14 21:28:40 +05:30
ArnabChatterjee20k 21aae468f2 updated database type function 2025-11-14 19:35:53 +05:30
ArnabChatterjee20k f007b83ccc updated composer 2025-11-14 19:18:03 +05:30
ArnabChatterjee20k 28be12d827 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-11-14 19:16:08 +05:30
ArnabChatterjee20k 93bd6b39a4 updated migrations + index finding issue in vectordb 2025-11-13 16:47:00 +05:30
ArnabChatterjee20k 75045ffd58 added constants for the vector dimension 2025-11-12 16:28:58 +05:30
ArnabChatterjee20k ed8419986a linting 2025-11-12 16:23:59 +05:30
ArnabChatterjee20k 954011b2c4 added transactions for vectordb 2025-11-12 16:21:27 +05:30
ArnabChatterjee20k c3f221f1fb added timestamp mutation test 2025-11-07 13:13:13 +05:30
ArnabChatterjee20k de59f53de3 reverted error tracing 2025-11-06 18:25:01 +05:30
ArnabChatterjee20k 04b169fab8 updated composer packages 2025-11-06 18:01:01 +05:30
ArnabChatterjee20k 857ec3b099 reverted docker compose 2025-11-06 17:54:21 +05:30
ArnabChatterjee20k b1dd377b67 Merge branch 'documents-db-api' into vector-db-api 2025-11-06 17:52:14 +05:30
ArnabChatterjee20k 81128e8446 reverted changes 2025-11-06 17:51:33 +05:30
ArnabChatterjee20k 86371e2082 Merge branch 'documents-db-api' into vector-db-api 2025-11-06 17:50:14 +05:30
ArnabChatterjee20k bd6f62dd68 updated realtime, create endpoint , resources, registers 2025-11-06 17:48:39 +05:30
ArnabChatterjee20k d2275c05fb updated tests 2025-11-05 20:34:12 +05:30
ArnabChatterjee20k 4988881568 updated method names and sdk namespaces for vectordb 2025-11-03 11:17:57 +05:30
ArnabChatterjee20k f9be1ddfc5 added vector embedding creation + update endpoint 2025-10-31 19:07:34 +05:30
ArnabChatterjee20k 60e95458a7 vector db endpoints
* configs and default attributes + indexes
* separate collection creation setup
* fix -> database metadata fix on collection creation
2025-10-31 18:01:47 +05:30
ArnabChatterjee20k 2bb6b0a2a9 updated database dsn for create in the create database 2025-10-31 16:45:01 +05:30
ArnabChatterjee20k 3311bd27cb Merge branch 'documents-db-api' into vector-db-api 2025-10-31 16:35:00 +05:30
ArnabChatterjee20k 5d9ef0dcca added metadata create on database 2025-10-31 16:33:54 +05:30
ArnabChatterjee20k 7ddecdd9ef Merge branch 'documents-db-api' into vector-db-api 2025-10-31 10:45:58 +05:30
ArnabChatterjee20k c8f966b0e5 added the default database type for the transactions context 2025-10-30 13:44:26 +05:30
ArnabChatterjee20k 3d2f21be7c updated composer lock 2025-10-30 13:02:49 +05:30
ArnabChatterjee20k 3e876f5bd8 fixed merge conflicts 2025-10-30 12:57:41 +05:30
ArnabChatterjee20k a5e56438c7 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-30 12:35:57 +05:30
ArnabChatterjee20k 4e79259c4e Refactor database handling to streamline DSN retrieval for documents and tables databases 2025-10-30 12:27:52 +05:30
ArnabChatterjee20k fae79e5c3f updated tests from feat-mongodb branch 2025-10-29 13:49:18 +05:30
ArnabChatterjee20k b169be9dda updated migration merge conflicts 2025-10-29 11:41:46 +05:30
ArnabChatterjee20k 8f4496346d Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-28 18:41:03 +05:30
ArnabChatterjee20k f306c03030 updated tests and index creation 2025-10-28 18:32:17 +05:30
ArnabChatterjee20k a8469a9b92 updated composer lock 2025-10-27 18:10:41 +05:30
ArnabChatterjee20k b63510acb5 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-27 18:10:08 +05:30
ArnabChatterjee20k 3e612ec88d flask test fixing via retry 2025-10-27 18:08:44 +05:30
ArnabChatterjee20k 1be36ae552 updated deps 2025-10-27 16:19:04 +05:30
ArnabChatterjee20k 445b657207 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-27 16:15:10 +05:30
ArnabChatterjee20k 5098973e0d reverted longtext resource file 2025-10-17 18:14:16 +05:30
ArnabChatterjee20k d0976ff429 updated registers config 2025-10-17 14:16:45 +05:30
ArnabChatterjee20k 157783f782 merged feat-mongodb 2025-10-17 13:58:27 +05:30
ArnabChatterjee20k e3a70373e1 updated docuemntsdb transaction path names 2025-10-16 22:19:53 +05:30
ArnabChatterjee20k a6e5563f8e reverted docker compose 2025-10-16 21:51:56 +05:30
ArnabChatterjee20k 470d84a843 * updated transactions
* updated tests
2025-10-16 21:45:30 +05:30
ArnabChatterjee20k 80037f7e8d updated http php for mongodb setup 2025-10-16 15:57:13 +05:30
ArnabChatterjee20k cc848c90a7 updated lock file 2025-10-16 14:25:22 +05:30
ArnabChatterjee20k e0c293c5b4 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-16 14:25:14 +05:30
ArnabChatterjee20k 2d82013261 updated docker compose setup for mongodb which was causing issue for mongo transactions 2025-10-16 14:22:28 +05:30
ArnabChatterjee20k 5a6561f158 vectordb (in progress)
* pools , env setup
* collections, db endpoints
2025-10-16 12:53:39 +05:30
ArnabChatterjee20k f28588ecb6 updated migration 2025-10-15 14:24:59 +05:30
ArnabChatterjee20k 6579ea5b56 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-15 14:16:49 +05:30
ArnabChatterjee20k 9373688be2 updated migration worker to pass the dsn resolver for the destination database 2025-10-15 10:33:46 +05:30
ArnabChatterjee20k 2cec06be18 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-14 21:18:38 +05:30
ArnabChatterjee20k 3a60bb306c * updated migration tests
* database dsn fetching
* removed dsn from response models
2025-10-14 21:13:26 +05:30
ArnabChatterjee20k e2ddb0d6d0 updated migration 2025-10-14 13:23:48 +05:30
Darshan 0049265c8a Merge remote-tracking branch 'origin/documents-db-api' into documents-db-api 2025-10-14 12:49:41 +05:30
Darshan 1f27867565 update: method name. 2025-10-14 12:49:34 +05:30
ArnabChatterjee20k faf0cdec35 changed default fallbackForDB to mariadb 2025-10-14 12:46:01 +05:30
ArnabChatterjee20k 6073eab496 * updated env to have mongodb support for the tablesdb/legacy
* setAttributeSupport to support context schema and schemaless in mongodb
* updated the connection registers
2025-10-13 15:47:40 +05:30
ArnabChatterjee20k 50ddc611a4 updated migrations 2025-10-12 20:49:02 +05:30
ArnabChatterjee20k 0ef2cfa753 reverted docker compose 2025-10-12 20:26:39 +05:30
ArnabChatterjee20k 790e503ad9 updated composer lock 2025-10-12 20:19:57 +05:30
ArnabChatterjee20k f6dbc0c882 Merge remote-tracking branch 'upstream/feat-mongodb' into documents-db-api 2025-10-12 20:17:53 +05:30
ArnabChatterjee20k a6c226aac9 removed the documentsdb changes from the migration tests 2025-10-10 20:38:54 +05:30
ArnabChatterjee20k 2d41a3353d * migration fix for tablesdb, legacy with multitype callback
* updated patch script
2025-10-10 20:29:05 +05:30
ArnabChatterjee20k 34e4208b3e addressed comments
* renamed getDatabaseDB to getDatabasesDB
* renamed dbForDatabase to dbForDatabases
* removed call_user_func and using newer callable syntax
2025-10-10 20:00:43 +05:30
ArnabChatterjee20k d51486c62a * fixed stats usage events(hacky fix)
* updated redundant routes(happened during merge conflicts)
2025-10-10 19:39:59 +05:30
ArnabChatterjee20k f62f00d4d9 Merge remote-tracking branch 'upstream/documents-db-api' into documents-db-api 2025-10-10 15:26:33 +05:30
ArnabChatterjee20k 44e6ef3146 event generation fix 2025-10-10 15:24:42 +05:30
Jake BarnbyandGitHub dea49d54c9 Merge pull request #10628 from appwrite/fix-enums
Update: enums
2025-10-10 22:16:45 +13:00
Darshan 8a9523fa48 update: enums. 2025-10-10 14:40:26 +05:30
Darshan 5dba0183c0 update: enums. 2025-10-10 14:40:01 +05:30
ArnabChatterjee20k 0108f86180 linting + merge conflicts resolving 2025-10-10 13:39:16 +05:30
ArnabChatterjee20k bc71d83697 empty commit 2025-10-10 10:58:11 +05:30
ArnabChatterjee20k 0754c6263e merged changes from 1.8.x 2025-10-10 10:55:48 +05:30
ArnabChatterjee20k 2c037803f0 updated sdk names and enums for documentsdb 2025-10-09 18:41:10 +05:30
ArnabChatterjee20k 48410d0cf6 * added getDatabaseDB in stats worker, migration worker
* added prefixed events for multitype db support with backward compat
* added realtime tests, migration tests
2025-10-09 18:26:05 +05:30
ArnabChatterjee20k 66b0f3c9df * added waiting time in usage test so that aggregator can work
* added documentsdb usage test
2025-10-09 18:24:04 +05:30
ArnabChatterjee20k d8910eea73 fix - updated documentsdb sdk namespace to documentsDB 2025-10-09 10:30:57 +05:30
Jake Barnby 38b04566b6 Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb
# Conflicts:
#	src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php
#	src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php
#	src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php
2025-10-09 17:36:22 +13:00
Jake Barnby c89af1201a Fix tests 2025-10-09 16:37:17 +13:00
Jake Barnby 9f85ca83b4 Fix roles param 2025-10-09 14:33:05 +13:00
Jake Barnby d5d09061e9 Fix index validator params 2025-10-09 13:46:14 +13:00
ArnabChatterjee20k f7f965a812 * added prefixed channels for realtime channels along with backward compatibility
* added documentsdb tests
2025-10-09 00:35:38 +05:30
Jake Barnby 143be8239f Fix inject 2025-10-09 00:41:25 +13:00
ArnabChatterjee20k d806bdbca7 added project region in the get database dsn 2025-10-08 11:17:12 +05:30
ArnabChatterjee20k 19b1196633 * new db pool implementation for connecting to db type
* fixed migration tests
2025-10-08 11:09:32 +05:30
Jake Barnby da519046dd Merge branch 'feat-mongodb' of github.com:appwrite/appwrite into feat-mongodb 2025-10-08 00:05:05 +13:00
Jake Barnby 0c5573ab05 Fix list wrapping UID injections 2025-10-08 00:04:52 +13:00
ArnabChatterjee20k 88f2b1ad50 added patch script for adding database dsn in the databases collection 2025-10-07 13:18:11 +05:30
ArnabChatterjee20k f5ea19b15d updated tests 2025-10-07 12:45:21 +05:30
Jake BarnbyandGitHub fa60f03536 Merge branch '1.8.x' into feat-mongodb 2025-10-07 18:52:28 +13:00
Jake Barnby 28392647e0 Pass adapter max ID length to validator 2025-10-07 18:52:05 +13:00
ArnabChatterjee20k d2645ecfb1 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-07 10:47:26 +05:30
Jake Barnby 4b0eddcc84 Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb
# Conflicts:
#	composer.json
#	composer.lock
2025-10-07 18:16:02 +13:00
Jake Barnby 94e40c0127 Update database 2025-10-04 10:15:13 +13:00
ArnabChatterjee20k 44b75d50f4 revmoved databasse logs xlist action for documentsdb 2025-10-03 19:56:20 +05:30
ArnabChatterjee20k df23aacbc0 updated routes and endpoints 2025-10-03 19:51:00 +05:30
ArnabChatterjee20k 7d4dfe06e2 * removed dbForDocumentsRecords
* using callback based db resolution
* updated env
2025-10-03 19:50:29 +05:30
Jake Barnby 498235a2ef Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb 2025-10-03 23:19:33 +13:00
Jake Barnby 52c9671157 Update deps 2025-10-03 23:19:09 +13:00
ArnabChatterjee20k e50af4c981 add references docs for the documentsdb 2025-10-02 19:24:35 +05:30
ArnabChatterjee20k 4fdab6fd52 updated database db resolution in the resources itself instead of switch in the worker action 2025-10-02 18:58:11 +05:30
ArnabChatterjee20k c54450f582 updated composer 2025-10-02 18:57:15 +05:30
ArnabChatterjee20k 6bf9693146 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-10-02 18:56:48 +05:30
Jake Barnby 61a1efd0fe Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb 2025-10-02 19:25:56 +13:00
Jake Barnby faf837e389 Update db for index validation fix 2025-10-02 15:29:27 +13:00
Jake Barnby 3ecd7e6a95 Fix fts create on array 2025-10-01 22:02:41 +13:00
Jake Barnby 36782650c6 Revert "Add CI debug"
This reverts commit 2d3dea84e3.
2025-10-01 21:36:03 +13:00
Jake Barnby 2f6bc9115f Fix workflows init 2025-10-01 21:35:55 +13:00
Jake Barnby 2d3dea84e3 Add CI debug 2025-10-01 21:10:26 +13:00
Jake Barnby b12f4008eb Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb
# Conflicts:
#	composer.lock
2025-10-01 20:13:48 +13:00
Jake Barnby 408bca400b Fix spatial tests 2025-10-01 19:33:11 +13:00
Jake Barnby 6bacec52c5 Fix storage test 2025-10-01 17:11:02 +13:00
Jake Barnby 9d70b5cab2 Fix domain test 2025-10-01 17:09:07 +13:00
Jake Barnby d9baf5b628 Fix sites error 2025-10-01 12:31:07 +13:00
Jake Barnby 9e837c2eb9 Fix storage error 2025-10-01 12:31:02 +13:00
Jake Barnby f3460db369 Fix fulltext error 2025-10-01 12:30:48 +13:00
ArnabChatterjee20k 422fd8b157 updated get endpoint 2025-09-30 20:02:30 +05:30
ArnabChatterjee20k bf061b460b added documentsdb in the github actions 2025-09-30 19:29:36 +05:30
ArnabChatterjee20k a035760b00 updated injections and reverted reduntant changes 2025-09-30 19:15:43 +05:30
ArnabChatterjee20k 85c0454c49 linting 2025-09-30 18:45:53 +05:30
Jake Barnby b57839402f Update DB 2025-10-01 02:14:51 +13:00
ArnabChatterjee20k 7bfb0401c6 linting 2025-09-30 18:44:27 +05:30
ArnabChatterjee20k c097f4a450 updated composer lock 2025-09-30 18:43:02 +05:30
ArnabChatterjee20k a3faa108c5 Merge remote-tracking branch 'upstream/1.8.x' into documents-db-api 2025-09-30 18:42:18 +05:30
ArnabChatterjee20k c89b76ba80 *updated tests
*updated create documents to use the on next callback
2025-09-30 18:19:44 +05:30
Jake Barnby 763158fe81 Fix usage tests 2025-10-01 01:30:18 +13:00
Jake Barnby 766c3293d2 Fix index text checks 2025-10-01 00:47:07 +13:00
Jake Barnby 1226c0834c Fix upsert 2025-10-01 00:13:09 +13:00
Jake Barnby f0983cd9ff Remove mounts 2025-10-01 00:03:07 +13:00
Jake Barnby daeb721995 Fix tests 2025-09-30 23:44:26 +13:00
Jake Barnby 0555a27656 Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb 2025-09-30 22:58:38 +13:00
Jake Barnby da3284ce84 Update deps 2025-09-30 22:58:29 +13:00
ArnabChatterjee20k 80636e8a91 updated timeouts 2025-09-30 00:03:12 +05:30
Jake Barnby 53f8a3a78b Update DB 2025-09-29 19:39:51 +13:00
ArnabChatterjee20k 206845e106 updated tests and delete delete documents 2025-09-28 14:43:44 +05:30
ArnabChatterjee20k 64d015065f * added new databasetype dsn
* updated worker to use the dsn to choose the database resource
2025-09-26 19:52:25 +05:30
ArnabChatterjee20k 56af56e341 updated endpoints 2025-09-26 18:01:39 +05:30
Jake Barnby aa77253b14 Fix OSV 2025-09-26 22:17:01 +12:00
Jake Barnby 78c5743e75 Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb
# Conflicts:
#	composer.lock
2025-09-26 22:14:40 +12:00
Jake Barnby 156a944b54 Merge remote-tracking branch 'origin/feat-mongodb-index-validation' into feat-mongodb 2025-09-26 22:05:31 +12:00
Jake Barnby b07fd5afe6 Merge remote-tracking branch 'origin/feat-mongodb-pulls' into feat-mongodb 2025-09-26 22:05:24 +12:00
ArnabChatterjee20k 3086e1cbc1 updated increment, and decrements routes 2025-09-25 19:58:59 +05:30
ArnabChatterjee20k b032a55045 updated the endpoints 2025-09-25 00:48:09 +05:30
ArnabChatterjee20k d71c56b11f * Migrating endpoints
* New adapter resolution and injection
* Removed attribute creation for documentsdb
2025-09-23 23:15:46 +05:30
shimon b828621feb Update composer dependencies and enhance index validation in database module 2025-09-21 19:14:40 +03:00
shimon 3edc055c9d Skip spatial column tests for MongoDB support in DatabasesBase trait 2025-09-21 16:02:36 +03:00
shimon ceda513083 Merge branch '1.8.x' of github.com:appwrite/appwrite into feat-mongodb-pulls
# Conflicts:
#	composer.lock
#	src/Appwrite/Platform/Workers/StatsUsage.php
#	tests/e2e/Services/Databases/TablesDB/DatabasesBase.php
2025-09-21 15:55:11 +03:00
Shimon NewmanandGitHub 2d47b88246 Merge pull request #10527 from appwrite/feat-mongodb-pulls
Feat mongodb pulls
2025-09-21 15:46:15 +03:00
shimon b88e74095b Merge remote-tracking branch 'origin/feat-mongodb-pulls' into feat-mongodb-pulls
# Conflicts:
#	composer.json
2025-09-21 15:44:41 +03:00
shimon 4d85c5ca4f composer 2025-09-21 15:42:44 +03:00
shimon c89e649d05 composer 2025-09-21 15:38:35 +03:00
shimon d9bdf01cee db lib ver 2025-09-21 15:30:09 +03:00
shimon 54e3a4b25d db lib ver 2025-09-21 15:27:41 +03:00
ArnabChatterjee20k 98ee242812 migrated tests 2025-09-20 18:21:00 +05:30
ArnabChatterjee20k 79267c8123 migrated endpoints 2025-09-20 18:20:50 +05:30
ArnabChatterjee20k d2ad0e7c74 documentsdb database creation endpoints 2025-09-19 19:44:46 +05:30
shimon b1e55702c8 Refactor MongoDB test cases for improved readability and consistency. Adjust whitespace in conditional statements and remove redundant test methods related to spatial columns. Add new tests for spatial distance queries and update existing tests to ensure proper functionality. 2025-09-16 19:14:09 +03:00
shimon f16eba2f9f Update PHPUnit configuration to stop on failure set to false, and clean up whitespace in multiple files for consistency. Adjust comments and ensure proper formatting in test cases and API handling. 2025-09-16 19:13:38 +03:00
shimon 7c0bd1da88 uncomment inversion tests 2025-09-16 17:51:29 +03:00
shimon cc87de8934 Merge branch 'feat-mongodb-pulls' of github.com:appwrite/appwrite into feat-mongodb-pulls
# Conflicts:
#	composer.lock
2025-09-16 17:43:47 +03:00
shimon 5f8dc9998c Refactor database document handling by replacing createOrUpdateDocuments with upsertDocuments in multiple classes. Clean up common.php by removing commented-out index definitions and ensuring proper indexing for MongoDB compatibility. Update UsageTest to correct API endpoint paths for database operations. 2025-09-16 17:39:41 +03:00
shimon cc7778ceea database lib check 2025-09-16 11:10:06 +03:00
shimon f5fc099d87 Merge branch '1.8.x' of github.com:appwrite/appwrite into feat-mongodb-pulls
# Conflicts:
#	composer.lock
#	tests/e2e/Services/Databases/TablesDB/DatabasesBase.php
2025-09-16 10:26:43 +03:00
shimon 89d06d00c0 Merge branch '1.8.x' of github.com:appwrite/appwrite into feat-mongodb-pulls
# Conflicts:
#	.github/workflows/tests.yml
#	composer.lock
#	tests/e2e/Services/Databases/TablesDB/DatabasesBase.php
2025-09-11 16:54:49 +03:00
shimon 882cd8c83e Merge remote-tracking branch 'origin/feat-mongodb-pulls' into feat-mongodb-pulls
# Conflicts:
#	tests/e2e/Services/Databases/TablesDB/DatabasesCustomClientTest.php
2025-09-11 16:43:39 +03:00
shimon 80cc6a0bb3 DatabasesCustomClientTest.php 2025-09-11 16:42:33 +03:00
shimon fc4ad175dd Update composer.json and composer.lock to reflect new versioning for utopia-php/database and other dependencies. Adjusted package versions for brick/math, open-telemetry/api, and symfony components. Added symfony/polyfill-php83 for compatibility with PHP 8.3 features. Minor formatting changes in MigrationsBase.php for code clarity. 2025-09-11 16:38:41 +03:00
shimon a0def8edf8 Updates 2025-08-31 17:57:58 +03:00
shimon bdb8204910 Refactor database attribute tests to streamline size validation and add support for additional integer index. Updated size constraints for 'description' and 'tagline' attributes, and introduced a new 'integers2' attribute to accommodate MongoDB limitations. Adjusted assertions to reflect these changes. 2025-08-27 16:32:13 +03:00
shimon 1274614d18 Update composer.json and composer.lock to reflect new versioning for utopia-php/database and other dependencies. Adjusted Docker configuration to set the database adapter to MariaDB. 2025-08-27 13:55:48 +03:00
shimon 4f937ac549 Update composer.json and composer.lock to reflect changes in utopia-php/database versioning, including the removal of the 'with-uuid7' suffix. Updated dependencies for composer/semver, symfony/polyfill packages, and phpunit/phpunit to their latest versions for improved compatibility and performance. 2025-08-27 10:28:17 +03:00
shimon 6910d669de Update composer.json to correct utopia-php/database version reference and modify test to use the correct endpoint for MongoDB operations. 2025-08-27 10:25:23 +03:00
shimon 4fb680350a Merge branch '1.8.x' of github.com:appwrite/appwrite into feat-mongodb-pulls
# Conflicts:
#	Dockerfile
#	composer.json
#	composer.lock
#	tests/e2e/Services/Databases/TablesDB/DatabasesCustomClientTest.php
#	tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php
2025-08-26 14:20:47 +03:00
Shimon NewmanandGitHub ff35dc6114 Merge pull request #10375 from appwrite/feat-mongodb-pulls
Feat mongodb pulls
2025-08-26 13:53:42 +03:00
shimon 38433b9ac1 Remove unnecessary var_dump statement from ProjectsConsoleClientTest for improved code clarity and consistency. 2025-08-26 13:52:05 +03:00
shimon b98be4756c Update composer.json and composer.lock to reflect changes in utopia-php/database versioning and dependencies. Adjusted MongoDB-related test conditions for improved compatibility and clarity. Removed unnecessary var_dump statements in account.php and enhanced logging in various test files for better debugging. 2025-08-26 13:48:01 +03:00
shimon ff8418ffb9 Update composer.lock to reflect new references and timestamps for dependencies, including updates for utopia-php/database and phpunit/phpunit. Removed duplicate entries and unnecessary lines for improved clarity. 2025-08-12 18:01:38 +03:00
shimon e151425b95 Merge branch '1.8.x' of github.com:appwrite/appwrite into feat-mongodb-pulls 2025-08-12 17:54:55 +03:00
shimon b9f4815c3a Remove unnecessary var_dump statements from api.php and enhance logging in MessagingConsoleClientTest for improved clarity and debugging. This aligns with recent efforts to clean up debugging output across the codebase. 2025-08-12 17:47:11 +03:00
shimon c4fb7ecbc1 Refactor and clean up debugging output across multiple files, including mock.php, account.php, and OAuth2 classes. Removed unnecessary var_dump statements for improved code clarity and consistency. Updated MongoDB condition checks in test cases to ensure case-insensitive comparisons. 2025-08-12 15:20:30 +03:00
shimon 24b7c95514 Merge branch 'feat-mongodb' of github.com:appwrite/appwrite into feat-mongodb 2025-08-11 22:07:11 +03:00
shimon 870125ed84 Refactor MongoDB condition checks in DatabasesCustomClientTest and UsersBase. Improved formatting for consistency and clarity in test assertions, particularly for MongoDB-related tests. 2025-08-11 22:07:05 +03:00
shimon e1475619ba Refactor debugging output across various files, including http.php, mock.php, and OAuth2 classes. Adjusted var_dump statements for improved traceability and consistency. Updated test assertions in ProjectsConsoleClientTest and UsersBase to enhance clarity and functionality. 2025-08-11 22:05:18 +03:00
Matej Bačo ba058a89a3 Merge branch '1.8.x' into feat-mongodb 2025-08-11 13:22:27 +02:00
shimon 236fab4658 Update composer configuration for minimum stability and prefer stable packages. Adjust utopia-php/database version alias and update phpunit and sebastian packages to latest versions. Add debugging output in http.php and uncomment OAuth2 conversion test in AccountCustomClientTest for improved functionality. 2025-08-11 11:56:38 +03:00
shimon 6cfd6d9ac9 Remove debugging var_dump statements from projects API and enhance error handling in XList class. Update test cases to comment out a specific OAuth2 conversion test for clarity. 2025-08-11 11:28:11 +03:00
shimon da706378ea Enhance debugging output in OAuth2 mock endpoints and update MongoDB version in tests. Added var_dump statements for better traceability during OAuth2 flows and adjusted test assertions for user search functionality. 2025-08-11 11:27:45 +03:00
shimon 40e36e23dd Merge remote-tracking branch 'origin/1.8.x' into feat-mongodb 2025-08-10 18:16:03 +03:00
shimon 603980759a composer.lock 2025-08-06 15:49:05 +03:00
shimon d63a218bd8 Merge branch '1.8.x' of github.com:appwrite/appwrite into feat-mongodb
# Conflicts:
#	composer.json
#	composer.lock
2025-08-06 15:48:19 +03:00
shimon def3628205 feat: rename tables to grids and update documentation 2025-08-06 15:37:59 +03:00
shimon 779fb7bd20 Update composer dependencies and Docker Compose configuration for MongoDB integration. Change database alias in composer.json, update package versions in composer.lock, and adjust volume mappings in Docker Compose to include MongoDB source directories. Refactor application code to set tenant to null for database connections. 2025-08-06 15:07:04 +03:00
shimon ea1aef1d70 composer.lock 2025-08-03 18:40:45 +03:00
shimon b1cc203eba composer 2025-08-03 18:38:38 +03:00
shimon b3e1a3415a Merge branch '1.8.x' of github.com:appwrite/appwrite into feat-mongodb
# Conflicts:
#	app/init/resources.php
#	composer.json
#	composer.lock
2025-08-03 18:33:27 +03:00
shimon d48248c9a2 Refactor Docker Compose and application code for MongoDB integration. Remove health check configuration and simplify service dependencies in Docker Compose. Update error logging in application to include context for MongoDB connection issues. 2025-08-03 18:13:16 +03:00
shimon eafca0c431 Add support for multiple database adapters in GitHub Actions workflow, including MARIADB and MONGODB. Set environment variables based on selected adapter for testing. 2025-07-31 18:22:42 +03:00
shimon a92bdfaed0 Update Docker Compose to clarify MongoDB readiness check comment, addressing implications of template substitution limitations. 2025-07-31 17:49:04 +03:00
shimon 46965135a4 Update Docker Compose and application configuration to support MongoDB as the primary database, replacing all instances of MariaDB. Introduce a new environment variable for database selection and adjust database schemes in the application initialization. 2025-07-31 17:17:08 +03:00
shimon 33c5ac83b2 Enhance Docker Compose configuration for MongoDB, add health checks, and update user creation logic in mongo-init.js. Improve database connection handling and fix conditional checks in application code. 2025-07-31 12:47:12 +03:00
shimon 57c08a41f1 Update environment configuration to support MongoDB, enhance Docker Compose for MongoDB integration, and improve database connection handling in the application. 2025-07-29 23:08:00 +03:00
shimon 36e7452f78 Update environment variables, Dockerfile version, and enhance MongoDB connection handling in the application. Add console document creation logic and improve code formatting for better readability. 2025-07-28 17:34:11 +03:00
shimon 469801b862 Update database configuration to use MongoDB, add MongoDB and Mongo Express services to Docker Compose, and adjust related code for MongoDB integration. 2025-07-27 20:38:49 +03:00
401 changed files with 30944 additions and 1148 deletions
+9
View File
@@ -41,10 +41,19 @@ _APP_REDIS_USER=
_APP_DB_ADAPTER=mariadb
_APP_DB_HOST=mariadb
_APP_DB_PORT=3306
_APP_DB_ADAPTER=mariadb
_APP_DB_SCHEMA=appwrite
_APP_DB_USER=user
_APP_DB_PASS=password
_APP_DB_ROOT_PASS=rootsecretpassword
_APP_DB_ADAPTER_DOCUMENTSDB=mongodb
_APP_DB_HOST_DOCUMENTSDB=mongodb
_APP_DB_PORT_DOCUMENTSDB=27017
_APP_DB_ADAPTER_VECTORDB=postgresql
_APP_DB_HOST_VECTORDB=postgresql
_APP_DB_PORT_VECTORDB=5432
_APP_EMBEDDING_MODELS=embeddinggemma
_APP_EMBEDDING_ENDPOINT='http://ollama:11434/api/embed'
_APP_STORAGE_DEVICE=Local
_APP_STORAGE_S3_ACCESS_KEY=
_APP_STORAGE_S3_SECRET=
+18 -6
View File
@@ -173,10 +173,8 @@ jobs:
- name: Failure Logs
if: failure()
run: |
echo "=== Appwrite Worker Builds Logs ==="
docker compose logs appwrite-worker-builds
echo "=== OpenRuntimes Executor Logs ==="
docker compose logs openruntimes-executor
echo "=== Appwrite Logs ==="
docker compose logs
e2e_service_test:
name: E2E Service Test
@@ -190,15 +188,17 @@ jobs:
matrix:
db_adapter: [
MARIADB,
POSTGRESQL
POSTGRESQL,
# MONGODB
]
service: [
Account,
Avatars,
Console,
Databases/Legacy,
Databases/TablesDB,
Databases/DocumentsDB,
Databases/VectorDB,
Functions,
FunctionsSchedule,
GraphQL,
@@ -232,6 +232,18 @@ jobs:
run: |
docker load --input /tmp/${{ env.IMAGE }}.tar
sed -i 's|^_APP_BROWSER_HOST=.*|_APP_BROWSER_HOST=http://invalid-browser/v1|' .env
# Set DB Adapter in .env before starting services
if [ "${{ matrix.db_adapter }}" = "MARIADB" ]; then
sed -i 's|^_APP_DB_ADAPTER=.*|_APP_DB_ADAPTER=mariadb|' .env
sed -i 's|^_APP_DB_HOST=.*|_APP_DB_HOST=mariadb|' .env
sed -i 's|^_APP_DB_PORT=.*|_APP_DB_PORT=3306|' .env
elif [ "${{ matrix.db_adapter }}" = "MONGODB" ]; then
sed -i 's|^_APP_DB_ADAPTER=.*|_APP_DB_ADAPTER=mongodb|' .env
sed -i 's|^_APP_DB_HOST=.*|_APP_DB_HOST=mongodb|' .env
sed -i 's|^_APP_DB_PORT=.*|_APP_DB_PORT=27017|' .env
fi
docker compose up -d
sleep 30
+3
View File
@@ -37,6 +37,9 @@ COPY ./app /usr/src/code/app
COPY ./public /usr/src/code/public
COPY ./bin /usr/local/bin
COPY ./src /usr/src/code/src
COPY ./dev /usr/src/code/dev
COPY ./mongo-init.js /usr/src/code/mongo-init.js
COPY ./mongo-entrypoint.sh /usr/src/code/mongo-entrypoint.sh
# Set Volumes
RUN mkdir -p /storage/uploads && \
+2
View File
@@ -4,6 +4,7 @@
$common = include __DIR__ . '/collections/common.php';
$projects = include __DIR__ . '/collections/projects.php';
$databases = include __DIR__ . '/collections/databases.php';
$vectordb = include __DIR__ . '/collections/vectordb.php';
$platform = include __DIR__ . '/collections/platform.php';
$logs = include __DIR__ . '/collections/logs.php';
@@ -26,6 +27,7 @@ unset($common['files']);
$collections = [
'buckets' => $buckets,
'databases' => $databases,
'vectordb' => $vectordb,
'projects' => array_merge_recursive($projects, $common),
'console' => array_merge_recursive($platform, $common),
'logs' => $logs,
+1 -21
View File
@@ -1617,13 +1617,6 @@ return [
],
],
'indexes' => [
[
'$id' => ID::custom('_fulltext_name'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['name'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_search'),
'type' => Database::INDEX_FULLTEXT,
@@ -1853,13 +1846,6 @@ return [
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_name'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['name'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_type'),
'type' => Database::INDEX_KEY,
@@ -2127,14 +2113,8 @@ return [
'filters' => ['topicSearch'],
],
],
'indexes' => [
[
'$id' => ID::custom('_key_name'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['name'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_search'),
'type' => Database::INDEX_FULLTEXT,
+9
View File
@@ -61,6 +61,15 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('database'),
'type' => Database::VAR_STRING,
'size' => 128,
'required' => true,
'signed' => true,
'array' => false,
'filters' => [],
]
],
'indexes' => [
[
+165
View File
@@ -0,0 +1,165 @@
<?php
use Utopia\Database\Database;
use Utopia\Database\Helpers\ID;
return [
'collections' => [
'$collection' => ID::custom('databases'),
'$id' => ID::custom('collections'),
'name' => 'Collections',
'attributes' => [
[
'$id' => ID::custom('databaseInternalId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('databaseId'),
'type' => Database::VAR_STRING,
'signed' => true,
'size' => Database::LENGTH_KEY,
'format' => '',
'filters' => [],
'required' => true,
'default' => null,
'array' => false,
],
[
'$id' => ID::custom('name'),
'type' => Database::VAR_STRING,
'size' => 256,
'required' => true,
'signed' => true,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('dimension'),
'type' => Database::VAR_INTEGER,
'size' => 0,
'required' => true,
'signed' => false,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('enabled'),
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'default' => null,
'array' => false,
],
[
'$id' => ID::custom('documentSecurity'),
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'default' => null,
'array' => false,
],
[
'$id' => ID::custom('attributes'),
'type' => Database::VAR_STRING,
'size' => 1000000,
'required' => false,
'signed' => true,
'array' => false,
'filters' => ['subQueryAttributes'],
],
[
'$id' => ID::custom('indexes'),
'type' => Database::VAR_STRING,
'size' => 1000000,
'required' => false,
'signed' => true,
'array' => false,
'filters' => ['subQueryIndexes'],
],
[
'$id' => ID::custom('search'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'defaultAttributes' => [
[
'$id' => ID::custom('embeddings'),
'type' => Database::VAR_VECTOR,
'required' => true,
'signed' => false,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('metadata'),
'type' => Database::VAR_OBJECT,
'default' => [],
'required' => false,
'size' => 0,
'signed' => false,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
'$id' => ID::custom('_fulltext_search'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['search'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_name'),
'type' => Database::INDEX_KEY,
'attributes' => ['name'],
'lengths' => [256],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_enabled'),
'type' => Database::INDEX_KEY,
'attributes' => ['enabled'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_documentSecurity'),
'type' => Database::INDEX_KEY,
'attributes' => ['documentSecurity'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
],
'defaultIndexes' => [
// not creating default indexes on the embeddings as it depends on the type of query users using the most
[
'$id' => ID::custom('_key_metadata'),
'type' => Database::INDEX_OBJECT,
'attributes' => ['metadata'],
'lengths' => [],
'orders' => [],
],
]
]
];
+9
View File
@@ -378,6 +378,15 @@ return [
]
],
],
[
'name' => '_APP_DB_ADAPTER',
'description' => 'Which database engine to use. Possible options are "mariadb" or "mongodb"',
'introduction' => '1.8.0',
'default' => 'mongoDB',
'required' => true,
'question' => 'Choose your database (mariadb|mongoDB)',
'filter' => ''
],
[
'category' => 'Redis',
'description' => 'Appwrite uses a Redis server for managing cache, queues and scheduled tasks. The Redis env vars are used to allow Appwrite server to connect to the Redis container.',
+20 -16
View File
@@ -367,7 +367,7 @@ Http::post('/v1/account')
contentType: ContentType::JSON
))
->label('abuse-limit', 10)
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be between 8 and 256 chars.', false, ['project', 'passwordsDictionary'])
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
@@ -728,7 +728,7 @@ Http::get('/v1/account/sessions/:sessionId')
],
contentType: ContentType::JSON
))
->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to get the current device session.')
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'current\' to get the current device session.', false, ['dbForProject'])
->inject('response')
->inject('user')
->inject('locale')
@@ -780,7 +780,7 @@ Http::delete('/v1/account/sessions/:sessionId')
contentType: ContentType::NONE
))
->label('abuse-limit', 100)
->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to delete the current device session.')
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'current\' to delete the current device session.', false, ['dbForProject'])
->inject('requestTimestamp')
->inject('request')
->inject('response')
@@ -868,7 +868,7 @@ Http::patch('/v1/account/sessions/:sessionId')
contentType: ContentType::JSON
))
->label('abuse-limit', 10)
->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to update the current device session.')
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'current\' to update the current device session.', false, ['dbForProject'])
->inject('response')
->inject('user')
->inject('dbForProject')
@@ -1485,6 +1485,7 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
} elseif ($protocol === 'http' && $port !== '80') {
$callbackBase .= ':' . $port;
}
$callback = $callbackBase . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
$appId = $project->getAttribute('oAuthProviders', [])[$provider . 'Appid'] ?? '';
@@ -1547,6 +1548,7 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
if (!empty($state['failure'])) {
$failure = URLParser::parse($state['failure']);
}
$failureRedirect = (function (string $type, ?string $message = null, ?int $code = null) use ($failure, $response) {
$exception = new Exception($type, $message, $code);
if (!empty($failure)) {
@@ -1592,7 +1594,9 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
$accessToken = $oauth2->getAccessToken($code);
$refreshToken = $oauth2->getRefreshToken($code);
$accessTokenExpiry = $oauth2->getAccessTokenExpiry($code);
} catch (OAuth2Exception $ex) {
$failureRedirect(
$ex->getType(),
'Failed to obtain access token. The ' . $providerName . ' OAuth2 provider returned an error: ' . $ex->getMessage(),
@@ -2092,7 +2096,7 @@ Http::post('/v1/account/tokens/magic-url')
))
->label('abuse-limit', 60)
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('url', '', fn ($redirectValidator) => $redirectValidator, 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['redirectValidator'])
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
@@ -2372,7 +2376,7 @@ Http::post('/v1/account/tokens/email')
))
->label('abuse-limit', 10)
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
->inject('request')
@@ -2728,7 +2732,7 @@ Http::put('/v1/account/sessions/phone')
))
->label('abuse-limit', 10)
->label('abuse-key', 'ip:{ip},userId:{param-userId}')
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('secret', '', new Text(256), 'Valid verification token.')
->inject('request')
->inject('response')
@@ -2771,7 +2775,7 @@ Http::post('/v1/account/tokens/phone')
))
->label('abuse-limit', 10)
->label('abuse-key', ['url:{url},phone:{param-phone}', 'url:{url},ip:{ip}'])
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the phone number has never been used, a new account is created using the provided userId. Otherwise, if the phone number is already attached to an account, the user ID is ignored.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the phone number has never been used, a new account is created using the provided userId. Otherwise, if the phone number is already attached to an account, the user ID is ignored.', false, ['dbForProject'])
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.')
->inject('request')
->inject('response')
@@ -3749,7 +3753,7 @@ Http::put('/v1/account/recovery')
))
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('secret', '', new Text(256), 'Valid reset token.')
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be between 8 and 256 chars.', false, ['project', 'passwordsDictionary'])
->inject('response')
@@ -4100,7 +4104,7 @@ Http::put('/v1/account/verifications/email')
])
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('secret', '', new Text(256), 'Valid verification token.')
->inject('response')
->inject('user')
@@ -4316,7 +4320,7 @@ Http::put('/v1/account/verifications/phone')
))
->label('abuse-limit', 10)
->label('abuse-key', 'userId:{param-userId}')
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('secret', '', new Text(256), 'Valid verification token.')
->inject('response')
->inject('user')
@@ -4381,9 +4385,9 @@ Http::post('/v1/account/targets/push')
],
contentType: ContentType::JSON
))
->param('targetId', '', new CustomId(), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('targetId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)')
->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true)
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true, ['dbForProject'])
->inject('queueForEvents')
->inject('user')
->inject('request')
@@ -4465,7 +4469,7 @@ Http::put('/v1/account/targets/:targetId/push')
],
contentType: ContentType::JSON
))
->param('targetId', '', new UID(), 'Target ID.')
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)')
->inject('queueForEvents')
->inject('user')
@@ -4531,7 +4535,7 @@ Http::delete('/v1/account/targets/:targetId/push')
],
contentType: ContentType::NONE
))
->param('targetId', '', new UID(), 'Target ID.')
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
->inject('queueForEvents')
->inject('queueForDeletes')
->inject('user')
@@ -4653,7 +4657,7 @@ Http::delete('/v1/account/identities/:identityId')
],
contentType: ContentType::NONE
))
->param('identityId', '', new UID(), 'Identity ID.')
->param('identityId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Identity ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
+69 -69
View File
@@ -78,7 +78,7 @@ Http::post('/v1/messaging/providers/mailgun')
)
]
))
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
@@ -172,7 +172,7 @@ Http::post('/v1/messaging/providers/sendgrid')
)
]
))
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
->param('fromName', '', new Text(128, 0), 'Sender Name.', true)
@@ -356,7 +356,7 @@ Http::post('/v1/messaging/providers/smtp')
]
)
])
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.')
->param('port', 587, new Range(1, 65535), 'The default SMTP server port.', true)
@@ -451,7 +451,7 @@ Http::post('/v1/messaging/providers/msg91')
)
]
))
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('templateId', '', new Text(0), 'Msg91 template ID', true)
->param('senderId', '', new Text(0), 'Msg91 sender ID.', true)
@@ -534,7 +534,7 @@ Http::post('/v1/messaging/providers/telesign')
)
]
))
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('customerId', '', new Text(0), 'Telesign customer ID.', true)
@@ -618,7 +618,7 @@ Http::post('/v1/messaging/providers/textmagic')
)
]
))
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('username', '', new Text(0), 'Textmagic username.', true)
@@ -702,7 +702,7 @@ Http::post('/v1/messaging/providers/twilio')
)
]
))
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('accountSid', '', new Text(0), 'Twilio account secret ID.', true)
@@ -786,7 +786,7 @@ Http::post('/v1/messaging/providers/vonage')
)
]
))
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('apiKey', '', new Text(0), 'Vonage API key.', true)
@@ -890,7 +890,7 @@ Http::post('/v1/messaging/providers/fcm')
]
)
])
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('serviceAccountJSON', null, new Nullable(new JSON()), 'FCM service account JSON.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
@@ -980,7 +980,7 @@ Http::post('/v1/messaging/providers/apns')
]
)
])
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.')
->param('authKey', '', new Text(0), 'APNS authentication key.', true)
->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true)
@@ -1135,7 +1135,7 @@ Http::get('/v1/messaging/providers/:providerId/logs')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -1231,7 +1231,7 @@ Http::get('/v1/messaging/providers/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->inject('dbForProject')
->inject('response')
->action(function (string $providerId, Database $dbForProject, Response $response) {
@@ -1265,7 +1265,7 @@ Http::patch('/v1/messaging/providers/mailgun/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
@@ -1378,7 +1378,7 @@ Http::patch('/v1/messaging/providers/sendgrid/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
@@ -1594,7 +1594,7 @@ Http::patch('/v1/messaging/providers/smtp/:providerId')
]
)
])
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.', true)
->param('port', null, new Nullable(new Range(1, 65535)), 'SMTP port.', true)
@@ -1723,7 +1723,7 @@ Http::patch('/v1/messaging/providers/msg91/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('templateId', '', new Text(0), 'Msg91 template ID.', true)
@@ -1810,7 +1810,7 @@ Http::patch('/v1/messaging/providers/telesign/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('customerId', '', new Text(0), 'Telesign customer ID.', true)
@@ -1899,7 +1899,7 @@ Http::patch('/v1/messaging/providers/textmagic/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('username', '', new Text(0), 'Textmagic username.', true)
@@ -1988,7 +1988,7 @@ Http::patch('/v1/messaging/providers/twilio/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('accountSid', '', new Text(0), 'Twilio account secret ID.', true)
@@ -2077,7 +2077,7 @@ Http::patch('/v1/messaging/providers/vonage/:providerId')
)
]
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('apiKey', '', new Text(0), 'Vonage API key.', true)
@@ -2186,7 +2186,7 @@ Http::patch('/v1/messaging/providers/fcm/:providerId')
]
)
])
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('serviceAccountJSON', null, new Nullable(new JSON()), 'FCM service account JSON.', true)
@@ -2282,7 +2282,7 @@ Http::patch('/v1/messaging/providers/apns/:providerId')
]
)
])
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Provider name.', true)
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
->param('authKey', '', new Text(0), 'APNS authentication key.', true)
@@ -2385,7 +2385,7 @@ Http::delete('/v1/messaging/providers/:providerId')
],
contentType: ContentType::NONE
))
->param('providerId', '', new UID(), 'Provider ID.')
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
->inject('queueForEvents')
->inject('dbForProject')
->inject('response')
@@ -2427,7 +2427,7 @@ Http::post('/v1/messaging/topics')
)
]
))
->param('topicId', '', new CustomId(), 'Topic ID. Choose a custom Topic ID or a new Topic ID.')
->param('topicId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. Choose a custom Topic ID or a new Topic ID.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Topic Name.')
->param('subscribe', [Role::users()], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true)
->inject('queueForEvents')
@@ -2539,7 +2539,7 @@ Http::get('/v1/messaging/topics/:topicId/logs')
)
]
))
->param('topicId', '', new UID(), 'Topic ID.')
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -2636,7 +2636,7 @@ Http::get('/v1/messaging/topics/:topicId')
)
]
))
->param('topicId', '', new UID(), 'Topic ID.')
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
->inject('dbForProject')
->inject('response')
->action(function (string $topicId, Database $dbForProject, Response $response) {
@@ -2671,7 +2671,7 @@ Http::patch('/v1/messaging/topics/:topicId')
)
]
))
->param('topicId', '', new UID(), 'Topic ID.')
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
->param('name', null, new Nullable(new Text(128)), 'Topic Name.', true)
->param('subscribe', null, new Nullable(new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE)), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true)
->inject('queueForEvents')
@@ -2723,7 +2723,7 @@ Http::delete('/v1/messaging/topics/:topicId')
],
contentType: ContentType::NONE
))
->param('topicId', '', new UID(), 'Topic ID.')
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
->inject('queueForEvents')
->inject('dbForProject')
->inject('queueForDeletes')
@@ -2770,9 +2770,9 @@ Http::post('/v1/messaging/topics/:topicId/subscribers')
)
]
))
->param('subscriberId', '', new CustomId(), 'Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.')
->param('topicId', '', new UID(), 'Topic ID. The topic ID to subscribe to.')
->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.')
->param('subscriberId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.', false, ['dbForProject'])
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID to subscribe to.', false, ['dbForProject'])
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID. The target ID to link to the specified Topic ID.', false, ['dbForProject'])
->inject('queueForEvents')
->inject('dbForProject')
->inject('authorization')
@@ -2868,7 +2868,7 @@ Http::get('/v1/messaging/topics/:topicId/subscribers')
)
]
))
->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.')
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID subscribed to.', false, ['dbForProject'])
->param('queries', [], new Subscribers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
@@ -2954,7 +2954,7 @@ Http::get('/v1/messaging/subscribers/:subscriberId/logs')
)
]
))
->param('subscriberId', '', new UID(), 'Subscriber ID.')
->param('subscriberId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID.', false, ['dbForProject'])
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -3051,8 +3051,8 @@ Http::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
)
]
))
->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.')
->param('subscriberId', '', new UID(), 'Subscriber ID.')
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID subscribed to.', false, ['dbForProject'])
->param('subscriberId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID.', false, ['dbForProject'])
->inject('dbForProject')
->inject('authorization')
->inject('response')
@@ -3102,8 +3102,8 @@ Http::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
],
contentType: ContentType::NONE
))
->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.')
->param('subscriberId', '', new UID(), 'Subscriber ID.')
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID subscribed to.', false, ['dbForProject'])
->param('subscriberId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID.', false, ['dbForProject'])
->inject('queueForEvents')
->inject('dbForProject')
->inject('authorization')
@@ -3169,14 +3169,14 @@ Http::post('/v1/messaging/messages/email')
)
]
))
->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('messageId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('subject', '', new Text(998), 'Email Subject.')
->param('content', '', new Text(64230), 'Email Content.')
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
->param('cc', [], new ArrayList(new UID()), 'Array of target IDs to be added as CC.', true)
->param('bcc', [], new ArrayList(new UID()), 'Array of target IDs to be added as BCC.', true)
->param('topics', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Topic IDs.', true, ['dbForProject'])
->param('users', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of User IDs.', true, ['dbForProject'])
->param('targets', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Targets IDs.', true, ['dbForProject'])
->param('cc', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Array of target IDs to be added as CC.', true, ['dbForProject'])
->param('bcc', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Array of target IDs to be added as BCC.', true, ['dbForProject'])
->param('attachments', [], new ArrayList(new CompoundUID()), 'Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.', true)
->param('draft', false, new Boolean(), 'Is message a draft', true)
->param('html', false, new Boolean(), 'Is content of type HTML', true)
@@ -3348,11 +3348,11 @@ Http::post('/v1/messaging/messages/sms')
]
)
])
->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('messageId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('content', '', new Text(64230), 'SMS Content.')
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
->param('topics', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Topic IDs.', true, ['dbForProject'])
->param('users', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of User IDs.', true, ['dbForProject'])
->param('targets', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Targets IDs.', true, ['dbForProject'])
->param('draft', false, new Boolean(), 'Is message a draft', true)
->param('scheduledAt', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
->inject('queueForEvents')
@@ -3471,12 +3471,12 @@ Http::post('/v1/messaging/messages/push')
)
]
))
->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('messageId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('title', '', new Text(256), 'Title for push notification.', true)
->param('body', '', new Text(64230), 'Body for push notification.', true)
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
->param('topics', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Topic IDs.', true, ['dbForProject'])
->param('users', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of User IDs.', true, ['dbForProject'])
->param('targets', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Targets IDs.', true, ['dbForProject'])
->param('data', null, new Nullable(new JSON()), 'Additional key-value pair data for push notification.', true)
->param('action', '', new Text(256), 'Action for push notification.', true)
->param('image', '', new CompoundUID(), 'Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.', true)
@@ -3752,7 +3752,7 @@ Http::get('/v1/messaging/messages/:messageId/logs')
)
],
))
->param('messageId', '', new UID(), 'Message ID.')
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -3849,7 +3849,7 @@ Http::get('/v1/messaging/messages/:messageId/targets')
)
],
))
->param('messageId', '', new UID(), 'Message ID.')
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -3927,7 +3927,7 @@ Http::get('/v1/messaging/messages/:messageId')
)
]
))
->param('messageId', '', new UID(), 'Message ID.')
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
->inject('dbForProject')
->inject('response')
->action(function (string $messageId, Database $dbForProject, Response $response) {
@@ -3961,16 +3961,16 @@ Http::patch('/v1/messaging/messages/email/:messageId')
)
]
))
->param('messageId', '', new UID(), 'Message ID.')
->param('topics', null, new Nullable(new ArrayList(new UID())), 'List of Topic IDs.', true)
->param('users', null, new Nullable(new ArrayList(new UID())), 'List of User IDs.', true)
->param('targets', null, new Nullable(new ArrayList(new UID())), 'List of Targets IDs.', true)
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
->param('topics', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Topic IDs.', true, ['dbForProject'])
->param('users', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of User IDs.', true, ['dbForProject'])
->param('targets', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Targets IDs.', true, ['dbForProject'])
->param('subject', null, new Nullable(new Text(998)), 'Email Subject.', true)
->param('content', null, new Nullable(new Text(64230)), 'Email Content.', true)
->param('draft', null, new Nullable(new Boolean()), 'Is message a draft', true)
->param('html', null, new Nullable(new Boolean()), 'Is content of type HTML', true)
->param('cc', null, new Nullable(new ArrayList(new UID())), 'Array of target IDs to be added as CC.', true)
->param('bcc', null, new Nullable(new ArrayList(new UID())), 'Array of target IDs to be added as BCC.', true)
->param('cc', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'Array of target IDs to be added as CC.', true, ['dbForProject'])
->param('bcc', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'Array of target IDs to be added as BCC.', true, ['dbForProject'])
->param('scheduledAt', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
->param('attachments', null, new Nullable(new ArrayList(new CompoundUID())), 'Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.', true)
->inject('queueForEvents')
@@ -4188,10 +4188,10 @@ Http::patch('/v1/messaging/messages/sms/:messageId')
]
)
])
->param('messageId', '', new UID(), 'Message ID.')
->param('topics', null, new Nullable(new ArrayList(new UID())), 'List of Topic IDs.', true)
->param('users', null, new Nullable(new ArrayList(new UID())), 'List of User IDs.', true)
->param('targets', null, new Nullable(new ArrayList(new UID())), 'List of Targets IDs.', true)
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
->param('topics', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Topic IDs.', true, ['dbForProject'])
->param('users', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of User IDs.', true, ['dbForProject'])
->param('targets', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Targets IDs.', true, ['dbForProject'])
->param('content', null, new Nullable(new Text(64230)), 'Email Content.', true)
->param('draft', null, new Nullable(new Boolean()), 'Is message a draft', true)
->param('scheduledAt', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
@@ -4350,10 +4350,10 @@ Http::patch('/v1/messaging/messages/push/:messageId')
)
]
))
->param('messageId', '', new UID(), 'Message ID.')
->param('topics', null, new Nullable(new ArrayList(new UID())), 'List of Topic IDs.', true)
->param('users', null, new Nullable(new ArrayList(new UID())), 'List of User IDs.', true)
->param('targets', null, new Nullable(new ArrayList(new UID())), 'List of Targets IDs.', true)
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
->param('topics', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Topic IDs.', true, ['dbForProject'])
->param('users', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of User IDs.', true, ['dbForProject'])
->param('targets', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Targets IDs.', true, ['dbForProject'])
->param('title', null, new Nullable(new Text(256)), 'Title for push notification.', true)
->param('body', null, new Nullable(new Text(64230)), 'Body for push notification.', true)
->param('data', null, new Nullable(new JSON()), 'Additional Data for push notification.', true)
@@ -4612,7 +4612,7 @@ Http::delete('/v1/messaging/messages/:messageId')
],
contentType: ContentType::NONE
))
->param('messageId', '', new UID(), 'Message ID.')
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
->inject('dbForProject')
->inject('dbForPlatform')
->inject('queueForEvents')
+38 -13
View File
@@ -43,6 +43,15 @@ use Utopia\Validator\WhiteList;
include_once __DIR__ . '/../shared/api.php';
function getDatabaseTransferResourceServices(string $databaseType)
{
return match($databaseType) {
DATABASE_TYPE_LEGACY,
DATABASE_TYPE_TABLESDB => Transfer::GROUP_DATABASES_TABLES_DB,
DATABASE_TYPE_VECTORDB => Transfer::GROUP_DATABASES_VECTOR_DB
};
}
Http::post('/v1/migrations/appwrite')
->groups(['api', 'migrations'])
->desc('Create Appwrite migration')
@@ -64,7 +73,7 @@ Http::post('/v1/migrations/appwrite')
))
->param('resources', [], new ArrayList(new WhiteList(Appwrite::getSupportedResources())), 'List of resources to migrate')
->param('endpoint', '', new URL(), 'Source Appwrite endpoint')
->param('projectId', '', new UID(), 'Source Project ID')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Source Project ID', false, ['dbForProject'])
->param('apiKey', '', new Text(512), 'Source API Key')
->inject('response')
->inject('dbForProject')
@@ -335,8 +344,8 @@ Http::post('/v1/migrations/csv/imports')
)
]
))
->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('bucketId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).', false, ['dbForProject'])
->param('fileId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'File ID.', false, ['dbForProject'])
->param('resourceId', null, new CompoundUID(), 'Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.')
->param('internalFile', false, new Boolean(), 'Is the file stored in an internal bucket?', true)
->inject('response')
@@ -427,8 +436,16 @@ Http::post('/v1/migrations/csv/imports')
throw new \Exception('Unable to copy file');
}
// getting databasetype
$resources = explode(':', $resourceId);
$databaseId = $resources[0];
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$databaseType = $database->getAttribute('type');
if (!in_array($databaseType, CSV_ALLOWED_DATABASE_TYPES)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Database type not supported for csv');
}
$fileSize = $deviceForMigrations->getFileSize($newPath);
$resources = Transfer::extractServices([Transfer::GROUP_DATABASES]);
$resources = Transfer::extractServices([getDatabaseTransferResourceServices($databaseType)]);
$migration = $dbForProject->createDocument('migrations', new Document([
'$id' => $migrationId,
@@ -557,13 +574,23 @@ Http::post('/v1/migrations/csv/exports')
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
}
// getting databasetype
$resources = explode(':', $resourceId);
$databaseId = $resources[0];
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$databaseType = $database->getAttribute('type');
if (!in_array($databaseType, CSV_ALLOWED_DATABASE_TYPES)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Database type not supported for csv');
}
$resources = Transfer::extractServices([getDatabaseTransferResourceServices($databaseType)]);
$migration = $dbForProject->createDocument('migrations', new Document([
'$id' => ID::unique(),
'status' => 'pending',
'stage' => 'init',
'source' => Appwrite::getName(),
'destination' => CSV::getName(),
'resources' => Transfer::extractServices([Transfer::GROUP_DATABASES]),
'resources' => $resources,
'resourceId' => $resourceId,
'resourceType' => Resource::TYPE_DATABASE,
'statusCounters' => '{}',
@@ -678,7 +705,7 @@ Http::get('/v1/migrations/:migrationId')
)
]
))
->param('migrationId', '', new UID(), 'Migration unique ID.')
->param('migrationId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Migration unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $migrationId, Response $response, Database $dbForProject) {
@@ -713,12 +740,10 @@ Http::get('/v1/migrations/appwrite/report')
->param('projectID', '', new Text(512), "Source's Project ID")
->param('key', '', new Text(512), "Source's API Key")
->inject('response')
->inject('dbForProject')
->inject('project')
->inject('user')
->action(function (array $resources, string $endpoint, string $projectID, string $key, Response $response) {
->inject('getDatabasesDB')
->action(function (array $resources, string $endpoint, string $projectID, string $key, Response $response, callable $getDatabasesDB) {
$appwrite = new Appwrite($projectID, $endpoint, $key);
$appwrite = new Appwrite($projectID, $endpoint, $key, $getDatabasesDB);
try {
$report = $appwrite->report($resources);
@@ -911,7 +936,7 @@ Http::patch('/v1/migrations/:migrationId')
)
]
))
->param('migrationId', '', new UID(), 'Migration unique ID.')
->param('migrationId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Migration unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('project')
@@ -965,7 +990,7 @@ Http::delete('/v1/migrations/:migrationId')
],
contentType: ContentType::NONE
))
->param('migrationId', '', new UID(), 'Migration ID.')
->param('migrationId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Migration ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
+63 -3
View File
@@ -62,16 +62,33 @@ Http::get('/v1/project/usage')
METRIC_EXECUTIONS_MB_SECONDS,
METRIC_BUILDS_MB_SECONDS,
METRIC_DOCUMENTS,
METRIC_DOCUMENTS_DOCUMENTSDB,
METRIC_DATABASES,
METRIC_DATABASES_DOCUMENTSDB,
METRIC_USERS,
METRIC_BUCKETS,
METRIC_FILES_STORAGE,
METRIC_DATABASES_STORAGE,
METRIC_DATABASES_STORAGE_DOCUMENTSDB,
METRIC_DEPLOYMENTS_STORAGE,
METRIC_BUILDS_STORAGE,
METRIC_DATABASES_OPERATIONS_READS,
METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB,
METRIC_DATABASES_OPERATIONS_WRITES,
METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB,
METRIC_FILES_IMAGES_TRANSFORMED,
// VectorDB totals
METRIC_DATABASES_VECTORDB,
METRIC_COLLECTIONS_VECTORDB,
METRIC_DOCUMENTS_VECTORDB,
METRIC_DATABASES_STORAGE_VECTORDB,
METRIC_DATABASES_OPERATIONS_READS_VECTORDB,
METRIC_DATABASES_OPERATIONS_WRITES_VECTORDB,
// Embeddings totals
METRIC_EMBEDDINGS_TEXT,
METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS,
METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION,
METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR
],
'period' => [
METRIC_NETWORK_REQUESTS,
@@ -80,11 +97,26 @@ Http::get('/v1/project/usage')
METRIC_USERS,
METRIC_EXECUTIONS,
METRIC_DATABASES_STORAGE,
METRIC_DATABASES_STORAGE_DOCUMENTSDB,
METRIC_EXECUTIONS_MB_SECONDS,
METRIC_BUILDS_MB_SECONDS,
METRIC_DATABASES_OPERATIONS_READS,
METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB,
METRIC_DATABASES_OPERATIONS_WRITES,
METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB,
METRIC_FILES_IMAGES_TRANSFORMED,
// VectorDB time series
METRIC_DATABASES_VECTORDB,
METRIC_COLLECTIONS_VECTORDB,
METRIC_DOCUMENTS_VECTORDB,
METRIC_DATABASES_STORAGE_VECTORDB,
METRIC_DATABASES_OPERATIONS_READS_VECTORDB,
METRIC_DATABASES_OPERATIONS_WRITES_VECTORDB,
// Embeddings time series
METRIC_EMBEDDINGS_TEXT,
METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS,
METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION,
METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR
]
];
@@ -357,8 +389,11 @@ Http::get('/v1/project/usage')
'buildsMbSecondsTotal' => $total[METRIC_BUILDS_MB_SECONDS],
'documentsTotal' => $total[METRIC_DOCUMENTS],
'rowsTotal' => $total[METRIC_DOCUMENTS],
'documentsdbDocumentsTotal' => $total[METRIC_DOCUMENTS_DOCUMENTSDB],
'databasesTotal' => $total[METRIC_DATABASES],
'documentsdbTotal' => $total[METRIC_DATABASES_DOCUMENTSDB],
'databasesStorageTotal' => $total[METRIC_DATABASES_STORAGE],
'documentsdbDatabasesStorageTotal' => $total[METRIC_DATABASES_STORAGE_DOCUMENTSDB],
'usersTotal' => $total[METRIC_USERS],
'bucketsTotal' => $total[METRIC_BUCKETS],
'filesStorageTotal' => $total[METRIC_FILES_STORAGE],
@@ -367,10 +402,27 @@ Http::get('/v1/project/usage')
'deploymentsStorageTotal' => $total[METRIC_DEPLOYMENTS_STORAGE],
'databasesReadsTotal' => $total[METRIC_DATABASES_OPERATIONS_READS],
'databasesWritesTotal' => $total[METRIC_DATABASES_OPERATIONS_WRITES],
'documentsdbDatabasesReadsTotal' => $total[METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB],
'documentsdbDatabasesWritesTotal' => $total[METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB],
'vectordbDatabasesTotal' => $total[METRIC_DATABASES_VECTORDB] ?? 0,
'vectordbCollectionsTotal' => $total[METRIC_COLLECTIONS_VECTORDB] ?? 0,
'vectordbDocumentsTotal' => $total[METRIC_DOCUMENTS_VECTORDB] ?? 0,
'vectordbDatabasesStorageTotal' => $total[METRIC_DATABASES_STORAGE_VECTORDB] ?? 0,
'vectordbDatabasesReadsTotal' => $total[METRIC_DATABASES_OPERATIONS_READS_VECTORDB] ?? 0,
'vectordbDatabasesWritesTotal' => $total[METRIC_DATABASES_OPERATIONS_WRITES_VECTORDB] ?? 0,
'executionsBreakdown' => $executionsBreakdown,
'bucketsBreakdown' => $bucketsBreakdown,
'databasesReads' => $usage[METRIC_DATABASES_OPERATIONS_READS],
'databasesWrites' => $usage[METRIC_DATABASES_OPERATIONS_WRITES],
'documentsdbDatabasesReads' => $usage[METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB],
'documentsdbDatabasesWrites' => $usage[METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB],
'documentsdbDatabasesStorage' => $usage[METRIC_DATABASES_STORAGE_DOCUMENTSDB],
'vectordbDatabases' => $usage[METRIC_DATABASES_VECTORDB] ?? [],
'vectordbCollections' => $usage[METRIC_COLLECTIONS_VECTORDB] ?? [],
'vectordbDocuments' => $usage[METRIC_DOCUMENTS_VECTORDB] ?? [],
'vectordbDatabasesStorage' => $usage[METRIC_DATABASES_STORAGE_VECTORDB] ?? [],
'vectordbDatabasesReads' => $usage[METRIC_DATABASES_OPERATIONS_READS_VECTORDB] ?? [],
'vectordbDatabasesWrites' => $usage[METRIC_DATABASES_OPERATIONS_WRITES_VECTORDB] ?? [],
'databasesStorageBreakdown' => $databasesStorageBreakdown,
'executionsMbSecondsBreakdown' => $executionsMbSecondsBreakdown,
'buildsMbSecondsBreakdown' => $buildsMbSecondsBreakdown,
@@ -380,6 +432,14 @@ Http::get('/v1/project/usage')
'authPhoneCountryBreakdown' => $authPhoneCountryBreakdown,
'imageTransformations' => $usage[METRIC_FILES_IMAGES_TRANSFORMED],
'imageTransformationsTotal' => $total[METRIC_FILES_IMAGES_TRANSFORMED],
'embeddingsText' => $usage[METRIC_EMBEDDINGS_TEXT] ?? [],
'embeddingsTextTokens' => $usage[METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS] ?? [],
'embeddingsTextDuration' => $usage[METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION] ?? [],
'embeddingsTextErrors' => $usage[METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR] ?? [],
'embeddingsTextTotal' => $total[METRIC_EMBEDDINGS_TEXT] ?? 0,
'embeddingsTextTokensTotal' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS] ?? 0,
'embeddingsTextDurationTotal' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION] ?? 0,
'embeddingsTextErrorsTotal' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR] ?? 0,
]), Response::MODEL_USAGE_PROJECT);
});
@@ -496,7 +556,7 @@ Http::get('/v1/project/variables/:variableId')
)
]
))
->param('variableId', '', new UID(), 'Variable unique ID.', false)
->param('variableId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Variable unique ID.', false, ['dbForProject'])
->inject('response')
->inject('project')
->inject('dbForProject')
@@ -526,7 +586,7 @@ Http::put('/v1/project/variables/:variableId')
)
]
))
->param('variableId', '', new UID(), 'Variable unique ID.', false)
->param('variableId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Variable unique ID.', false, ['dbForProject'])
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
->param('value', null, new Nullable(new Text(8192, 0)), 'Variable value. Max length: 8192 chars.', true)
->param('secret', null, new Nullable(new Boolean()), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true)
@@ -585,7 +645,7 @@ Http::delete('/v1/project/variables/:variableId')
],
contentType: ContentType::NONE
))
->param('variableId', '', new UID(), 'Variable unique ID.', false)
->param('variableId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Variable unique ID.', false, ['dbForProject'])
->inject('project')
->inject('response')
->inject('dbForProject')
+46 -46
View File
@@ -71,7 +71,7 @@ Http::get('/v1/projects/:projectId')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, Response $response, Database $dbForPlatform) {
@@ -102,7 +102,7 @@ Http::patch('/v1/projects/:projectId/service')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.')
->param('status', null, new Boolean(), 'Service status.')
->inject('response')
@@ -140,7 +140,7 @@ Http::patch('/v1/projects/:projectId/service/all')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('status', null, new Boolean(), 'Service status.')
->inject('response')
->inject('dbForPlatform')
@@ -201,7 +201,7 @@ Http::patch('/v1/projects/:projectId/api')
]
)
])
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('api', '', new WhiteList(array_keys(Config::getParam('apis')), true), 'API name.')
->param('status', null, new Boolean(), 'API status.')
->inject('response')
@@ -259,7 +259,7 @@ Http::patch('/v1/projects/:projectId/api/all')
]
)
])
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('status', null, new Boolean(), 'API status.')
->inject('response')
->inject('dbForPlatform')
@@ -300,7 +300,7 @@ Http::patch('/v1/projects/:projectId/oauth2')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'Provider Name')
->param('appId', null, new Nullable(new Text(256)), 'Provider app ID. Max length: 256 chars.', true)
->param('secret', null, new Nullable(new text(512)), 'Provider secret key. Max length: 512 chars.', true)
@@ -351,7 +351,7 @@ Http::patch('/v1/projects/:projectId/auth/session-alerts')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('alerts', false, new Boolean(true), 'Set to true to enable session emails.')
->inject('response')
->inject('dbForPlatform')
@@ -389,7 +389,7 @@ Http::patch('/v1/projects/:projectId/auth/memberships-privacy')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('userName', true, new Boolean(true), 'Set to true to show userName to members of a team.')
->param('userEmail', true, new Boolean(true), 'Set to true to show email to members of a team.')
->param('mfa', true, new Boolean(true), 'Set to true to show mfa to members of a team.')
@@ -431,7 +431,7 @@ Http::patch('/v1/projects/:projectId/auth/limit')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('limit', false, new Range(0, APP_LIMIT_USERS), 'Set the max number of users allowed in this project. Use 0 for unlimited.')
->inject('response')
->inject('dbForPlatform')
@@ -469,7 +469,7 @@ Http::patch('/v1/projects/:projectId/auth/duration')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('duration', 31536000, new Range(0, 31536000), 'Project session length in seconds. Max length: 31536000 seconds.')
->inject('response')
->inject('dbForPlatform')
@@ -507,7 +507,7 @@ Http::patch('/v1/projects/:projectId/auth/:method')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false)
->param('status', false, new Boolean(true), 'Set the status of this auth method.')
->inject('response')
@@ -548,7 +548,7 @@ Http::patch('/v1/projects/:projectId/auth/password-history')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0')
->inject('response')
->inject('dbForPlatform')
@@ -586,7 +586,7 @@ Http::patch('/v1/projects/:projectId/auth/password-dictionary')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('enabled', false, new Boolean(false), 'Set whether or not to enable checking user\'s password against most commonly used passwords. Default is false.')
->inject('response')
->inject('dbForPlatform')
@@ -624,7 +624,7 @@ Http::patch('/v1/projects/:projectId/auth/personal-data')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('enabled', false, new Boolean(false), 'Set whether or not to check a password for similarity with personal data. Default is false.')
->inject('response')
->inject('dbForPlatform')
@@ -662,7 +662,7 @@ Http::patch('/v1/projects/:projectId/auth/max-sessions')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT)
->inject('response')
->inject('dbForPlatform')
@@ -700,7 +700,7 @@ Http::patch('/v1/projects/:projectId/auth/mock-numbers')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('numbers', '', new ArrayList(new MockNumber(), 10), 'An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.')
->inject('response')
->inject('dbForPlatform')
@@ -749,7 +749,7 @@ Http::delete('/v1/projects/:projectId')
],
contentType: ContentType::NONE
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->inject('response')
->inject('user')
->inject('dbForPlatform')
@@ -792,7 +792,7 @@ Http::post('/v1/projects/:projectId/webhooks')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true)
->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
@@ -857,7 +857,7 @@ Http::get('/v1/projects/:projectId/webhooks')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
->inject('dbForPlatform')
@@ -897,8 +897,8 @@ Http::get('/v1/projects/:projectId/webhooks/:webhookId')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('webhookId', '', new UID(), 'Webhook unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('webhookId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) {
@@ -938,8 +938,8 @@ Http::put('/v1/projects/:projectId/webhooks/:webhookId')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('webhookId', '', new UID(), 'Webhook unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('webhookId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForProject'])
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true)
->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
@@ -1004,8 +1004,8 @@ Http::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('webhookId', '', new UID(), 'Webhook unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('webhookId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) {
@@ -1051,8 +1051,8 @@ Http::delete('/v1/projects/:projectId/webhooks/:webhookId')
],
contentType: ContentType::NONE
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('webhookId', '', new UID(), 'Webhook unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('webhookId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) {
@@ -1098,7 +1098,7 @@ Http::post('/v1/projects/:projectId/keys')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
// TODO: When migrating to Platform API, mark keyId required for consistency
->param('keyId', 'unique()', new CustomId(), 'Key ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true)
->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
@@ -1163,7 +1163,7 @@ Http::get('/v1/projects/:projectId/keys')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('queries', [], new Keys(), '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(', ', Keys::ALLOWED_ATTRIBUTES), true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -1236,8 +1236,8 @@ Http::get('/v1/projects/:projectId/keys/:keyId')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('keyId', '', new UID(), 'Key unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('keyId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Key unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) {
@@ -1278,8 +1278,8 @@ Http::put('/v1/projects/:projectId/keys/:keyId')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('keyId', '', new UID(), 'Key unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('keyId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Key unique ID.', false, ['dbForProject'])
->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
->param('scopes', null, new Nullable(new ArrayList(new WhiteList(array_keys(Config::getParam('projectScopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE)), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
->param('expire', null, new Nullable(new DatetimeValidator()), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true)
@@ -1333,8 +1333,8 @@ Http::delete('/v1/projects/:projectId/keys/:keyId')
],
contentType: ContentType::NONE
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('keyId', '', new UID(), 'Key unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('keyId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Key unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) {
@@ -1425,7 +1425,7 @@ Http::post('/v1/projects/:projectId/platforms')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param(
'type',
null,
@@ -1503,7 +1503,7 @@ Http::get('/v1/projects/:projectId/platforms')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
->inject('dbForPlatform')
@@ -1543,8 +1543,8 @@ Http::get('/v1/projects/:projectId/platforms/:platformId')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('platformId', '', new UID(), 'Platform unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('platformId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Platform unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) {
@@ -1584,8 +1584,8 @@ Http::put('/v1/projects/:projectId/platforms/:platformId')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('platformId', '', new UID(), 'Platform unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('platformId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Platform unique ID.', false, ['dbForProject'])
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
->param('key', '', new Text(256), 'Package name for android or bundle ID for iOS. Max length: 256 chars.', true)
->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true)
@@ -1641,8 +1641,8 @@ Http::delete('/v1/projects/:projectId/platforms/:platformId')
],
contentType: ContentType::NONE
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('platformId', '', new UID(), 'Platform unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('platformId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Platform unique ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) {
@@ -1708,7 +1708,7 @@ Http::patch('/v1/projects/:projectId/smtp')
]
)
])
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('enabled', false, new Boolean(), 'Enable custom SMTP service')
->param('senderName', '', new Text(255, 0), 'Name of the email sender', true)
->param('senderEmail', '', new Email(), 'Email of the sender', true)
@@ -1826,7 +1826,7 @@ Http::post('/v1/projects/:projectId/smtp/tests')
]
)
])
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('emails', [], new ArrayList(new Email(), 10), 'Array of emails to send test email to. Maximum of 10 emails are allowed.')
->param('senderName', System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'), new Text(255, 0), 'Name of the email sender')
->param('senderEmail', System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM), new Email(), 'Email of the sender')
@@ -2317,7 +2317,7 @@ Http::patch('/v1/projects/:projectId/auth/session-invalidation')
)
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForProject'])
->param('enabled', false, new Boolean(), 'Update authentication session invalidation status. Use this endpoint to enable or disable session invalidation on password change')
->inject('response')
->inject('dbForPlatform')
+18 -18
View File
@@ -79,9 +79,9 @@ Http::post('/v1/teams')
)
]
))
->param('teamId', '', new CustomId(), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('teamId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('name', null, new Text(128), 'Team name. Max length: 128 chars.')
->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true)
->param('roles', ['owner'], fn (Database $dbForProject) => new ArrayList(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true, ['dbForProject'])
->inject('response')
->inject('user')
->inject('dbForProject')
@@ -240,7 +240,7 @@ Http::get('/v1/teams/:teamId')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $teamId, Response $response, Database $dbForProject) {
@@ -271,7 +271,7 @@ Http::get('/v1/teams/:teamId/prefs')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $teamId, Response $response, Database $dbForProject) {
@@ -313,7 +313,7 @@ Http::put('/v1/teams/:teamId')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->param('name', null, new Text(128), 'New team name. Max length: 128 chars.')
->inject('requestTimestamp')
->inject('response')
@@ -359,7 +359,7 @@ Http::put('/v1/teams/:teamId/prefs')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
->inject('response')
->inject('dbForProject')
@@ -407,7 +407,7 @@ Http::delete('/v1/teams/:teamId')
],
contentType: ContentType::NONE
))
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->inject('response')
->inject('getProjectDB')
->inject('dbForProject')
@@ -473,9 +473,9 @@ Http::post('/v1/teams/:teamId/memberships')
]
))
->label('abuse-limit', 10)
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'Email of the new team member.', true)
->param('userId', '', new UID(), 'ID of the user to be added to a team.', true)
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'ID of the user to be added to a team.', true, ['dbForProject'])
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('roles', [], new ArrayList(new Key(maxLength: 81), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project']) // For project-specific permissions, roles will be in the format `project-<projectId>-<role>`. Template takes 9 characters, `projectId` and `role` can be upto 36 characters. In total, 81 characters.
->param('url', '', fn ($redirectValidator) => $redirectValidator, 'URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['redirectValidator']) // TODO add our own built-in confirm page
@@ -845,7 +845,7 @@ Http::get('/v1/teams/:teamId/memberships')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->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)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
@@ -982,8 +982,8 @@ Http::get('/v1/teams/:teamId/memberships/:membershipId')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('membershipId', '', new UID(), 'Membership ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->param('membershipId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Membership ID.', false, ['dbForProject'])
->inject('response')
->inject('project')
->inject('dbForProject')
@@ -1172,9 +1172,9 @@ Http::patch('/v1/teams/:teamId/memberships/:membershipId/status')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('membershipId', '', new UID(), 'Membership ID.')
->param('userId', '', new UID(), 'User ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->param('membershipId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Membership ID.', false, ['dbForProject'])
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('secret', '', new Text(256), 'Secret key.')
->inject('request')
->inject('response')
@@ -1339,8 +1339,8 @@ Http::delete('/v1/teams/:teamId/memberships/:membershipId')
],
contentType: ContentType::NONE
))
->param('teamId', '', new UID(), 'Team ID.')
->param('membershipId', '', new UID(), 'Membership ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->param('membershipId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Membership ID.', false, ['dbForProject'])
->inject('user')
->inject('project')
->inject('response')
@@ -1435,7 +1435,7 @@ Http::get('/v1/teams/:teamId/logs')
)
]
))
->param('teamId', '', new UID(), 'Team ID.')
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
+48 -48
View File
@@ -246,7 +246,7 @@ Http::post('/v1/users')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', null, new Nullable(new EmailValidator()), 'User email.', true)
->param('phone', null, new Nullable(new Phone()), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'Plain text user password. Must be at least 8 chars.', true, ['project', 'passwordsDictionary'])
@@ -283,7 +283,7 @@ Http::post('/v1/users/bcrypt')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', new Password(), 'User password hashed using Bcrypt.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
@@ -321,7 +321,7 @@ Http::post('/v1/users/md5')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', new Password(), 'User password hashed using MD5.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
@@ -358,7 +358,7 @@ Http::post('/v1/users/argon2')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', new Password(), 'User password hashed using Argon2.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
@@ -395,7 +395,7 @@ Http::post('/v1/users/sha')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', new Password(), 'User password hashed using SHA.')
->param('passwordVersion', '', new WhiteList(['sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512']), "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", true)
@@ -436,7 +436,7 @@ Http::post('/v1/users/phpass')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', new Password(), 'User password hashed using PHPass.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
@@ -473,7 +473,7 @@ Http::post('/v1/users/scrypt')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', new Password(), 'User password hashed using Scrypt.')
->param('passwordSalt', '', new Text(128), 'Optional salt used to hash password.')
@@ -521,7 +521,7 @@ Http::post('/v1/users/scrypt-modified')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('email', '', new EmailValidator(), 'User email.')
->param('password', '', new Password(), 'User password hashed using Scrypt Modified.')
->param('passwordSalt', '', new Text(128), 'Salt used to hash password.')
@@ -566,11 +566,11 @@ Http::post('/v1/users/:userId/targets')
)
]
))
->param('targetId', '', new CustomId(), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', new UID(), 'User ID.')
->param('targetId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('providerType', '', new WhiteList([MESSAGE_TYPE_EMAIL, MESSAGE_TYPE_SMS, MESSAGE_TYPE_PUSH]), 'The target provider type. Can be one of the following: `email`, `sms` or `push`.')
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)')
->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true)
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true, ['dbForProject'])
->param('name', '', new Text(128), 'Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.', true)
->inject('queueForEvents')
->inject('response')
@@ -731,7 +731,7 @@ Http::get('/v1/users/:userId')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $userId, Response $response, Database $dbForProject) {
@@ -762,7 +762,7 @@ Http::get('/v1/users/:userId/prefs')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $userId, Response $response, Database $dbForProject) {
@@ -795,8 +795,8 @@ Http::get('/v1/users/:userId/targets/:targetId')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('targetId', '', new UID(), 'Target ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $userId, string $targetId, Response $response, Database $dbForProject) {
@@ -833,7 +833,7 @@ Http::get('/v1/users/:userId/sessions')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
->inject('dbForProject')
@@ -877,7 +877,7 @@ Http::get('/v1/users/:userId/memberships')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->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)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
@@ -932,7 +932,7 @@ Http::get('/v1/users/:userId/logs')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -1019,7 +1019,7 @@ Http::get('/v1/users/:userId/targets')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
@@ -1147,7 +1147,7 @@ Http::patch('/v1/users/:userId/status')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('status', null, new Boolean(true), 'User Status. To activate the user pass `true` and to block the user pass `false`.')
->inject('response')
->inject('dbForProject')
@@ -1188,7 +1188,7 @@ Http::put('/v1/users/:userId/labels')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), APP_LIMIT_ARRAY_LABELS_SIZE), 'Array of user labels. Replaces the previous labels. Maximum of ' . APP_LIMIT_ARRAY_LABELS_SIZE . ' labels are allowed, each up to 36 alphanumeric characters long.')
->inject('response')
->inject('dbForProject')
@@ -1231,7 +1231,7 @@ Http::patch('/v1/users/:userId/verification/phone')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('phoneVerification', false, new Boolean(), 'User phone verification status.')
->inject('response')
->inject('dbForProject')
@@ -1273,7 +1273,7 @@ Http::patch('/v1/users/:userId/name')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('name', '', new Text(128, 0), 'User name. Max length: 128 chars.')
->inject('response')
->inject('dbForProject')
@@ -1316,7 +1316,7 @@ Http::patch('/v1/users/:userId/password')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, enabled: $project->getAttribute('auths', [])['passwordDictionary'] ?? false, allowEmpty: true), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary'])
->inject('response')
->inject('project')
@@ -1415,7 +1415,7 @@ Http::patch('/v1/users/:userId/email')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('email', '', new EmailValidator(allowEmpty: true), 'User email.')
->inject('response')
->inject('dbForProject')
@@ -1526,7 +1526,7 @@ Http::patch('/v1/users/:userId/phone')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('number', '', new Phone(allowEmpty: true), 'User phone number.')
->inject('response')
->inject('dbForProject')
@@ -1616,7 +1616,7 @@ Http::patch('/v1/users/:userId/verification')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('emailVerification', false, new Boolean(), 'User email verification status.')
->inject('response')
->inject('dbForProject')
@@ -1654,7 +1654,7 @@ Http::patch('/v1/users/:userId/prefs')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
->inject('response')
->inject('dbForProject')
@@ -1695,10 +1695,10 @@ Http::patch('/v1/users/:userId/targets/:targetId')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('targetId', '', new UID(), 'Target ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true)
->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true)
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true, ['dbForProject'])
->param('name', '', new Text(128), 'Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.', true)
->inject('queueForEvents')
->inject('response')
@@ -1820,7 +1820,7 @@ Http::patch('/v1/users/:userId/mfa')
]
)
])
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('mfa', null, new Boolean(), 'Enable or disable MFA.')
->inject('response')
->inject('dbForProject')
@@ -1880,7 +1880,7 @@ Http::get('/v1/users/:userId/mfa/factors')
]
)
])
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $userId, Response $response, Database $dbForProject) {
@@ -1939,7 +1939,7 @@ Http::get('/v1/users/:userId/mfa/recovery-codes')
]
)
])
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->action(function (string $userId, Response $response, Database $dbForProject) {
@@ -2004,7 +2004,7 @@ Http::patch('/v1/users/:userId/mfa/recovery-codes')
]
)
])
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -2077,7 +2077,7 @@ Http::put('/v1/users/:userId/mfa/recovery-codes')
public: false,
)
])
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -2150,7 +2150,7 @@ Http::delete('/v1/users/:userId/mfa/authenticators/:type')
contentType: ContentType::NONE
)
])
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.')
->inject('response')
->inject('dbForProject')
@@ -2197,7 +2197,7 @@ Http::post('/v1/users/:userId/sessions')
)
]
))
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForProject'])
->inject('request')
->inject('response')
->inject('dbForProject')
@@ -2289,7 +2289,7 @@ Http::post('/v1/users/:userId/tokens')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('length', 6, new Range(4, 128), 'Token length in characters. The default length is 6 characters', true)
->param('expire', TOKEN_EXPIRATION_GENERIC, new Range(60, TOKEN_EXPIRATION_LOGIN_LONG), 'Token expiration period in seconds. The default expiration is 15 minutes.', true)
->inject('request')
@@ -2355,8 +2355,8 @@ Http::delete('/v1/users/:userId/sessions/:sessionId')
],
contentType: ContentType::NONE
))
->param('userId', '', new UID(), 'User ID.')
->param('sessionId', '', new UID(), 'Session ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -2406,7 +2406,7 @@ Http::delete('/v1/users/:userId/sessions')
],
contentType: ContentType::NONE
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -2456,7 +2456,7 @@ Http::delete('/v1/users/:userId')
],
contentType: ContentType::NONE
))
->param('userId', '', new UID(), 'User ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -2508,8 +2508,8 @@ Http::delete('/v1/users/:userId/targets/:targetId')
],
contentType: ContentType::NONE
))
->param('userId', '', new UID(), 'User ID.')
->param('targetId', '', new UID(), 'Target ID.')
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
->inject('queueForEvents')
->inject('queueForDeletes')
->inject('response')
@@ -2566,7 +2566,7 @@ Http::delete('/v1/users/identities/:identityId')
],
contentType: ContentType::NONE,
))
->param('identityId', '', new UID(), 'Identity ID.')
->param('identityId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Identity ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -2605,8 +2605,8 @@ Http::post('/v1/users/:userId/jwts')
)
]
))
->param('userId', '', new UID(), 'User ID.')
->param('sessionId', '', new UID(), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true)
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true, ['dbForProject'])
->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true)
->inject('response')
->inject('dbForProject')
-1
View File
@@ -31,7 +31,6 @@ Http::get('/v1/mock/tests/general/oauth2')
->param('state', '', new Text(1024), 'OAuth2 state.')
->inject('response')
->action(function (string $client_id, string $redirectURI, string $scope, string $state, Response $response) {
$response->redirect($redirectURI . '?' . \http_build_query(['code' => 'abcdef', 'state' => $state]));
});
+8
View File
@@ -460,6 +460,12 @@ Http::init()
->action(function (Http $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) {
$route = $utopia->getRoute();
$path = $route->getMatchedPath();
$databaseType = match (true) {
str_contains($path, '/documentsdb') => DATABASE_TYPE_DOCUMENTSDB,
str_contains($path, '/vectordb') => DATABASE_TYPE_VECTORDB,
default => '',
};
if (
array_key_exists('rest', $project->getAttribute('apis', []))
@@ -472,6 +478,7 @@ Http::init()
/*
* Abuse Check
*/
$abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}');
$timeLimitArray = [];
@@ -507,6 +514,7 @@ Http::init()
$abuse = new Abuse($timeLimit);
$remaining = $timeLimit->remaining();
$limit = $timeLimit->limit();
$time = $timeLimit->time() + $route->getLabel('abuse-time', 3600);
+60 -15
View File
@@ -192,8 +192,8 @@ include __DIR__ . '/controllers/general.php';
function createDatabase(Http $app, string $resourceKey, string $dbName, array $collections, mixed $pools, ?callable $extraSetup = null): void
{
$max = 10;
$sleep = 1;
$max = 15;
$sleep = 2;
$attempts = 0;
while (true) {
@@ -203,7 +203,7 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
/* @var $database Database */
$database = is_callable($resource) ? $resource() : $resource;
break; // exit loop on success
} catch (\Exception $e) {
} catch (\Throwable $e) {
Console::warning(" └── Database not ready. Retrying connection ({$attempts})...");
if ($attempts >= $max) {
throw new \Exception(' └── Failed to connect to database: ' . $e->getMessage());
@@ -215,11 +215,26 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
Span::init("database.setup");
Span::add('database.name', $dbName);
// Attempt to create the database
try {
$database->create();
} catch (\Exception $e) {
Span::add('database.exists', true);
$attempts = 0;
while (true) {
try {
$attempts++;
$database->create();
break; // exit loop on success
} catch (\Exception $e) {
if ($e instanceof DuplicateException) {
Console::info(" └── Skip: metadata table already exists");
Span::add('database.exists', true);
break;
}
Console::warning(" └── Database create failed. Retrying ({$attempts})...");
if ($attempts >= $max) {
throw new \Exception(' └── Failed to create database: ' . $e->getMessage());
}
\sleep($sleep);
}
}
// Process collections
@@ -389,13 +404,29 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $tot
});
$projectCollections = $collections['projects'];
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
$sharedTablesV2 = \array_diff($sharedTables, $sharedTablesV1);
$documentsSharedTables = \explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES', ''));
$documentsSharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES_V1', ''));
$documentsSharedTablesV2 = \array_diff($documentsSharedTables, $documentsSharedTablesV1);
$vectorSharedTables = \explode(',', System::getEnv('_APP_DATABASE_VECTORDB_SHARED_TABLES', ''));
$vectorSharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_VECTORDB_SHARED_TABLES_V1', ''));
$vectorSharedTablesV2 = \array_diff($vectorSharedTables, $vectorSharedTablesV1);
$cache = $app->getResource('cache');
foreach ($sharedTablesV2 as $hostname) {
// All shared tables V2 pools that need project metadata collections
$sharedTablesV2All = \array_values(\array_unique(\array_filter([
...$sharedTablesV2,
...$documentsSharedTablesV2,
...$vectorSharedTablesV2,
])));
foreach ($sharedTablesV2All as $hostname) {
Span::init('database.setup');
Span::add('database.hostname', $hostname);
@@ -406,10 +437,24 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $tot
->setTenant(null)
->setNamespace(System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''));
try {
$dbForProject->create();
} catch (DuplicateException) {
Span::add('database.exists', true);
$max = 15;
$sleep = 2;
$attempts = 0;
while (true) {
try {
$attempts++;
$dbForProject->create();
break; // exit loop on success
} catch (DuplicateException) {
Span::add('database.exists', true);
break;
} catch (\Throwable $e) {
Console::warning(" └── Project database create failed. Retrying ({$attempts})...");
if ($attempts >= $max) {
throw new \Exception(' └── Failed to create project database: ' . $e->getMessage());
}
sleep($sleep);
}
}
if ($dbForProject->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) {
@@ -610,7 +655,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register) {
if ($latestDocument !== null) {
$queries[] = Query::cursorAfter($latestDocument);
}
if ($lastSyncUpdate != null) {
if ($lastSyncUpdate !== null) {
$queries[] = Query::greaterThanEqual('$updatedAt', $lastSyncUpdate);
}
$results = [];
@@ -618,7 +663,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register) {
$authorization = $app->getResource('authorization');
$results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries));
} catch (Throwable $th) {
Console::error($th->getMessage());
Console::error('rules ' . $th->getMessage());
}
$sum = count($results);
+53
View File
@@ -286,6 +286,45 @@ 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';
// documentsdb
const METRIC_DATABASES_DOCUMENTSDB = 'documentsdb.databases';
const METRIC_COLLECTIONS_DOCUMENTSDB = 'documentsdb.collections';
const METRIC_DATABASES_STORAGE_DOCUMENTSDB = 'documentsdb.databases.storage';
const METRIC_DATABASE_ID_COLLECTIONS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.collections';
const METRIC_DATABASE_ID_STORAGE_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.databases.storage';
const METRIC_DOCUMENTS_DOCUMENTSDB = 'documentsdb.documents';
const METRIC_DATABASE_ID_DOCUMENTS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.{collectionInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.{collectionInternalId}.databases.storage';
const METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB = 'documentsdb.databases.operations.reads';
const METRIC_DATABASE_ID_OPERATIONS_READS_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.databases.operations.reads';
const METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB = 'documentsdb.databases.operations.writes';
const METRIC_DATABASE_ID_OPERATIONS_WRITES_DOCUMENTSDB = 'documentsdb.{databaseInternalId}.databases.operations.writes';
// vectordb
const METRIC_DATABASES_VECTORDB = 'vectordb.databases';
const METRIC_COLLECTIONS_VECTORDB = 'vectordb.collections';
const METRIC_DATABASES_STORAGE_VECTORDB = 'vectordb.databases.storage';
const METRIC_DATABASE_ID_COLLECTIONS_VECTORDB = 'vectordb.{databaseInternalId}.collections';
const METRIC_DATABASE_ID_STORAGE_VECTORDB = 'vectordb.{databaseInternalId}.databases.storage';
const METRIC_DOCUMENTS_VECTORDB = 'vectordb.documents';
const METRIC_DATABASE_ID_DOCUMENTS_VECTORDB = 'vectordb.{databaseInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS_VECTORDB = 'vectordb.{databaseInternalId}.{collectionInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE_VECTORDB = 'vectordb.{databaseInternalId}.{collectionInternalId}.databases.storage';
const METRIC_DATABASES_OPERATIONS_READS_VECTORDB = 'vectordb.databases.operations.reads';
const METRIC_DATABASE_ID_OPERATIONS_READS_VECTORDB = 'vectordb.{databaseInternalId}.databases.operations.reads';
const METRIC_DATABASES_OPERATIONS_WRITES_VECTORDB = 'vectordb.databases.operations.writes';
const METRIC_DATABASE_ID_OPERATIONS_WRITES_VECTORDB = 'vectordb.{databaseInternalId}.databases.operations.writes';
const METRIC_EMBEDDINGS_TEXT = 'embeddings.text';
const METRIC_EMBEDDINGS_MODEL_TEXT = 'embeddings.text.{embeddingModel}';
const METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR = 'embeddings.text.totalErrors';
const METRIC_EMBEDDINGS_MODEL_TEXT_TOTAL_ERROR = 'embeddings.text.{embeddingModel}.totalErrors';
const METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION = 'embeddings.text.totalDuration';
const METRIC_EMBEDDINGS_MODEL_TEXT_TOTAL_DURATION = 'embeddings.text.{embeddingModel}.totalDuration';
const METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS = 'embeddings.text.totalTokens';
const METRIC_EMBEDDINGS_MODEL_TEXT_TOTAL_TOKENS = 'embeddings.text.{embeddingModel}.totalTokens';
const METRIC_BUCKETS = 'buckets';
const METRIC_FILES = 'files';
const METRIC_FILES_STORAGE = 'files.storage';
@@ -372,6 +411,7 @@ const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers';
const RESOURCE_TYPE_MESSAGES = 'messages';
const RESOURCE_TYPE_EXECUTIONS = 'executions';
const RESOURCE_TYPE_VCS = 'vcs';
const RESOURCE_TYPE_EMBEDDINGS_TEXT = 'embeddingsText';
// Resource types for Tokens
const TOKENS_RESOURCE_TYPE_FILES = 'files';
@@ -393,3 +433,16 @@ const CACHE_RECONNECT_RETRY_DELAY = 1000;
// Project status
const PROJECT_STATUS_ACTIVE = 'active';
// Database types
const DATABASE_TYPE_LEGACY = 'legacy';
const DATABASE_TYPE_TABLESDB = 'tablesdb';
const DATABASE_TYPE_DOCUMENTSDB = 'documentsdb';
const DATABASE_TYPE_VECTORDB = 'vectordb';
// CSV import/export allowed database types
const CSV_ALLOWED_DATABASE_TYPES = [
DATABASE_TYPE_LEGACY,
DATABASE_TYPE_TABLESDB,
DATABASE_TYPE_VECTORDB
];
+22
View File
@@ -22,6 +22,7 @@ use Appwrite\Utopia\Response\Model\AttributeLine;
use Appwrite\Utopia\Response\Model\AttributeList;
use Appwrite\Utopia\Response\Model\AttributeLongtext;
use Appwrite\Utopia\Response\Model\AttributeMediumtext;
use Appwrite\Utopia\Response\Model\AttributeObject;
use Appwrite\Utopia\Response\Model\AttributePoint;
use Appwrite\Utopia\Response\Model\AttributePolygon;
use Appwrite\Utopia\Response\Model\AttributeRelationship;
@@ -29,6 +30,7 @@ use Appwrite\Utopia\Response\Model\AttributeString;
use Appwrite\Utopia\Response\Model\AttributeText;
use Appwrite\Utopia\Response\Model\AttributeURL;
use Appwrite\Utopia\Response\Model\AttributeVarchar;
use Appwrite\Utopia\Response\Model\AttributeVector;
use Appwrite\Utopia\Response\Model\AuthProvider;
use Appwrite\Utopia\Response\Model\BaseList;
use Appwrite\Utopia\Response\Model\Branch;
@@ -65,6 +67,7 @@ use Appwrite\Utopia\Response\Model\DetectionRuntime;
use Appwrite\Utopia\Response\Model\DetectionVariable;
use Appwrite\Utopia\Response\Model\DevKey;
use Appwrite\Utopia\Response\Model\Document as ModelDocument;
use Appwrite\Utopia\Response\Model\Embedding;
use Appwrite\Utopia\Response\Model\Error;
use Appwrite\Utopia\Response\Model\ErrorDev;
use Appwrite\Utopia\Response\Model\Execution;
@@ -136,6 +139,8 @@ use Appwrite\Utopia\Response\Model\UsageBuckets;
use Appwrite\Utopia\Response\Model\UsageCollection;
use Appwrite\Utopia\Response\Model\UsageDatabase;
use Appwrite\Utopia\Response\Model\UsageDatabases;
use Appwrite\Utopia\Response\Model\UsageDocumentsDB;
use Appwrite\Utopia\Response\Model\UsageDocumentsDBs;
use Appwrite\Utopia\Response\Model\UsageFunction;
use Appwrite\Utopia\Response\Model\UsageFunctions;
use Appwrite\Utopia\Response\Model\UsageProject;
@@ -144,9 +149,12 @@ use Appwrite\Utopia\Response\Model\UsageSites;
use Appwrite\Utopia\Response\Model\UsageStorage;
use Appwrite\Utopia\Response\Model\UsageTable;
use Appwrite\Utopia\Response\Model\UsageUsers;
use Appwrite\Utopia\Response\Model\UsageVectorDB;
use Appwrite\Utopia\Response\Model\UsageVectorDBs;
use Appwrite\Utopia\Response\Model\User;
use Appwrite\Utopia\Response\Model\Variable;
use Appwrite\Utopia\Response\Model\VcsContent;
use Appwrite\Utopia\Response\Model\VectorDBCollection;
use Appwrite\Utopia\Response\Model\Webhook;
// General
@@ -211,9 +219,12 @@ Response::setModel(new BaseList('Migrations List', Response::MODEL_MIGRATION_LIS
Response::setModel(new BaseList('Migrations Firebase Projects List', Response::MODEL_MIGRATION_FIREBASE_PROJECT_LIST, 'projects', Response::MODEL_MIGRATION_FIREBASE_PROJECT));
Response::setModel(new BaseList('Specifications List', Response::MODEL_SPECIFICATION_LIST, 'specifications', Response::MODEL_SPECIFICATION));
Response::setModel(new BaseList('VCS Content List', Response::MODEL_VCS_CONTENT_LIST, 'contents', Response::MODEL_VCS_CONTENT));
Response::setModel(new BaseList('VectorDB Collections List', Response::MODEL_VECTORDB_COLLECTION_LIST, 'collections', Response::MODEL_VECTORDB_COLLECTION));
Response::setModel(new BaseList('Embedding list', Response::MODEL_EMBEDDING_LIST, 'embeddings', Response::MODEL_EMBEDDING));
// Entities
Response::setModel(new Database());
Response::setModel(new Embedding());
// Collection API Models
Response::setModel(new Collection());
@@ -237,6 +248,17 @@ Response::setModel(new AttributeText());
Response::setModel(new AttributeMediumtext());
Response::setModel(new AttributeLongtext());
// DocumentsDB API Models
Response::setModel(new UsageDocumentsDBs());
Response::setModel(new UsageDocumentsDB());
// VectorDB API Models
Response::setModel(new VectorDBCollection());
Response::setModel(new AttributeObject());
Response::setModel(new AttributeVector());
Response::setModel(new UsageVectorDBs());
Response::setModel(new UsageVectorDB());
// Table API Models
Response::setModel(new Table());
Response::setModel(new Column());
+75 -16
View File
@@ -12,6 +12,7 @@ use Utopia\Cache\Adapter\Redis as RedisCache;
use Utopia\Config\Config;
use Utopia\Console;
use Utopia\Database\Adapter\MariaDB;
use Utopia\Database\Adapter\Mongo;
use Utopia\Database\Adapter\MySQL;
use Utopia\Database\Adapter\Postgres;
use Utopia\Database\Adapter\SQL;
@@ -24,6 +25,7 @@ use Utopia\Logger\Adapter\LogOwl;
use Utopia\Logger\Adapter\Raygun;
use Utopia\Logger\Adapter\Sentry;
use Utopia\Logger\Logger;
use Utopia\Mongo\Client as MongoClient;
use Utopia\Pools\Adapter\Stack as StackPool;
use Utopia\Pools\Adapter\Swoole as SwoolePool;
use Utopia\Pools\Group;
@@ -166,24 +168,53 @@ $register->set('pools', function () {
'pass' => System::getEnv('_APP_REDIS_PASS', ''),
]);
$fallbackForDocumentsDB = 'db_main=' . AppwriteURL::unparse([
'scheme' => System::getEnv('_APP_DB_ADAPTER_DOCUMENTSDB', 'mongodb'),
'host' => System::getEnv('_APP_DB_HOST_DOCUMENTSDB', 'mongodb'),
'port' => System::getEnv('_APP_DB_PORT_DOCUMENTSDB', '27017'),
'user' => System::getEnv('_APP_DB_USER', ''),
'pass' => System::getEnv('_APP_DB_PASS', ''),
'path' => System::getEnv('_APP_DB_SCHEMA', ''),
]);
$fallbackForVectorDB = 'db_main=' . AppwriteURL::unparse([
'scheme' => System::getEnv('_APP_DB_ADAPTER_VECTORDB', 'postgresql'),
'host' => System::getEnv('_APP_DB_HOST_VECTORDB', 'postgresql'),
'port' => System::getEnv('_APP_DB_PORT_VECTORDB', '5432'),
'user' => System::getEnv('_APP_DB_USER', ''),
'pass' => System::getEnv('_APP_DB_PASS', ''),
'path' => System::getEnv('_APP_DB_SCHEMA', ''),
]);
$connections = [
'console' => [
'type' => 'database',
'dsns' => $fallbackForDB,
'multiple' => false,
'schemes' => ['mariadb', 'mysql','postgresql'],
'schemes' => ['mongodb','mariadb', 'mysql','postgresql'],
],
'database' => [
'type' => 'database',
'dsns' => $fallbackForDB,
'multiple' => true,
'schemes' => ['mariadb', 'mysql','postgresql'],
'schemes' => ['mongodb','mariadb', 'mysql','postgresql'],
],
'documentsdb' => [
'type' => 'database',
'dsns' => System::getEnv('_APP_CONNECTIONS_DATABASE_DOCUMENTSDB', $fallbackForDocumentsDB),
'multiple' => true,
'schemes' => ['mongodb'],
],
'vectordb' => [
'type' => 'database',
'dsns' => System::getEnv('_APP_CONNECTIONS_DATABASE_VECTORDB', $fallbackForVectorDB),
'multiple' => true,
'schemes' => ['postgresql'],
],
'logs' => [
'type' => 'database',
'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB),
'multiple' => false,
'schemes' => ['mariadb', 'mysql','postgresql'],
'schemes' => ['mongodb','mariadb', 'mysql','postgresql'],
],
'publisher' => [
'type' => 'publisher',
@@ -263,6 +294,7 @@ $register->set('pools', function () {
*
* Resource assignment to an adapter will happen below.
*/
$resource = match ($dsnScheme) {
'mysql',
'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
@@ -287,6 +319,27 @@ $register->set('pools', function () {
));
});
},
'mongodb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase, $dsn) {
try {
$mongo = new MongoClient($dsnDatabase, $dsnHost, (int)$dsnPort, $dsnUser, $dsnPass, false);
@$mongo->connect();
return $mongo;
} catch (\Throwable $e) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, "MongoDB connection failed: " . $e->getMessage());
}
},
'postgresql' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDO("pgsql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase}", $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);
@@ -302,7 +355,7 @@ $register->set('pools', function () {
$poolAdapter = System::getEnv('_APP_POOL_ADAPTER', default: 'stack') === 'swoole' ? new SwoolePool() : new StackPool();
$pool = new Pool($poolAdapter, $name, $poolSize, function () use ($type, $resource, $dsn) {
$pool = new Pool($poolAdapter, $name, $poolSize, function () use ($type, $resource, $dsn, $key) {
// Get Adapter
switch ($type) {
case 'database':
@@ -310,10 +363,14 @@ $register->set('pools', function () {
'mariadb' => new MariaDB($resource()),
'mysql' => new MySQL($resource()),
'postgresql' => new Postgres($resource()),
'mongodb' => new Mongo($resource()),
default => null
};
$adapter->setDatabase($dsn->getPath());
if ($key === 'documentsdb') {
$adapter->setSupportForAttributes(false);
}
return $adapter;
case 'pubsub':
return match ($dsn->getScheme()) {
@@ -364,11 +421,21 @@ $register->set('db', function () {
$dbPort = System::getEnv('_APP_DB_PORT', '');
$dbUser = System::getEnv('_APP_DB_USER', '');
$dbPass = System::getEnv('_APP_DB_PASS', '');
$dbSchema = System::getEnv('_APP_DB_SCHEMA', '');
$dbAdapter = System::getEnv('_APP_DB_ADAPTER', 'mariadb');
$dbScheme = System::getEnv('_APP_DB_SCHEMA', '');
$dbAdapter = System::getEnv('_APP_DB_ADAPTER', 'mongodb');
$dsn = '';
switch ($dbAdapter) {
case 'mongodb':
try {
$mongo = new MongoClient($dbScheme, $dbHost, (int)$dbPort, $dbUser, $dbPass, false);
@$mongo->connect();
return $mongo;
} catch (\Throwable $e) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, "MongoDB connection failed: " . $e->getMessage());
}
case 'postgresql':
$dsn = "pgsql:host={$dbHost};port={$dbPort};dbname={$dbSchema}";
break;
@@ -376,17 +443,9 @@ $register->set('db', function () {
case 'mysql':
case 'mariadb':
default:
$dsn = "mysql:host={$dbHost};port={$dbPort};dbname={$dbSchema};charset=utf8mb4";
break;
$dsn = "mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4";
return new PDO($dsn, $dbUser, $dbPass, SQL::getPDOAttributes());
}
return new PDO(
$dsn,
$dbUser,
$dbPass,
SQL::getPDOAttributes()
);
});
$register->set('smtp', function () {
+321 -12
View File
@@ -32,6 +32,8 @@ use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Executor\Executor;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\Agents\Adapters\Ollama;
use Utopia\Agents\Agent;
use Utopia\Audit\Adapter\Database as AdapterDatabase;
use Utopia\Audit\Audit;
use Utopia\Auth\Hashes\Argon2;
@@ -560,7 +562,8 @@ Http::setResource('authorization', function () {
return new Authorization();
}, []);
Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Response $response, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime, StatsUsage $queueForStatsUsage, Authorization $authorization) {
// TODO: check here do we really need the database listener for the dbForProject?
Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Response $response, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime, StatsUsage $queueForStatsUsage, Authorization $authorization, Request $request) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForPlatform;
}
@@ -668,7 +671,31 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor
$dbForProject->getCache()->purge($cacheKey);
};
$usageDatabaseListener = function (string $event, Document $document, StatsUsage $queueForStatsUsage) {
/**
* Prefix metrics with database type when applicable.
* Avoids prefixing for legacy and tablesdb types to preserve historical metrics.
*/
$getDatabaseTypePrefixedMetric = function (string $databaseType, string $metric): string {
if (
$databaseType === '' ||
$databaseType === DATABASE_TYPE_LEGACY ||
$databaseType === DATABASE_TYPE_TABLESDB
) {
return $metric;
}
return $databaseType . '.' . $metric;
};
// Determine database type from request path, similar to api.php
$path = $request->getURI();
$databaseType = match (true) {
str_contains($path, '/documentsdb') => DATABASE_TYPE_DOCUMENTSDB,
str_contains($path, '/vectordb') => DATABASE_TYPE_VECTORDB,
default => '',
};
$usageDatabaseListener = function (string $event, Document $document, StatsUsage $queueForStatsUsage) use ($getDatabaseTypePrefixedMetric, $databaseType) {
$value = 1;
switch ($event) {
@@ -700,7 +727,8 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor
$queueForStatsUsage->addMetric(METRIC_SESSIONS, $value); //per project
break;
case $document->getCollection() === 'databases': // databases
$queueForStatsUsage->addMetric(METRIC_DATABASES, $value); // per project
$metric = $getDatabaseTypePrefixedMetric($databaseType, METRIC_DATABASES);
$queueForStatsUsage->addMetric($metric, $value); // per project
if ($event === Database::EVENT_DOCUMENT_DELETE) {
$queueForStatsUsage->addReduce($document);
@@ -709,9 +737,11 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor
case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionMetric = $getDatabaseTypePrefixedMetric($databaseType, METRIC_COLLECTIONS);
$databaseIdCollectionMetric = $getDatabaseTypePrefixedMetric($databaseType, METRIC_DATABASE_ID_COLLECTIONS);
$queueForStatsUsage
->addMetric(METRIC_COLLECTIONS, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value);
->addMetric($collectionMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdCollectionMetric), $value);
if ($event === Database::EVENT_DOCUMENT_DELETE) {
$queueForStatsUsage->addReduce($document);
@@ -721,10 +751,13 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$documentsMetric = $getDatabaseTypePrefixedMetric($databaseType, METRIC_DOCUMENTS);
$databaseIdDocumentsMetric = $getDatabaseTypePrefixedMetric($databaseType, METRIC_DATABASE_ID_DOCUMENTS);
$databaseIdCollectionIdDocumentsMetric = $getDatabaseTypePrefixedMetric($databaseType, METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS);
$queueForStatsUsage
->addMetric(METRIC_DOCUMENTS, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_DOCUMENTS), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), $value); // per collection
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
break;
case $document->getCollection() === 'buckets': //buckets
$queueForStatsUsage
@@ -782,6 +815,9 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor
$queueForWebhooks = new Webhook($publisherWebhooks);
$queueForRealtime = new Realtime();
// to get consumed in the stats worker without calling to database
$queueForStatsUsage->setContext('database', new Document(['type' => $databaseType]));
$database
->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
@@ -805,7 +841,7 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForPlatfor
return $database;
}, ['pools', 'dbForPlatform', 'cache', 'project', 'response', 'publisher', 'publisherFunctions', 'publisherWebhooks', 'queueForEvents', 'queueForFunctions', 'queueForWebhooks', 'queueForRealtime', 'queueForStatsUsage', 'authorization']);
}, ['pools', 'dbForPlatform', 'cache', 'project', 'response', 'publisher', 'publisherFunctions', 'publisherWebhooks', 'queueForEvents', 'queueForFunctions', 'queueForWebhooks', 'queueForRealtime', 'queueForStatsUsage', 'authorization', 'request']);
Http::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) {
@@ -826,6 +862,270 @@ Http::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authori
return $database;
}, ['pools', 'cache', 'authorization']);
Http::setResource('getDatabasesDB', function (Group $pools, Cache $cache, Document $project, Request $request, StatsUsage $queueForStatsUsage, Authorization $authorization) {
return function (Document $database) use ($pools, $cache, $project, $request, $queueForStatsUsage, $authorization): Database {
$databaseDSN = $database->getAttribute('database', '');
$databaseType = $database->getAttribute('type', '');
try {
$databaseDSN = new DSN($databaseDSN);
} catch (\InvalidArgumentException) {
// for old databases migrated through patch script
// databaseDSN determines the adapter
$databaseDSN = new DSN('mysql://'.$databaseDSN);
}
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'));
}
$pool = $pools->get($databaseDSN->getHost());
$adapter = new DatabasePool($pool);
$database = new Database($adapter, $cache);
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$database
->setDatabase(APP_DATABASE)
->setAuthorization($authorization)
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant((int)$project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getSequence());
}
$timeout = \intval($request->getHeader('x-appwrite-timeout'));
if (!empty($timeout) && Http::isDevelopment()) {
$database->setTimeout($timeout);
}
// Register database event listeners for usage stats collection
$documentsMetric = METRIC_DOCUMENTS;
$databaseIdDocumentsMetric = METRIC_DATABASE_ID_DOCUMENTS;
$databaseIdCollectionIdDocumentsMetric = METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS;
if ($databaseType !== DATABASE_TYPE_LEGACY && $databaseType !== DATABASE_TYPE_TABLESDB) {
$documentsMetric = $databaseType. '.' .$documentsMetric;
$databaseIdDocumentsMetric = $databaseType. '.' .$databaseIdDocumentsMetric;
$databaseIdCollectionIdDocumentsMetric = $databaseType . '.' .$databaseIdCollectionIdDocumentsMetric;
}
$database
->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = 1;
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = -1;
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENTS_CREATE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = $document->getAttribute('modified', 0);
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENTS_DELETE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = -1 * $document->getAttribute('modified', 0);
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENTS_UPSERT, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = $document->getAttribute('created', 0);
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
});
return $database;
};
}, ['pools','cache','project','request','queueForStatsUsage','authorization']);
Http::setResource('getDatabasesDB', function (Group $pools, Cache $cache, Document $project, Request $request, StatsUsage $queueForStatsUsage, Authorization $authorization) {
return function (Document $database) use ($pools, $cache, $project, $request, $queueForStatsUsage, $authorization): Database {
$databaseDSN = $database->getAttribute('database', '');
$databaseType = $database->getAttribute('type', '');
try {
$databaseDSN = new DSN($databaseDSN);
} catch (\InvalidArgumentException) {
// for old databases migrated through patch script
// databaseDSN determines the adapter
$databaseDSN = new DSN('mysql://'.$databaseDSN);
}
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'));
}
$pool = $pools->get($databaseDSN->getHost());
$adapter = new DatabasePool($pool);
$database = new Database($adapter, $cache);
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$database
->setDatabase(APP_DATABASE)
->setAuthorization($authorization)
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant((int)$project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getSequence());
}
$timeout = \intval($request->getHeader('x-appwrite-timeout'));
if (!empty($timeout) && Http::isDevelopment()) {
$database->setTimeout($timeout);
}
// Register database event listeners for usage stats collection
$documentsMetric = METRIC_DOCUMENTS;
$databaseIdDocumentsMetric = METRIC_DATABASE_ID_DOCUMENTS;
$databaseIdCollectionIdDocumentsMetric = METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS;
if ($databaseType !== DATABASE_TYPE_LEGACY && $databaseType !== DATABASE_TYPE_TABLESDB) {
$documentsMetric = $databaseType. '.' .$documentsMetric;
$databaseIdDocumentsMetric = $databaseType. '.' .$databaseIdDocumentsMetric;
$databaseIdCollectionIdDocumentsMetric = $databaseType . '.' .$databaseIdCollectionIdDocumentsMetric;
}
$database
->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = 1;
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = -1;
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENTS_CREATE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = $document->getAttribute('modified', 0);
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENTS_DELETE, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = -1 * $document->getAttribute('modified', 0);
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
})
->on(Database::EVENT_DOCUMENTS_UPSERT, 'calculate-usage', function ($event, $document) use ($queueForStatsUsage, $documentsMetric, $databaseIdDocumentsMetric, $databaseIdCollectionIdDocumentsMetric) {
$value = $document->getAttribute('created', 0);
if (str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_')) {
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForStatsUsage
->addMetric($documentsMetric, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, $databaseIdDocumentsMetric), $value) // per database
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], $databaseIdCollectionIdDocumentsMetric), $value); // per collection
}
});
return $database;
};
}, ['pools','cache','project','request','queueForStatsUsage','authorization']);
Http::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) {
$databases = [];
@@ -1297,6 +1597,8 @@ Http::setResource('team', function (Document $project, Database $dbForPlatform,
}
}
// if teamInternalId is empty, return an empty document
if (empty($teamInternalId)) {
return new Document([]);
}
@@ -1434,9 +1736,9 @@ Http::setResource('resourceToken', function ($project, $dbForProject, $request,
return new Document([]);
}, ['project', 'dbForProject', 'request', 'authorization']);
Http::setResource('transactionState', function (Database $dbForProject, Authorization $authorization) {
return new TransactionState($dbForProject, $authorization);
}, ['dbForProject', 'authorization']);
Http::setResource('transactionState', function (Database $dbForProject, Authorization $authorization, callable $getDatabasesDB) {
return new TransactionState($dbForProject, $authorization, $getDatabasesDB);
}, ['dbForProject', 'authorization', 'getDatabasesDB']);
Http::setResource('executionsRetentionCount', function (Document $project, array $plan) {
if ($project->getId() === 'console' || empty($plan)) {
@@ -1445,3 +1747,10 @@ Http::setResource('executionsRetentionCount', function (Document $project, array
return (int) ($plan['executionsRetentionCount'] ?? 100);
}, ['project', 'plan']);
Http::setResource('embeddingAgent', function ($register) {
$adapter = new Ollama();
$adapter->setEndpoint(System::getEnv('_APP_EMBEDDING_ENDPOINT', 'http://ollama:11434/api/embed'));
$adapter->setTimeout(90000);
return new Agent($adapter);
}, ['register']);
+19
View File
@@ -104,6 +104,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -237,6 +238,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -265,6 +267,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -290,6 +293,7 @@ $dbService = $this->getParam('database');
- _APP_OPENSSL_KEY_V1
- _APP_EMAIL_SECURITY
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -328,6 +332,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -385,6 +390,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -419,6 +425,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -492,6 +499,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -522,6 +530,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -557,6 +566,7 @@ $dbService = $this->getParam('database');
- _APP_OPENSSL_KEY_V1
- _APP_SYSTEM_EMAIL_NAME
- _APP_SYSTEM_EMAIL_ADDRESS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -597,6 +607,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -656,6 +667,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -692,6 +704,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -722,6 +735,7 @@ $dbService = $this->getParam('database');
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -752,6 +766,7 @@ $dbService = $this->getParam('database');
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -781,6 +796,7 @@ $dbService = $this->getParam('database');
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -814,6 +830,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -840,6 +857,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -866,6 +884,7 @@ $dbService = $this->getParam('database');
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
+52
View File
@@ -220,6 +220,58 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authoriza
};
}, ['pools', 'cache', 'authorization']);
Server::setResource('getDatabasesDB', function (Cache $cache, Registry $register, Document $project, Authorization $authorization) {
return function (Document $database, ?Document $projectDocument = null) use ($cache, $register, $project, $authorization): Database {
$projectDocument ??= $project;
$databaseType = $database->getAttribute('database', '');
// Backwardscompatibility: older or seeded legacy databases may not have a DSN stored
// in the "database" attribute. In that case, fall back to the project's database DSN.
if ($databaseType === '') {
$databaseType = $projectDocument->getAttribute('database', '');
}
try {
$databaseDSN = new DSN($databaseType);
} catch (\InvalidArgumentException) {
$databaseDSN = new DSN('mysql://'.$databaseType);
}
try {
$dsn = new DSN($projectDocument->getAttribute('database'));
} catch (\InvalidArgumentException) {
// Temporary fallback until all projects use shared tables
$dsn = new DSN('mysql://' . $projectDocument->getAttribute('database'));
}
$pools = $register->get('pools');
$pool = $pools->get($databaseDSN->getHost());
$adapter = new DatabasePool($pool);
$database = new Database($adapter, $cache);
$database
->setDatabase(APP_DATABASE)
->setAuthorization($authorization);
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables, true)) {
$database
->setSharedTables(true)
->setTenant((int) $projectDocument->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $projectDocument->getSequence());
}
$database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
return $database;
};
}, ['cache', 'register', 'project', 'authorization']);
Server::setResource('abuseRetention', function () {
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day
});
+6 -4
View File
@@ -29,6 +29,8 @@
"Appwrite\\Tests\\": "tests/extensions"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=8.3.0",
"ext-curl": "*",
@@ -55,6 +57,7 @@
"utopia-php/config": "1.*",
"utopia-php/console": "0.1.*",
"utopia-php/database": "5.*",
"utopia-php/agents": "1.*",
"utopia-php/detector": "0.2.*",
"utopia-php/domains": "1.*",
"utopia-php/emails": "0.6.*",
@@ -66,7 +69,7 @@
"utopia-php/locale": "0.8.*",
"utopia-php/logger": "0.6.*",
"utopia-php/messaging": "0.20.*",
"utopia-php/migration": "1.6.*",
"utopia-php/migration": "dev-remove-dsn-callables as 1.6.2",
"utopia-php/platform": "0.7.*",
"utopia-php/pools": "1.*",
"utopia-php/span": "1.1.*",
@@ -81,11 +84,11 @@
"matomo/device-detector": "6.4.*",
"dragonmantank/cron-expression": "3.4.*",
"phpmailer/phpmailer": "6.9.*",
"chillerlan/php-qrcode": "4.4.*",
"chillerlan/php-qrcode": "4.3.*",
"adhocore/jwt": "1.1.*",
"spomky-labs/otphp": "^11.4.2",
"webonyx/graphql-php": "14.11.*",
"league/csv": "9.24.*",
"league/csv": "9.14.*",
"enshrined/svg-sanitize": "0.22.*"
},
"require-dev": {
@@ -103,7 +106,6 @@
},
"config": {
"platform": {
"php": "8.3"
},
"allow-plugins": {
"php-http/discovery": true,
Generated
+129 -69
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "dd9887a50fb434887461a99413007573",
"content-hash": "1f4033f1f09f0ddc0b040d3f1af0dfb0",
"packages": [
{
"name": "adhocore/jwt",
@@ -276,34 +276,31 @@
},
{
"name": "chillerlan/php-qrcode",
"version": "4.4.2",
"version": "4.3.4",
"source": {
"type": "git",
"url": "https://github.com/chillerlan/php-qrcode.git",
"reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4"
"reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4",
"reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4",
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d",
"reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d",
"shasum": ""
},
"require": {
"chillerlan/php-settings-container": "^2.1.6 || ^3.2.1",
"chillerlan/php-settings-container": "^2.1.4",
"ext-mbstring": "*",
"php": "^7.4 || ^8.0"
},
"require-dev": {
"phan/phan": "^5.4.5",
"phpmd/phpmd": "^2.15",
"phpunit/phpunit": "^9.6",
"setasign/fpdf": "^1.8.2",
"squizlabs/php_codesniffer": "^3.11"
"phan/phan": "^5.3",
"phpunit/phpunit": "^9.5",
"setasign/fpdf": "^1.8.2"
},
"suggest": {
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.",
"setasign/fpdf": "Required to use the QR FPDF output.",
"simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code"
"setasign/fpdf": "Required to use the QR FPDF output."
},
"type": "library",
"autoload": {
@@ -330,7 +327,7 @@
"homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors"
}
],
"description": "A QR code generator with a user friendly API. PHP 7.4+",
"description": "A QR code generator. PHP 7.4+",
"homepage": "https://github.com/chillerlan/php-qrcode",
"keywords": [
"phpqrcode",
@@ -341,39 +338,43 @@
],
"support": {
"issues": "https://github.com/chillerlan/php-qrcode/issues",
"source": "https://github.com/chillerlan/php-qrcode/tree/4.4.2"
"source": "https://github.com/chillerlan/php-qrcode/tree/4.3.4"
},
"funding": [
{
"url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4",
"type": "custom"
},
{
"url": "https://ko-fi.com/codemasher",
"type": "ko_fi"
}
],
"time": "2024-11-15T15:36:24+00:00"
"time": "2022-07-25T09:12:45+00:00"
},
{
"name": "chillerlan/php-settings-container",
"version": "3.2.1",
"version": "2.1.6",
"source": {
"type": "git",
"url": "https://github.com/chillerlan/php-settings-container.git",
"reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681"
"reference": "5553558bd381fce5108c6d0343c12e488cfec6bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
"reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/5553558bd381fce5108c6d0343c12e488cfec6bb",
"reference": "5553558bd381fce5108c6d0343c12e488cfec6bb",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^8.1"
"php": "^7.4 || ^8.0"
},
"require-dev": {
"phpmd/phpmd": "^2.15",
"phpstan/phpstan": "^1.11",
"phpstan/phpstan-deprecation-rules": "^1.2",
"phpunit/phpunit": "^10.5",
"phpunit/phpunit": "^9.6",
"squizlabs/php_codesniffer": "^3.10"
},
"type": "library",
@@ -393,9 +394,10 @@
"homepage": "https://github.com/codemasher"
}
],
"description": "A container class for immutable settings objects. Not a DI container.",
"description": "A container class for immutable settings objects. Not a DI container. PHP 7.4+",
"homepage": "https://github.com/chillerlan/php-settings-container",
"keywords": [
"PHP7",
"Settings",
"configuration",
"container",
@@ -415,7 +417,7 @@
"type": "ko_fi"
}
],
"time": "2024-07-16T11:13:48+00:00"
"time": "2024-07-17T01:04:28+00:00"
},
{
"name": "composer/semver",
@@ -790,42 +792,40 @@
},
{
"name": "league/csv",
"version": "9.24.1",
"version": "9.14.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/csv.git",
"reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8"
"reference": "34bf0df7340b60824b9449b5c526fcc3325070d5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/e0221a3f16aa2a823047d59fab5809d552e29bc8",
"reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/34bf0df7340b60824b9449b5c526fcc3325070d5",
"reference": "34bf0df7340b60824b9449b5c526fcc3325070d5",
"shasum": ""
},
"require": {
"ext-filter": "*",
"ext-json": "*",
"ext-mbstring": "*",
"php": "^8.1.2"
},
"require-dev": {
"doctrine/collections": "^2.1.4",
"ext-dom": "*",
"ext-xdebug": "*",
"friendsofphp/php-cs-fixer": "^3.75.0",
"phpbench/phpbench": "^1.4.1",
"phpstan/phpstan": "^1.12.27",
"phpstan/phpstan-deprecation-rules": "^1.2.1",
"phpstan/phpstan-phpunit": "^1.4.2",
"phpstan/phpstan-strict-rules": "^1.6.2",
"phpunit/phpunit": "^10.5.16 || ^11.5.22",
"symfony/var-dumper": "^6.4.8 || ^7.3.0"
"friendsofphp/php-cs-fixer": "^v3.22.0",
"phpbench/phpbench": "^1.2.15",
"phpstan/phpstan": "^1.10.50",
"phpstan/phpstan-deprecation-rules": "^1.1.4",
"phpstan/phpstan-phpunit": "^1.3.15",
"phpstan/phpstan-strict-rules": "^1.5.2",
"phpunit/phpunit": "^10.5.3",
"symfony/var-dumper": "^6.4.0"
},
"suggest": {
"ext-dom": "Required to use the XMLConverter and the HTMLConverter classes",
"ext-iconv": "Needed to ease transcoding CSV using iconv stream filters",
"ext-mbstring": "Needed to ease transcoding CSV using mb stream filters",
"ext-mysqli": "Requiered to use the package with the MySQLi extension",
"ext-pdo": "Required to use the package with the PDO extension",
"ext-pgsql": "Requiered to use the package with the PgSQL extension",
"ext-sqlite3": "Required to use the package with the SQLite3 extension"
"ext-iconv": "Needed to ease transcoding CSV using iconv stream filters"
},
"type": "library",
"extra": {
@@ -877,7 +877,7 @@
"type": "github"
}
],
"time": "2025-06-25T14:53:51+00:00"
"time": "2023-12-29T07:34:53+00:00"
},
{
"name": "matomo/device-detector",
@@ -3401,6 +3401,60 @@
},
"time": "2026-02-02T10:43:10+00:00"
},
{
"name": "utopia-php/agents",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/agents.git",
"reference": "77ec73c02f91a571aabee3f72ac5cd49a1d1f39c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/agents/zipball/77ec73c02f91a571aabee3f72ac5cd49a1d1f39c",
"reference": "77ec73c02f91a571aabee3f72ac5cd49a1d1f39c",
"shasum": ""
},
"require": {
"php": ">=8.3",
"utopia-php/fetch": "0.5.*"
},
"require-dev": {
"laravel/pint": "1.2.*",
"phpstan/phpstan": "1.9.x-dev",
"phpunit/phpunit": "^9.3",
"vimeo/psalm": "4.0.1"
},
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\Agents\\": "src/Agents"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Utopia PHP",
"email": "team@appwrite.io"
}
],
"description": "A simple PHP AI agents library",
"keywords": [
"agents",
"ai",
"automation",
"machine-learning",
"php"
],
"support": {
"issues": "https://github.com/utopia-php/agents/issues",
"source": "https://github.com/utopia-php/agents/tree/1.1.1"
},
"time": "2026-02-19T08:42:23+00:00"
},
{
"name": "utopia-php/analytics",
"version": "0.15.2",
@@ -4464,16 +4518,16 @@
},
{
"name": "utopia-php/migration",
"version": "1.6.1",
"version": "dev-remove-dsn-callables",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "c5c7544d02d2418536d41050794050132f247d62"
"reference": "682cdc36618a2be4fe376047a6250a3d0c4ea739"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/c5c7544d02d2418536d41050794050132f247d62",
"reference": "c5c7544d02d2418536d41050794050132f247d62",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/682cdc36618a2be4fe376047a6250a3d0c4ea739",
"reference": "682cdc36618a2be4fe376047a6250a3d0c4ea739",
"shasum": ""
},
"require": {
@@ -4513,9 +4567,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/1.6.1"
"source": "https://github.com/utopia-php/migration/tree/remove-dsn-callables"
},
"time": "2026-02-17T05:49:48+00:00"
"time": "2026-02-24T05:05:52+00:00"
},
{
"name": "utopia-php/mongo",
@@ -4953,16 +5007,16 @@
},
{
"name": "utopia-php/storage",
"version": "1.0.0",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/storage.git",
"reference": "f672e8865938e5d1d6dc3bd149ceba4e5582199e"
"reference": "f014be445f0baa635d0764e1673196f412511618"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/f672e8865938e5d1d6dc3bd149ceba4e5582199e",
"reference": "f672e8865938e5d1d6dc3bd149ceba4e5582199e",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/f014be445f0baa635d0764e1673196f412511618",
"reference": "f014be445f0baa635d0764e1673196f412511618",
"shasum": ""
},
"require": {
@@ -5000,9 +5054,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/storage/issues",
"source": "https://github.com/utopia-php/storage/tree/1.0.0"
"source": "https://github.com/utopia-php/storage/tree/1.0.1"
},
"time": "2026-02-17T04:37:10+00:00"
"time": "2026-02-23T05:59:32+00:00"
},
{
"name": "utopia-php/system",
@@ -5385,16 +5439,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "1.10.1",
"version": "1.10.2",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "fd08ddfefc7b07870b0fa8616c6d13714b2481c8"
"reference": "b31e6b4209ecad46d2fef509dc59f1945d0e83cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/fd08ddfefc7b07870b0fa8616c6d13714b2481c8",
"reference": "fd08ddfefc7b07870b0fa8616c6d13714b2481c8",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/b31e6b4209ecad46d2fef509dc59f1945d0e83cb",
"reference": "b31e6b4209ecad46d2fef509dc59f1945d0e83cb",
"shasum": ""
},
"require": {
@@ -5430,9 +5484,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/1.10.1"
"source": "https://github.com/appwrite/sdk-generator/tree/1.10.2"
},
"time": "2026-02-20T07:22:19+00:00"
"time": "2026-02-23T04:04:15+00:00"
},
{
"name": "doctrine/annotations",
@@ -8883,10 +8937,19 @@
"time": "2024-03-07T20:33:40+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"aliases": [
{
"package": "utopia-php/migration",
"version": "dev-remove-dsn-callables",
"alias": "1.6.2",
"alias_normalized": "1.6.2.0"
}
],
"minimum-stability": "dev",
"stability-flags": {
"utopia-php/migration": 20
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": ">=8.3.0",
@@ -8906,8 +8969,5 @@
"platform-dev": {
"ext-fileinfo": "*"
},
"platform-overrides": {
"php": "8.3"
},
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.9.0"
}
+128 -5
View File
@@ -103,6 +103,7 @@ services:
- ${_APP_DB_HOST:-mariadb}
- redis
- coredns
- ollama
# - clamav
entrypoint:
- php
@@ -144,12 +145,18 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_DB_ADAPTER
- _APP_DB_ADAPTER_VECTORDB
- _APP_DB_HOST_VECTORDB
- _APP_DB_PORT_VECTORDB
- _APP_DB_SCHEMA_VECTORDB
- _APP_DB_USER_VECTORDB
- _APP_DB_PASS_VECTORDB
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
@@ -286,6 +293,7 @@ services:
depends_on:
- ${_APP_DB_HOST:-mariadb}
- redis
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -296,12 +304,18 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_DB_ADAPTER
- _APP_DB_ADAPTER_VECTORDB
- _APP_DB_HOST_VECTORDB
- _APP_DB_PORT_VECTORDB
- _APP_DB_SCHEMA_VECTORDB
- _APP_DB_USER_VECTORDB
- _APP_DB_PASS_VECTORDB
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- _APP_LOGGING_CONFIG_REALTIME
@@ -321,6 +335,7 @@ services:
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -330,6 +345,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -354,12 +370,14 @@ services:
- ${_APP_DB_HOST:-mariadb}
- request-catcher-sms
- request-catcher-webhook
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_POOL_ADAPTER
- _APP_OPENSSL_KEY_V1
- _APP_EMAIL_SECURITY
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -384,6 +402,7 @@ services:
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
@@ -393,6 +412,7 @@ services:
- appwrite-certificates:/storage/certificates:rw
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -402,6 +422,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -449,9 +470,11 @@ services:
volumes:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -461,12 +484,18 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_DB_ADAPTER
- _APP_DB_ADAPTER_VECTORDB
- _APP_DB_HOST_VECTORDB
- _APP_DB_PORT_VECTORDB
- _APP_DB_SCHEMA_VECTORDB
- _APP_DB_USER_VECTORDB
- _APP_DB_PASS_VECTORDB
- _APP_LOGGING_CONFIG
- _APP_WORKERS_NUM
- _APP_QUEUE_NAME
@@ -488,6 +517,7 @@ services:
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -499,6 +529,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -619,6 +650,7 @@ services:
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
volumes:
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
@@ -642,6 +674,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -693,8 +726,10 @@ services:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
depends_on:
- ${_APP_DB_HOST:-mariadb}
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
- openruntimes-executor
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -706,6 +741,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -791,6 +827,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -839,8 +876,10 @@ services:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
- ./tests:/usr/src/code/tests
depends_on:
- ${_APP_DB_HOST:-mariadb}
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -857,6 +896,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -899,6 +939,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -968,11 +1009,13 @@ services:
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_POOL_ADAPTER
- _APP_OPENSSL_KEY_V1
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -1001,11 +1044,13 @@ services:
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_POOL_ADAPTER
- _APP_OPENSSL_KEY_V1
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -1034,11 +1079,13 @@ services:
depends_on:
- redis
- ${_APP_DB_HOST:-mariadb}
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_POOL_ADAPTER
- _APP_OPENSSL_KEY_V1
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -1067,6 +1114,7 @@ services:
depends_on:
- ${_APP_DB_HOST:-mariadb}
- redis
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -1076,6 +1124,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -1097,6 +1146,7 @@ services:
depends_on:
- ${_APP_DB_HOST:-mariadb}
- redis
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -1106,6 +1156,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -1126,6 +1177,7 @@ services:
depends_on:
- ${_APP_DB_HOST:-mariadb}
- redis
- ollama
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -1135,6 +1187,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_ADAPTER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@@ -1234,8 +1287,58 @@ services:
- MARIADB_AUTO_UPGRADE=1
command: "mysqld --innodb-flush-method=fsync"
mongodb:
image: mongo:8.0.10
container_name: appwrite-mongodb
<<: *x-logging
networks:
- appwrite
volumes:
- appwrite-mongodb:/data/db
- appwrite-mongodb-keyfile:/data/keyfile
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongo-entrypoint.sh:/mongo-entrypoint.sh:ro
ports:
- "27017:27017"
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
- MONGO_INITDB_DATABASE=${_APP_DB_SCHEMA}
- MONGO_INITDB_USERNAME=${_APP_DB_USER}
- MONGO_INITDB_PASSWORD=${_APP_DB_PASS}
entrypoint: ["/bin/bash", "/mongo-entrypoint.sh"]
healthcheck:
test: |
bash -c "
if mongosh -u root -p ${_APP_DB_ROOT_PASS} --authenticationDatabase admin --quiet --eval 'rs.status().ok' 2>/dev/null | grep -q 1; then
exit 0
else
mongosh -u root -p ${_APP_DB_ROOT_PASS} --authenticationDatabase admin --quiet --eval \"
rs.initiate({_id: 'rs0', members: [{_id: 0, host: 'appwrite-mongodb:27017'}]})
\" 2>/dev/null || exit 1
fi
"
interval: 10s
timeout: 10s
retries: 10
start_period: 30s
appwrite-mongo-express:
image: mongo-express
container_name: appwrite-mongo-express
networks:
- appwrite
ports:
- "8082:8081"
environment:
ME_CONFIG_MONGODB_URL: "mongodb://root:${_APP_DB_ROOT_PASS}@appwrite-mongodb:27017/?replicaSet=rs0&directConnection=true"
ME_CONFIG_BASICAUTH_USERNAME: ${_APP_DB_USER}
ME_CONFIG_BASICAUTH_PASSWORD: ${_APP_DB_PASS}
depends_on: []
postgresql:
image: postgres:18
build:
context: https://github.com/appwrite/docker-postgres.git#feat-dockerfile
container_name: appwrite-postgresql
<<: *x-logging
networks:
@@ -1250,6 +1353,23 @@ services:
- POSTGRES_PASSWORD=${_APP_DB_PASS}
command: "postgres"
ollama:
build:
context: https://github.com/appwrite/docker-ollama.git#feat-dockerfile
args:
MODELS: ${_APP_EMBEDDING_MODELS:-embeddinggemma}
# duration to keep model in memory
OLLAMA_KEEP_ALIVE: 24h
container_name: ollama
ports:
- "11434:11434"
restart: unless-stopped
# persistent for caching models across restarts and preloading
volumes:
- appwrite-models:/root/.ollama
networks:
- appwrite
redis:
image: redis:7.2.4-alpine
<<: *x-logging
@@ -1477,6 +1597,8 @@ configs:
volumes:
appwrite-mariadb:
appwrite-mongodb:
appwrite-mongodb-keyfile:
appwrite-postgresql:
appwrite-redis:
appwrite-cache:
@@ -1487,3 +1609,4 @@ volumes:
appwrite-sites:
appwrite-builds:
appwrite-config:
appwrite-models:
@@ -0,0 +1 @@
Create a new Collection. Before using this route, you should create a new database resource using either a [server integration](https://appwrite.io/docs/server/databases#documentsDBCreateCollection) API or directly from your database console.
@@ -0,0 +1 @@
Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#documentsDBCreateCollection) API or directly from your database console.
@@ -0,0 +1 @@
Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#documentsDBCreateCollection) API or directly from your database console.
@@ -0,0 +1,2 @@
Creates an index on the attributes listed. Your index should include all the attributes you will query in a single request.
Attributes can be `key`, `fulltext`, and `unique`.
+1
View File
@@ -0,0 +1 @@
Create a new Database.
@@ -0,0 +1 @@
Decrement a specific column of a row by a given value.
@@ -0,0 +1 @@
Delete a collection by its unique ID. Only users with write permissions have access to delete this resource.
@@ -0,0 +1 @@
Delete a document by its unique ID.
@@ -0,0 +1 @@
Bulk delete documents using queries, if no queries are passed then all documents are deleted.
@@ -0,0 +1 @@
Delete an index.
+1
View File
@@ -0,0 +1 @@
Delete a database by its unique ID. Only API keys with with databases.write scope can delete a database.
@@ -0,0 +1 @@
Get the collection activity logs list by its unique ID.
@@ -0,0 +1 @@
Get usage metrics and statistics for a collection. Returning the total number of documents. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.
@@ -0,0 +1 @@
Get a collection by its unique ID. This endpoint response returns a JSON object with the collection metadata.
@@ -0,0 +1 @@
Get usage metrics and statistics for a database. You can view the total number of collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.
@@ -0,0 +1 @@
Get the document activity logs list by its unique ID.
@@ -0,0 +1 @@
Get a document by its unique ID. This endpoint response returns a JSON object with the document data.
+1
View File
@@ -0,0 +1 @@
Get index by ID.
+1
View File
@@ -0,0 +1 @@
Get the database activity logs list by its unique ID.
+1
View File
@@ -0,0 +1 @@
Get a database by its unique ID. This endpoint response returns a JSON object with the database metadata.
@@ -0,0 +1 @@
Increment a specific column of a row by a given value.
@@ -0,0 +1 @@
List attributes in the collection.
@@ -0,0 +1 @@
Get a list of all collections that belong to the provided databaseId. You can use the search parameter to filter your results.
@@ -0,0 +1 @@
Get a list of all the user's documents in a given collection. You can use the query params to filter your results.
@@ -0,0 +1 @@
List indexes in the collection.
@@ -0,0 +1 @@
List usage metrics and statistics for all databases in the project. You can view the total number of databases, collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.
+1
View File
@@ -0,0 +1 @@
Get a list of all databases from the current Appwrite project. You can use the search parameter to filter your results.
@@ -0,0 +1 @@
Update a collection by its unique ID.
@@ -0,0 +1 @@
Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated.
@@ -0,0 +1 @@
Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.
+1
View File
@@ -0,0 +1 @@
Update a database by its unique ID.
@@ -0,0 +1 @@
Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#documentsDBCreateCollection) API or directly from your database console.
@@ -0,0 +1 @@
Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#documentsDBCreateCollection) API or directly from your database console.
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
set -e
# Fix keyfile permissions if mounted from volume
KEYFILE_PATH="/data/keyfile/mongo-keyfile"
if [ ! -f "$KEYFILE_PATH" ]; then
echo "Generating random MongoDB keyfile..."
mkdir -p /data/keyfile
openssl rand -base64 756 > "$KEYFILE_PATH"
fi
chmod 400 "$KEYFILE_PATH"
chown mongodb:mongodb "$KEYFILE_PATH" 2>/dev/null || chown 999:999 "$KEYFILE_PATH"
# Use MongoDB's standard entrypoint with our command
exec docker-entrypoint.sh mongod --replSet rs0 --bind_ip_all --auth --keyFile "$KEYFILE_PATH"
+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
# MongoDB Replica Set Initialization Script
# Runs after MongoDB starts as part of docker-entrypoint-initdb.d
# Check if replica set is already initialized
RS_STATUS=$(mongosh --username root --password "${MONGO_INITDB_ROOT_PASSWORD}" --authenticationDatabase admin --eval "try { rs.status().ok } catch(e) { 0 }" --quiet 2>/dev/null || echo "0")
if [ "$RS_STATUS" = "1" ]; then
echo "Replica set already initialized"
exit 0
fi
# Initialize replica set
echo "Initializing replica set 'rs0'..."
# For single-node replica set, we can use localhost since clients connect directly
# The MongoDB driver will handle connection to this node
mongosh --username root --password "${MONGO_INITDB_ROOT_PASSWORD}" --authenticationDatabase admin --eval "rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: '127.0.0.1:27017' }] })"
# Wait for replica set to elect a primary and become stable
echo "Waiting for PRIMARY to be ready..."
MAX_WAIT=15
COUNTER=0
while [ $COUNTER -lt $MAX_WAIT ]; do
# Use try/catch to handle cases where rs.status() fails during initialization
PRIMARY_STATE=$(mongosh --username root --password "${MONGO_INITDB_ROOT_PASSWORD}" --authenticationDatabase admin --eval "try { rs.status().members[0].stateStr } catch(e) { 'WAITING' }" --quiet 2>/dev/null || echo "WAITING")
if [ "$PRIMARY_STATE" = "PRIMARY" ]; then
echo "PRIMARY is ready!"
break
fi
# Give it more time between checks
sleep 2
COUNTER=$((COUNTER+1))
# Only show status every few attempts to reduce log noise
if [ $((COUNTER % 3)) -eq 0 ]; then
echo "Still waiting for PRIMARY (attempt $COUNTER/$MAX_WAIT, current state: $PRIMARY_STATE)..."
fi
done
# Don't fail the init even if PRIMARY isn't ready immediately
# MongoDB will continue to elect a primary in the background
# Clients will wait for it to be ready via their connection retry logic
if [ $COUNTER -eq $MAX_WAIT ]; then
echo "NOTE: PRIMARY not confirmed within $((MAX_WAIT * 2)) seconds, but replica set is configured"
echo "MongoDB will continue initializing the replica set in the background"
fi
echo "Replica set initialization complete!"
+18
View File
@@ -0,0 +1,18 @@
// mongo-init.js
// Switch to the admin database
const adminDb = db.getSiblingDB('admin');
// Get username and password from environment variables
const username = process.env.MONGO_INITDB_USERNAME;
const password = process.env.MONGO_INITDB_PASSWORD;
const database = process.env.MONGO_INITDB_DATABASE;
// Create the user
adminDb.createUser({
user: username,
pwd: password,
roles: [
{ role: 'readWrite', db: database }
]
});
+16
View File
@@ -0,0 +1,16 @@
i4Ge9ZbzXgpP4ZLLX/9/pkfhZYlEpSCfhl3Gqr0iwx1UAf4z3egza5J5tjj+S1zl
flopL/FlHaBLQAbY9E6kQyaIFQHJ4Wd6bOkL5hajIizvBBLtKxgpKMPQdvnx6mwe
aeK866TFRx4rWWQs69Gz3nZb822YRmdC4m2H+1rx635/ICWMWv26EdmYayafe010
zKJW/Ty75MpAk9yxc3PFEooDZtmb9PQKkkA4c+P7hfg1HBnrkcqfOejmlwvr/tWE
P8JIQTtcruo8A/5BFq0x0BToLJzY/eOiGcNe1Qf8CO4/8ZKWnvk00FvxXuU1KQ1G
uDlhaCakwitUGEjkKSeIH7V1Qk96JlY8kR5qBhavmROEd/o3VceLfdbbZzd+bitH
PRIocDb06SuWWvJGnwLRoyQmpeXu8AEd5YD+yimhGMQqzCfRFhxlT9rIJbWc8Z+Y
M8uDgd3bHaVfQCQDxbOgo9xB0zqOx77HUBXqeU4xqMeiOkKJxDrt6Cz0osQyybZO
NL9lsJ2y+2S6RyUWNMWJTrVGhgKnse/Z0dgrHpShBMI02G/Q8MKTDXyJmeX1PToe
CCdDmVMKhQRkrvZqeNTvOiNGb/hUDqU/Px/lCmhZYzIKsOK7nhaH6U5FiIAzxeNi
g03gwyrwRfmJWRyTcTSuQKIprBoobl2xJG2CYjdc2UhtY2I3bSlOue1DOKYnOFjA
x58DNwUQdegadSsyd2IPlWpUGIY1GJjTV+J9vEf79TQtnzYSFH5lmg3J08Cq64wg
UAedRHUEnRHFlVfg4ZdkGTGL/2Q7l2Dk0jJQCFFq+tEFGncLgGlAJaWXkczaFaZy
r9h12ulCUq6trZ1RGS1DlDxwQU2J6bSz0ZFwux/3W0YyIQyq4rWcoDjEG98DSE5n
P3Qht2DsBjFkh55nfC0EgwXwnWzBTJiJo1GYf5RdEIVCmmWxmAfTfPYaKWOVcgGG
6QGX5TCPyI6+SZUT/qOfGxnIE/1R3N1wD+J1rORXwWucLOiR
+23
View File
@@ -0,0 +1,23 @@
FROM ollama/ollama:0.12.7
# Preload specific models
ARG MODELS
# needed to set in the environment
ARG OLLAMA_KEEP_ALIVE
ENV OLLAMA_KEEP_ALIVE=${OLLAMA_KEEP_ALIVE:-24h}
# Pre-pull models at build time for Docker layer caching
RUN ollama serve & \
sleep 5 && \
for m in $MODELS; do \
echo "Pulling model $m..."; \
ollama pull $m || exit 1; \
done && \
pkill ollama
# Expose Ollama default port
EXPOSE 11434
# On container start, quickly ensure models exist (no re-download unless missing)
ENTRYPOINT ["/bin/bash", "-c", "(sleep 2; for m in $MODELS; do ollama list | grep -q $m || ollama pull $m; done) & exec ollama $0"]
CMD ["serve"]
+8
View File
@@ -0,0 +1,8 @@
FROM postgres:16
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
postgresql-16-postgis-3 \
postgresql-16-postgis-3-scripts \
postgresql-16-pgvector \
&& rm -rf /var/lib/apt/lists/*
+1
View File
@@ -56,6 +56,7 @@ class Mock extends OAuth2
*/
protected function getTokens(string $code): array
{
if (empty($this->tokens)) {
$this->tokens = \json_decode($this->request(
'GET',
+27 -14
View File
@@ -21,17 +21,23 @@ class TransactionState
{
private Database $dbForProject;
private Authorization $authorization;
/** @var Authorization $authorization */
public function __construct(Database $dbForProject, Authorization $authorization)
/** @var Authorization $authorization */ /**
* @var callable(Document $database): Database
*/
private mixed $getDatabasesDB;
public function __construct(Database $dbForProject, Authorization $authorization, callable $getDatabasesDB)
{
$this->dbForProject = $dbForProject;
$this->authorization = $authorization;
$this->getDatabasesDB = $getDatabasesDB;
}
/**
* Get a document with transaction-aware logic
*
* @param Document $database Target database document
* @param string $collectionId Collection ID
* @param string $documentId Document ID
* @param string|null $transactionId Optional transaction ID
@@ -42,13 +48,15 @@ class TransactionState
* @throws Timeout
*/
public function getDocument(
Document $database,
string $collectionId,
string $documentId,
?string $transactionId = null,
array $queries = []
): Document {
$dbForDatabases = ($this->getDatabasesDB)($database);
if ($transactionId === null) {
return $this->dbForProject->getDocument($collectionId, $documentId, $queries);
return $dbForDatabases->getDocument($collectionId, $documentId, $queries);
}
$state = $this->getTransactionState($transactionId);
@@ -66,7 +74,7 @@ class TransactionState
if ($docState['action'] === 'update' || $docState['action'] === 'upsert') {
// Merge with committed version
$committedDoc = $this->dbForProject->getDocument($collectionId, $documentId, $queries);
$committedDoc = $dbForDatabases->getDocument($collectionId, $documentId, $queries);
if (!$committedDoc->isEmpty()) {
foreach ($docState['document']->getAttributes() as $key => $value) {
if ($key !== '$id') {
@@ -80,13 +88,13 @@ class TransactionState
}
}
}
return $this->dbForProject->getDocument($collectionId, $documentId, $queries);
return $dbForDatabases->getDocument($collectionId, $documentId, $queries);
}
/**
* List documents with transaction-aware logic
*
* @param Document $database Target database document
* @param string $collectionId Collection ID
* @param string|null $transactionId Optional transaction ID
* @param array $queries Optional query filters
@@ -96,17 +104,19 @@ class TransactionState
* @throws Timeout
*/
public function listDocuments(
Document $database,
string $collectionId,
?string $transactionId = null,
array $queries = []
): array {
$dbForDatabases = ($this->getDatabasesDB)($database);
// If no transaction, use normal database retrieval
if ($transactionId === null) {
return $this->dbForProject->find($collectionId, $queries);
return $dbForDatabases->find($collectionId, $queries);
}
$state = $this->getTransactionState($transactionId);
$committedDocs = $this->dbForProject->find($collectionId, $queries);
$committedDocs = $dbForDatabases->find($collectionId, $queries);
$documentMap = [];
// Build map of committed documents
@@ -147,6 +157,7 @@ class TransactionState
/**
* Count documents with transaction-aware logic
*
* @param Document $database Target database document
* @param string $collectionId Collection ID
* @param string|null $transactionId Optional transaction ID
* @param array $queries Optional query filters
@@ -156,23 +167,23 @@ class TransactionState
* @throws Timeout
*/
public function countDocuments(
Document $database,
string $collectionId,
?string $transactionId = null,
array $queries = []
): int {
$dbForDatabases = ($this->getDatabasesDB)($database);
if ($transactionId === null) {
return $this->dbForProject->count($collectionId, $queries, APP_LIMIT_COUNT);
return $dbForDatabases->count($collectionId, $queries, APP_LIMIT_COUNT);
}
$state = $this->getTransactionState($transactionId);
$baseCount = $this->dbForProject->count($collectionId, $queries, APP_LIMIT_COUNT);
$baseCount = $dbForDatabases->count($collectionId, $queries, APP_LIMIT_COUNT);
if (!isset($state[$collectionId])) {
return $baseCount;
}
$committedDocs = $this->dbForProject->find($collectionId, $queries);
$committedDocs = $dbForDatabases->find($collectionId, $queries);
$committedDocIds = [];
foreach ($committedDocs as $doc) {
$committedDocIds[$doc->getId()] = true;
@@ -214,17 +225,19 @@ class TransactionState
/**
* Check if a document exists with transaction-aware logic
*
* @param Document $database Target database document
* @param string $collectionId Collection ID
* @param string $documentId Document ID
* @param string|null $transactionId Optional transaction ID
* @return bool True if document exists
*/
public function documentExists(
Document $database,
string $collectionId,
string $documentId,
?string $transactionId = null
): bool {
$doc = $this->getDocument($collectionId, $documentId, $transactionId);
$doc = $this->getDocument($database, $collectionId, $documentId, $transactionId);
return !$doc->isEmpty();
}
+71 -9
View File
@@ -518,10 +518,11 @@ class Event
*
* @param string $pattern
* @param array $params
* @param ?Document $database
* @return array
* @throws \InvalidArgumentException
*/
public static function generateEvents(string $pattern, array $params = []): array
public static function generateEvents(string $pattern, array $params = [], ?Document $database = null): array
{
// $params = \array_filter($params, fn($param) => !\is_array($param));
$paramKeys = \array_keys($params);
@@ -530,6 +531,12 @@ class Event
$patterns = [];
$parsed = self::parseEventPattern($pattern);
// to switch the resource types from databases to the required prefix
// eg; all databases events get fired with databases. prefix which mainly depicts legacy type
// so a projection from databases to the actual prefix(documentsdb, vectordb,etc)
if ((str_contains($pattern, 'databases.') && $database && $database->getAttribute('type') !== 'legacy')) {
$parsed = self::getDatabaseTypeEvents($database, $parsed);
}
$type = $parsed['type'];
$resource = $parsed['resource'];
$subType = $parsed['subType'];
@@ -630,8 +637,8 @@ class Event
$eventValues = \array_values($events);
/**
* Return a combined list of table, collection events.
*/
* Return a combined list of table, collection events and if tablesdb present then include all for backward compatibility
*/
return Event::mirrorCollectionEvents($pattern, $eventValues[0], $eventValues);
}
@@ -671,16 +678,40 @@ class Event
'attributes' => 'columns',
];
$databasesEventMap = [
'tablesdb' => 'databases',
'tables' => 'collections',
'rows' => 'documents',
'columns' => 'attributes'
];
if (
str_contains($pattern, 'databases.') &&
str_contains($firstEvent, 'collections')
(
str_contains($pattern, 'databases.') &&
str_contains($firstEvent, 'collections')
) ||
(
str_contains($firstEvent, 'tablesdb.')
)
) {
$pairedEvents = [];
foreach ($events as $event) {
$pairedEvents[] = $event;
if (str_contains($event, 'collections')) {
// tablesdb needs databases event with tables and collections
if (str_contains($event, 'tablesdb')) {
$databasesSideEvent = str_replace(
array_keys($databasesEventMap),
array_values($databasesEventMap),
$event
);
$pairedEvents[] = $databasesSideEvent;
$tableSideEvent = str_replace(
array_keys($tableEventMap),
array_values($tableEventMap),
$databasesSideEvent
);
$pairedEvents[] = $tableSideEvent;
} elseif (str_contains($event, 'collections')) {
$tableSideEvent = str_replace(
array_keys($tableEventMap),
array_values($tableEventMap),
@@ -692,8 +723,39 @@ class Event
$events = $pairedEvents;
}
// mirrored events can have duplicates in case of smaller events
return array_unique($events);
}
return $events;
/**
* Maps event terminology based on database type
*/
private static function getDatabaseTypeEvents(Document $database, array $event): array
{
$eventMap = [];
switch ($database->getAttribute('type')) {
case 'tablesdb':
$eventMap = [
'databases' => 'tablesdb',
'documents' => 'rows',
'collections' => 'tables',
'attributes' => 'columns',
];
break;
case 'documentsdb':
case 'vectordb':
// sending the type itself(eg: documentsdb, vectordb)
$eventMap = [
'databases' => $database->getAttribute('type')
];
break;
}
foreach ($event as $eventKey => $eventValue) {
if (isset($eventMap[$eventValue])) {
$event[$eventKey] = $eventMap[$eventValue];
}
}
return $event;
}
/**
+1 -1
View File
@@ -72,7 +72,7 @@ class Realtime extends Event
return false;
}
$allEvents = Event::generateEvents($this->getEvent(), $this->getParams());
$allEvents = Event::generateEvents($this->getEvent(), $this->getParams(), $this->getContext('database'));
$payload = new Document($this->getPayload());
+1
View File
@@ -84,6 +84,7 @@ class StatsUsage extends Event
}
return true;
}),
'context' => $this->context,
];
}
+80 -6
View File
@@ -491,6 +491,9 @@ class Realtime extends MessagingAdapter
$roles = [Role::team(ID::custom($parts[1]))->toString()];
break;
case 'databases':
case 'tablesdb':
case 'documentsdb':
case 'vectordb':
$resource = $parts[4] ?? '';
if (in_array($resource, ['columns', 'attributes', 'indexes'])) {
$channels[] = 'console';
@@ -508,14 +511,25 @@ class Realtime extends MessagingAdapter
$tableId = $payload->getAttribute('$tableId', '');
$collectionId = $payload->getAttribute('$collectionId', '');
$resourceId = $tableId ?: $collectionId;
$channels = [];
// backward compat(tablesdb will have databases channels + tablesdb prefixed channels)
if ($parts[0] === 'databases' || $parts[0] === 'tablesdb') {
$prefix = 'databases';
$channels[] = 'rows';
$channels[] = 'databases.' . $database->getId() . '.tables.' . $resourceId . '.rows';
$channels[] = 'databases.' . $database->getId() . '.tables.' . $resourceId . '.rows.' . $payload->getId();
$channels = self::getDatabaseChannels('legacy', $database->getId(), $resourceId, $payload->getId(), $prefix);
$channels[] = 'documents';
$channels[] = 'databases.' . $database->getId() . '.collections.' . $resourceId . '.documents';
$channels[] = 'databases.' . $database->getId() . '.collections.' . $resourceId . '.documents.' . $payload->getId();
$channels = array_unique([
...$channels,
...self::getDatabaseChannels('tablesdb', $database->getId(), $resourceId, $payload->getId(), $prefix)
]);
}
// prefixed channels -> tablesdb, documentsdb,etc
if ($parts[0] !== 'databases') {
$channels = array_unique([
...$channels,
...self::getDatabaseChannels($parts[0], $database->getId(), $resourceId, $payload->getId()),
]);
}
$roles = $collection->getAttribute('documentSecurity', false)
? \array_merge($collection->getRead(), $payload->getRead())
@@ -572,4 +586,64 @@ class Realtime extends MessagingAdapter
'projectId' => $projectId
];
}
/**
* Generate realtime channels for database events
*
* @param string $type The database API type
* @param string $databaseId The database ID
* @param string $resourceId The collection/table ID
* @param string $payloadId The document/row ID
* @param string $prefixOverride Override the channel prefix when different API types share the same terminology but need different prefixes
* (e.g., 'databases' and 'documentsdb' use same terminology but need different prefixes)
* @return array Array of channel names
*/
private static function getDatabaseChannels(
string $type = 'databases',
string $databaseId = '',
string $resourceId = '',
string $payloadId = '',
string $prefixOverride = '',
): array {
$basePrefix = $prefixOverride ?: $type;
if (!$databaseId || !$resourceId || !$payloadId) {
return [];
}
$channels = [];
switch ($type) {
case 'legacy':
if (empty($prefixOverride)) {
$basePrefix = 'databases';
}
$channels[] = 'documents';
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents";
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents.{$payloadId}";
break;
case 'tablesdb':
$channels[] = 'rows';
$channels[] = "{$basePrefix}.{$databaseId}.tables.{$resourceId}.rows";
$channels[] = "{$basePrefix}.{$databaseId}.tables.{$resourceId}.rows.{$payloadId}";
break;
case 'documentsdb':
case 'vectordb':
$channels[] = 'documents';
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents";
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents.{$payloadId}";
break;
default:
$basePrefix = 'databases';
$channels[] = 'documents';
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents";
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents.{$payloadId}";
break;
}
return $channels;
}
}
@@ -22,3 +22,10 @@ const INDEX = 'index';
const DOCUMENTS = 'document';
const ATTRIBUTES = 'attribute';
const COLLECTIONS = 'collection';
const TABLESDB = 'tablesdb';
const DOCUMENTSDB = 'documentsdb';
const VECTORDB = 'vectordb';
const MIN_VECTOR_DIMENSION = 1;
const MAX_VECTOR_DIMENSION = 16000;
@@ -10,7 +10,7 @@ use Utopia\Database\Operator;
class Action extends AppwriteAction
{
private string $context = 'legacy';
private string $context = DATABASE_TYPE_LEGACY;
public function getDatabaseType(): string
{
@@ -20,7 +20,13 @@ class Action extends AppwriteAction
public function setHttpPath(string $path): AppwriteAction
{
if (\str_contains($path, '/tablesdb')) {
$this->context = 'tablesdb';
$this->context = DATABASE_TYPE_TABLESDB;
}
if (\str_contains($path, '/documentsdb')) {
$this->context = DATABASE_TYPE_DOCUMENTSDB;
}
if (\str_contains($path, '/vectordb')) {
$this->context = DATABASE_TYPE_VECTORDB;
}
return parent::setHttpPath($path);
}
@@ -15,6 +15,8 @@ abstract class Action extends UtopiaAction
*/
private ?string $context = COLLECTIONS;
private ?string $databaseType = TABLESDB;
/**
* Get the response model used in the SDK and HTTP responses.
*/
@@ -24,6 +26,9 @@ abstract class Action extends UtopiaAction
{
if (\str_contains($path, '/tablesdb')) {
$this->context = TABLES;
$this->databaseType = TABLESDB;
} elseif (\str_contains($path, '/vectordb')) {
$this->databaseType = VECTORDB;
}
return parent::setHttpPath($path);
}
@@ -36,6 +41,14 @@ abstract class Action extends UtopiaAction
return $this->context;
}
/**
* Get the current API database type.
*/
protected function getDatabaseType(): string
{
return $this->databaseType;
}
/**
* Get the key used in event parameters (e.g., 'collectionId' or 'tableId').
*/
@@ -60,9 +60,9 @@ class Create extends Action
replaceWith: 'tablesDB.createBooleanColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Boolean()), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
@@ -60,12 +60,12 @@ class Update extends Action
replaceWith: 'tablesDB.updateBooleanColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Boolean()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->param('newKey', null, new Nullable(new Key()), 'New attribute key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New attribute key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -61,9 +61,9 @@ class Create extends Action
replaceWith: 'tablesDB.createDatetimeColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, fn (Database $dbForProject) => new Nullable(new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime())), 'Default value for the attribute in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.', true, ['dbForProject'])
->param('array', false, new Boolean(), 'Is attribute an array?', true)
@@ -61,12 +61,12 @@ class Update extends Action
replaceWith: 'tablesDB.updateDatetimeColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, fn (Database $dbForProject) => new Nullable(new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime())), 'Default value for attribute when not provided. Cannot be set when attribute is required.', injections: ['dbForProject'])
->param('newKey', null, new Nullable(new Key()), 'New attribute key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New attribute key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -60,9 +60,9 @@ class Delete extends Action
replaceWith: 'tablesDB.deleteColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
@@ -61,9 +61,9 @@ class Create extends Action
replaceWith: 'tablesDB.createEmailColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Email()), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
@@ -61,12 +61,12 @@ class Update extends Action
replaceWith: 'tablesDB.updateEmailColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Email()), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New Attribute Key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -63,9 +63,9 @@ class Create extends Action
replaceWith: 'tablesDB.createEnumColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('elements', [], new ArrayList(new Text(Database::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of enum values.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
@@ -62,13 +62,13 @@ class Update extends Action
replaceWith: 'tablesDB.updateEnumColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('elements', null, new ArrayList(new Text(Database::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Updated list of enum values.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.')
->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New Attribute Key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -63,9 +63,9 @@ class Create extends Action
replaceWith: 'tablesDB.createFloatColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new Nullable(new FloatValidator()), 'Minimum value.', true)
->param('max', null, new Nullable(new FloatValidator()), 'Maximum value.', true)
@@ -61,14 +61,14 @@ class Update extends Action
replaceWith: 'tablesDB.updateFloatColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new Nullable(new FloatValidator()), 'Minimum value.', true)
->param('max', null, new Nullable(new FloatValidator()), 'Maximum value.', true)
->param('default', null, new Nullable(new FloatValidator()), 'Default value. Cannot be set when required.')
->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New Attribute Key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -63,9 +63,9 @@ class Get extends Action
replaceWith: 'tablesDB.getColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('authorization')
@@ -61,9 +61,9 @@ class Create extends Action
replaceWith: 'tablesDB.createIpColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new IP()), 'Default value. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
@@ -61,12 +61,12 @@ class Update extends Action
replaceWith: 'tablesDB.updateIpColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new IP()), 'Default value. Cannot be set when attribute is required.')
->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New Attribute Key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -63,9 +63,9 @@ class Create extends Action
replaceWith: 'tablesDB.createIntegerColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true)
->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true)
@@ -61,14 +61,14 @@ class Update extends Action
replaceWith: 'tablesDB.updateIntegerColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true)
->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true)
->param('default', null, new Nullable(new Integer(false, 64)), 'Default value. Cannot be set when attribute is required.')
->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New Attribute Key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -61,9 +61,9 @@ class Create extends Action
replaceWith: 'tablesDB.createLineColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_LINESTRING)), 'Default value for attribute when not provided, two-dimensional array of coordinate pairs, [[longitude, latitude], [longitude, latitude], …], listing the vertices of the line in order. Cannot be set when attribute is required.', true)
->inject('response')
@@ -61,12 +61,12 @@ class Update extends Action
replaceWith: 'tablesDB.updateLineColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_LINESTRING)), 'Default value for attribute when not provided, two-dimensional array of coordinate pairs, [[longitude, latitude], [longitude, latitude], …], listing the vertices of the line in order. Cannot be set when attribute is required.', true)
->param('newKey', null, new Nullable(new Key()), 'New attribute key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New attribute key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -61,9 +61,9 @@ class Create extends Action
replaceWith: 'tablesDB.createPointColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for attribute when not provided, array of two numbers [longitude, latitude], representing a single coordinate. Cannot be set when attribute is required.', true)
->inject('response')
@@ -61,12 +61,12 @@ class Update extends Action
replaceWith: 'tablesDB.updatePointColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POINT)), 'Default value for attribute when not provided, array of two numbers [longitude, latitude], representing a single coordinate. Cannot be set when attribute is required.', true)
->param('newKey', null, new Nullable(new Key()), 'New attribute key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New attribute key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -61,9 +61,9 @@ class Create extends Action
replaceWith: 'tablesDB.createPolygonColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POLYGON)), 'Default value for attribute when not provided, three-dimensional array where the outer array holds one or more linear rings, [[[longitude, latitude], …], …], the first ring is the exterior boundary, any additional rings are interior holes, and each ring must start and end with the same coordinate pair. Cannot be set when attribute is required.', true)
->inject('response')
@@ -61,12 +61,12 @@ class Update extends Action
replaceWith: 'tablesDB.updatePolygonColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Spatial(Database::VAR_POLYGON)), 'Default value for attribute when not provided, three-dimensional array where the outer array holds one or more linear rings, [[[longitude, latitude], …], …], the first ring is the exterior boundary, any additional rings are interior holes, and each ring must start and end with the same coordinate pair. Cannot be set when attribute is required.', true)
->param('newKey', null, new Nullable(new Key()), 'New attribute key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New attribute key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -62,9 +62,9 @@ class Create extends Action
replaceWith: 'tablesDB.createRelationshipColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('relatedCollectionId', '', new UID(), 'Related Collection ID.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('relatedCollectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Related Collection ID.', false, ['dbForProject'])
->param('type', '', new WhiteList([
Database::RELATION_ONE_TO_ONE,
Database::RELATION_MANY_TO_ONE,
@@ -72,8 +72,8 @@ class Create extends Action
Database::RELATION_ONE_TO_MANY
], true), 'Relation type')
->param('twoWay', false, new Boolean(), 'Is Two Way?', true)
->param('key', null, new Nullable(new Key()), 'Attribute Key.', true)
->param('twoWayKey', null, new Nullable(new Key()), 'Two Way Attribute Key.', true)
->param('key', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'Attribute Key.', true, ['dbForProject'])
->param('twoWayKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'Two Way Attribute Key.', true, ['dbForProject'])
->param('onDelete', Database::RELATION_MUTATE_RESTRICT, new WhiteList([
Database::RELATION_MUTATE_CASCADE,
Database::RELATION_MUTATE_RESTRICT,
@@ -34,7 +34,8 @@ class Update extends Action
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH)
->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/relationship')
->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/relationship/:key')
->httpAlias('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/relationship')
->desc('Update relationship attribute')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
@@ -60,15 +61,15 @@ class Update extends Action
replaceWith: 'tablesDB.updateRelationshipColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('onDelete', null, new Nullable(new WhiteList([
Database::RELATION_MUTATE_CASCADE,
Database::RELATION_MUTATE_RESTRICT,
Database::RELATION_MUTATE_SET_NULL
], true)), 'Constraints option', true)
->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true)
->param('newKey', null, fn (Database $dbForProject) => new Nullable(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength())), 'New Attribute Key.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
@@ -65,9 +65,9 @@ class Create extends Action
replaceWith: 'tablesDB.createStringColumn',
),
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).', false, ['dbForProject'])
->param('key', '', fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Attribute Key.', false, ['dbForProject'])
->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Validator::TYPE_INTEGER), 'Attribute size for text attributes, in number of characters.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)

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