Merge remote-tracking branch 'origin/1.8.x' into chore-update

# Conflicts:
#	app/init/constants.php
#	composer.json
#	composer.lock
#	src/Appwrite/Migration/Migration.php
This commit is contained in:
Jake Barnby
2026-03-20 14:04:46 +13:00
268 changed files with 1887 additions and 23337 deletions
+14 -27
View File
@@ -21,23 +21,17 @@ class TransactionState
{
private Database $dbForProject;
private Authorization $authorization;
/**
* @var callable(Document $database): Database
*/
private mixed $getDatabasesDB;
public function __construct(Database $dbForProject, Authorization $authorization, callable $getDatabasesDB)
/** @var Authorization $authorization */
public function __construct(Database $dbForProject, Authorization $authorization)
{
$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
@@ -48,15 +42,13 @@ 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 $dbForDatabases->getDocument($collectionId, $documentId, $queries);
return $this->dbForProject->getDocument($collectionId, $documentId, $queries);
}
$state = $this->getTransactionState($transactionId);
@@ -74,7 +66,7 @@ class TransactionState
if ($docState['action'] === 'update' || $docState['action'] === 'upsert') {
// Merge with committed version
$committedDoc = $dbForDatabases->getDocument($collectionId, $documentId, $queries);
$committedDoc = $this->dbForProject->getDocument($collectionId, $documentId, $queries);
if (!$committedDoc->isEmpty()) {
foreach ($docState['document']->getAttributes() as $key => $value) {
if ($key !== '$id') {
@@ -88,13 +80,13 @@ class TransactionState
}
}
}
return $dbForDatabases->getDocument($collectionId, $documentId, $queries);
return $this->dbForProject->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
@@ -104,19 +96,17 @@ 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 $dbForDatabases->find($collectionId, $queries);
return $this->dbForProject->find($collectionId, $queries);
}
$state = $this->getTransactionState($transactionId);
$committedDocs = $dbForDatabases->find($collectionId, $queries);
$committedDocs = $this->dbForProject->find($collectionId, $queries);
$documentMap = [];
// Build map of committed documents
@@ -157,7 +147,6 @@ 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
@@ -167,23 +156,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 $dbForDatabases->count($collectionId, $queries, APP_LIMIT_COUNT);
return $this->dbForProject->count($collectionId, $queries, APP_LIMIT_COUNT);
}
$state = $this->getTransactionState($transactionId);
$baseCount = $dbForDatabases->count($collectionId, $queries, APP_LIMIT_COUNT);
$baseCount = $this->dbForProject->count($collectionId, $queries, APP_LIMIT_COUNT);
if (!isset($state[$collectionId])) {
return $baseCount;
}
$committedDocs = $dbForDatabases->find($collectionId, $queries);
$committedDocs = $this->dbForProject->find($collectionId, $queries);
$committedDocIds = [];
foreach ($committedDocs as $doc) {
$committedDocIds[$doc->getId()] = true;
@@ -225,19 +214,17 @@ 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($database, $collectionId, $documentId, $transactionId);
$doc = $this->getDocument($collectionId, $documentId, $transactionId);
return !$doc->isEmpty();
}
+2 -9
View File
@@ -519,7 +519,6 @@ class Event
* @param string $pattern
* @param array $params
* @param ?Document $database
* @param ?Document $database
* @return array
* @throws \InvalidArgumentException
*/
@@ -534,7 +533,7 @@ class Event
$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, vectorsdb,etc)
// so a projection from databases to the actual prefix
if ((str_contains($pattern, 'databases.') && $database && $database->getAttribute('type') !== 'legacy')) {
$parsed = self::getDatabaseTypeEvents($database, $parsed);
}
@@ -696,6 +695,7 @@ class Event
)
) {
$pairedEvents = [];
foreach ($events as $event) {
$pairedEvents[] = $event;
// tablesdb needs databases event with tables and collections
@@ -745,13 +745,6 @@ class Event
'attributes' => 'columns',
];
break;
case 'documentsdb':
case 'vectorsdb':
// sending the type itself(eg: documentsdb, vectorsdb)
$eventMap = [
'databases' => $database->getAttribute('type')
];
break;
}
foreach ($event as $eventKey => $eventValue) {
if (isset($eventMap[$eventValue])) {
-1
View File
@@ -340,7 +340,6 @@ class Exception extends \Exception
public const string MIGRATION_ALREADY_EXISTS = 'migration_already_exists';
public const string MIGRATION_IN_PROGRESS = 'migration_in_progress';
public const string MIGRATION_PROVIDER_ERROR = 'migration_provider_error';
public const string MIGRATION_DATABASE_TYPE_UNSUPPORTED = 'migration_database_type_unsupported';
/** Realtime */
public const string REALTIME_MESSAGE_FORMAT_INVALID = 'realtime_message_format_invalid';
+6 -25
View File
@@ -492,8 +492,6 @@ class Realtime extends MessagingAdapter
break;
case 'databases':
case 'tablesdb':
case 'documentsdb':
case 'vectorsdb':
$resource = $parts[4] ?? '';
if (in_array($resource, ['columns', 'attributes', 'indexes'])) {
$channels[] = 'console';
@@ -513,20 +511,12 @@ class Realtime extends MessagingAdapter
$resourceId = $tableId ?: $collectionId;
$channels = [];
switch ($parts[0]) {
case 'databases':
case 'tablesdb':
// sending legacy + tablesdb events to both legacy and tablesdb
$channels = array_values(array_unique(array_merge(
self::getDatabaseChannels('legacy', $database->getId(), $resourceId, $payload->getId(), 'databases'),
self::getDatabaseChannels('tablesdb', $database->getId(), $resourceId, $payload->getId(), 'databases'),
self::getDatabaseChannels('tablesdb', $database->getId(), $resourceId, $payload->getId())
)));
break;
default:
// only prefixed events
$channels = array_values(self::getDatabaseChannels($parts[0], $database->getId(), $resourceId, $payload->getId()));
}
// sending legacy + tablesdb events to both legacy and tablesdb
$channels = array_values(array_unique(array_merge(
self::getDatabaseChannels('legacy', $database->getId(), $resourceId, $payload->getId(), 'databases'),
self::getDatabaseChannels('tablesdb', $database->getId(), $resourceId, $payload->getId(), 'databases'),
self::getDatabaseChannels('tablesdb', $database->getId(), $resourceId, $payload->getId())
)));
$roles = $collection->getAttribute('documentSecurity', false)
? \array_merge($collection->getRead(), $payload->getRead())
@@ -592,7 +582,6 @@ class Realtime extends MessagingAdapter
* @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(
@@ -626,13 +615,6 @@ class Realtime extends MessagingAdapter
$channels[] = "{$basePrefix}.{$databaseId}.tables.{$resourceId}.rows.{$payloadId}";
break;
case 'documentsdb':
case 'vectorsdb':
$channels[] = 'documents';
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents";
$channels[] = "{$basePrefix}.{$databaseId}.collections.{$resourceId}.documents.{$payloadId}";
break;
default:
$basePrefix = 'databases';
$channels[] = 'documents';
@@ -641,7 +623,6 @@ class Realtime extends MessagingAdapter
break;
}
return $channels;
}
}
+1
View File
@@ -91,6 +91,7 @@ abstract class Migration
'1.7.4' => 'V22',
'1.8.0' => 'V23',
'1.8.1' => 'V23',
'1.8.2' => 'V23',
'1.9.0' => 'V24',
];
+2
View File
@@ -35,6 +35,7 @@ class Platform
public const SCHEME_ANDROID = 'appwrite-android';
public const SCHEME_WINDOWS = 'appwrite-windows';
public const SCHEME_LINUX = 'appwrite-linux';
public const SCHEME_TAURI = 'tauri';
/**
* @var array<string, string> Map scheme types to user-friendly platform names.
@@ -53,6 +54,7 @@ class Platform
self::SCHEME_FIREFOX_EXTENSION => 'Web (Firefox Extension)',
self::SCHEME_SAFARI_EXTENSION => 'Web (Safari Extension)',
self::SCHEME_EDGE_EXTENSION => 'Web (Edge Extension)',
self::SCHEME_TAURI => 'Web (Tauri)',
];
/**
@@ -69,6 +69,7 @@ class Origin extends Validator
Platform::SCHEME_FIREFOX_EXTENSION,
Platform::SCHEME_SAFARI_EXTENSION,
Platform::SCHEME_EDGE_EXTENSION,
Platform::SCHEME_TAURI,
];
if (in_array($this->scheme, $webPlatforms, true)) {
$validator = new Hostname($this->allowedHostnames);
@@ -22,11 +22,3 @@ const INDEX = 'index';
const DOCUMENTS = 'document';
const ATTRIBUTES = 'attribute';
const COLLECTIONS = 'collection';
const LEGACY = 'legacy';
const TABLESDB = 'tablesdb';
const DOCUMENTSDB = 'documentsdb';
const VECTORSDB = 'vectorsdb';
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 = DATABASE_TYPE_LEGACY;
private string $context = 'legacy';
public function getDatabaseType(): string
{
@@ -20,13 +20,7 @@ class Action extends AppwriteAction
public function setHttpPath(string $path): AppwriteAction
{
if (\str_contains($path, '/tablesdb')) {
$this->context = DATABASE_TYPE_TABLESDB;
}
if (\str_contains($path, '/documentsdb')) {
$this->context = DATABASE_TYPE_DOCUMENTSDB;
}
if (\str_contains($path, '/vectorsdb')) {
$this->context = DATABASE_TYPE_VECTORSDB;
$this->context = 'tablesdb';
}
return parent::setHttpPath($path);
}
@@ -15,8 +15,6 @@ abstract class Action extends UtopiaAction
*/
private ?string $context = COLLECTIONS;
private ?string $databaseType = LEGACY;
/**
* Get the response model used in the SDK and HTTP responses.
*/
@@ -26,9 +24,6 @@ abstract class Action extends UtopiaAction
{
if (\str_contains($path, '/tablesdb')) {
$this->context = TABLES;
$this->databaseType = TABLESDB;
} elseif (\str_contains($path, '/vectorsdb')) {
$this->databaseType = VECTORSDB;
}
return parent::setHttpPath($path);
}
@@ -41,14 +36,6 @@ 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').
*/
@@ -84,13 +84,12 @@ class Create extends Action
->param('indexes', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial), attributes (array of attribute keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional).', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
{
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@@ -122,18 +121,12 @@ class Create extends Action
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
}
/**
* @var Database $dbForDatabases
*/
$dbForDatabases = $getDatabasesDB($database);
$collectionKey = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
$databaseKey = 'database_' . $database->getSequence();
$attributesValidator = new AttributesValidator(
APP_LIMIT_ARRAY_PARAMS_SIZE,
$dbForDatabases->getAdapter()->getSupportForSpatialAttributes(),
$dbForDatabases->getAdapter()->getSupportForAttributes()
$dbForProject->getAdapter()->getSupportForSpatialAttributes()
);
if (!$attributesValidator->isValid($attributes)) {
@@ -162,7 +155,7 @@ class Create extends Action
}
// Validate indexes
$indexesValidator = new IndexesValidator($dbForDatabases->getLimitForIndexes());
$indexesValidator = new IndexesValidator($dbForProject->getLimitForIndexes());
if (!$indexesValidator->isValid($indexes)) {
$dbForProject->deleteDocument($databaseKey, $collection->getId());
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $indexesValidator->getDescription());
@@ -185,23 +178,21 @@ class Create extends Action
$indexValidator = new IndexValidator(
$collectionAttributes,
[],
$dbForDatabases->getAdapter()->getMaxIndexLength(),
$dbForDatabases->getAdapter()->getInternalIndexesKeys(),
$dbForDatabases->getAdapter()->getSupportForIndexArray(),
$dbForDatabases->getAdapter()->getSupportForSpatialIndexNull(),
$dbForDatabases->getAdapter()->getSupportForSpatialIndexOrder(),
$dbForDatabases->getAdapter()->getSupportForVectors(),
$dbForDatabases->getAdapter()->getSupportForAttributes(),
$dbForDatabases->getAdapter()->getSupportForMultipleFulltextIndexes(),
$dbForDatabases->getAdapter()->getSupportForIdenticalIndexes(),
$dbForDatabases->getAdapter()->getSupportForObjectIndexes(),
$dbForDatabases->getAdapter()->getSupportForTrigramIndex(),
$dbForDatabases->getAdapter()->getSupportForSpatialAttributes(),
$dbForDatabases->getAdapter()->getSupportForIndex(),
$dbForDatabases->getAdapter()->getSupportForUniqueIndex(),
$dbForDatabases->getAdapter()->getSupportForFulltextIndex(),
$dbForDatabases->getAdapter()->getSupportForTTLIndexes(),
$dbForDatabases->getAdapter()->getSupportForObject(),
$dbForProject->getAdapter()->getMaxIndexLength(),
$dbForProject->getAdapter()->getInternalIndexesKeys(),
$dbForProject->getAdapter()->getSupportForIndexArray(),
$dbForProject->getAdapter()->getSupportForSpatialIndexNull(),
$dbForProject->getAdapter()->getSupportForSpatialIndexOrder(),
$dbForProject->getAdapter()->getSupportForVectors(),
$dbForProject->getAdapter()->getSupportForAttributes(),
$dbForProject->getAdapter()->getSupportForMultipleFulltextIndexes(),
$dbForProject->getAdapter()->getSupportForIdenticalIndexes(),
$dbForProject->getAdapter()->getSupportForObjectIndexes(),
$dbForProject->getAdapter()->getSupportForTrigramIndex(),
$dbForProject->getAdapter()->getSupportForSpatialAttributes(),
$dbForProject->getAdapter()->getSupportForIndex(),
$dbForProject->getAdapter()->getSupportForUniqueIndex(),
$dbForProject->getAdapter()->getSupportForFulltextIndex(),
);
foreach ($collectionIndexes as $indexDoc) {
@@ -212,7 +203,7 @@ class Create extends Action
}
try {
$dbForDatabases->createCollection(
$dbForProject->createCollection(
id: $collectionKey,
attributes: $collectionAttributes,
indexes: $collectionIndexes,
@@ -62,14 +62,13 @@ class Delete extends Action
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
{
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($database->isEmpty()) {
@@ -86,8 +85,7 @@ class Delete extends Action
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Failed to remove $type from DB");
}
$dbForDatabases = $getDatabasesDB($database);
$dbForDatabases->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence());
$dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence());
$queueForDatabase
->setType(DATABASE_TYPE_DELETE_COLLECTION)
@@ -17,7 +17,6 @@ abstract class Action extends DatabasesAction
* @var string|null The current context (either 'row' or 'document')
*/
private ?string $context = DOCUMENTS;
private ?string $databaseType = DATABASE_TYPE_LEGACY;
/**
* Get the response model used in the SDK and HTTP responses.
@@ -28,10 +27,6 @@ abstract class Action extends DatabasesAction
{
if (str_contains($path, '/tablesdb/')) {
$this->context = ROWS;
} elseif (str_contains($path, '/documentsdb/')) {
$this->databaseType = DATABASE_TYPE_DOCUMENTSDB;
} elseif (str_contains($path, '/vectorsdb/')) {
$this->databaseType = DATABASE_TYPE_VECTORSDB;
}
$contextId = '$' . $this->getCollectionsEventsContext() . 'Id';
@@ -50,39 +45,6 @@ abstract class Action extends DatabasesAction
return parent::setHttpPath($path);
}
protected function getDatabasesOperationReadMetric(): string
{
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return METRIC_DATABASES_OPERATIONS_READS;
}
return $this->databaseType.'.'.METRIC_DATABASES_OPERATIONS_READS;
}
protected function getDatabasesIdOperationReadMetric(): string
{
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return METRIC_DATABASE_ID_OPERATIONS_READS;
}
return $this->databaseType.'.'.METRIC_DATABASE_ID_OPERATIONS_READS;
}
protected function getDatabasesOperationWriteMetric(): string
{
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return METRIC_DATABASES_OPERATIONS_WRITES;
}
return $this->databaseType.'.'.METRIC_DATABASES_OPERATIONS_WRITES;
}
protected function getDatabasesIdOperationWriteMetric(): string
{
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return METRIC_DATABASE_ID_OPERATIONS_WRITES;
}
return $this->databaseType.'.'.METRIC_DATABASE_ID_OPERATIONS_WRITES;
}
/**
* Get the plural of the given name.
*
@@ -82,7 +82,6 @@ class Decrement extends Action
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('plan')
@@ -90,7 +89,7 @@ class Decrement extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization): void
{
$isAPIKey = User::isApp($authorization->getRoles());
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
@@ -171,9 +170,8 @@ class Decrement extends Action
return;
}
$dbForDatabases = $getDatabasesDB($database);
try {
$document = $dbForDatabases->decreaseDocumentAttribute(
$document = $dbForProject->decreaseDocumentAttribute(
collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
id: $documentId,
attribute: $attribute,
@@ -203,8 +201,8 @@ class Decrement extends Action
);
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), 1)
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), 1);
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1)
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1);
$queueForEvents
->setParam('databaseId', $databaseId)
@@ -82,7 +82,6 @@ class Increment extends Action
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('plan')
@@ -90,7 +89,7 @@ class Increment extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization): void
{
$isAPIKey = User::isApp($authorization->getRoles());
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
@@ -171,9 +170,8 @@ class Increment extends Action
return;
}
$dbForDatabases = $getDatabasesDB($database);
try {
$document = $dbForDatabases->increaseDocumentAttribute(
$document = $dbForProject->increaseDocumentAttribute(
collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
id: $documentId,
attribute: $attribute,
@@ -203,8 +201,8 @@ class Increment extends Action
);
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), 1)
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), 1);
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1)
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1);
$queueForEvents
->setParam('databaseId', $databaseId)
@@ -76,7 +76,6 @@ class Delete extends Action
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -87,7 +86,7 @@ class Delete extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, EventProcessor $eventProcessor): void
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Context $usage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, EventProcessor $eventProcessor): void
{
$database = $dbForProject->getDocument('databases', $databaseId);
if ($database->isEmpty()) {
@@ -164,11 +163,10 @@ class Delete extends Action
return;
}
$dbForDatabases = $getDatabasesDB($database);
$documents = [];
try {
$modified = $dbForDatabases->deleteDocuments(
$modified = $dbForProject->deleteDocuments(
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
$queries,
onNext: function (Document $document) use ($plan, &$documents) {
@@ -191,12 +189,12 @@ class Delete extends Action
}
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), \max(1, $modified));
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified));
$response->dynamic(new Document([
'total' => $modified,
$this->getSDKGroup() => $documents
$this->getSDKGroup() => $documents,
]), $this->getResponseModel());
$this->triggerBulk(
@@ -80,7 +80,6 @@ class Update extends Action
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -91,7 +90,7 @@ class Update extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string|array $data, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, EventProcessor $eventProcessor): void
public function action(string $databaseId, string $collectionId, string|array $data, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Context $usage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, EventProcessor $eventProcessor): void
{
$data = \is_string($data)
? \json_decode($data, true)
@@ -190,12 +189,11 @@ class Update extends Action
return;
}
$dbForDatabases = $getDatabasesDB($database);
$documents = [];
try {
$modified = $dbForDatabases->withPreserveDates(function () use ($plan, &$documents, $dbForDatabases, $database, $collection, $data, $queries) {
return $dbForDatabases->updateDocuments(
$modified = $dbForProject->withPreserveDates(function () use ($plan, &$documents, $dbForProject, $database, $collection, $data, $queries) {
return $dbForProject->updateDocuments(
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
new Document($data),
$queries,
@@ -222,8 +220,8 @@ class Update extends Action
}
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), \max(1, $modified));
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified));
$response->dynamic(new Document([
'total' => $modified,
@@ -58,7 +58,7 @@ class Upsert extends Action
group: $this->getSDKGroup(),
name: self::getName(),
description: '/docs/references/databases/upsert-documents.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
@@ -78,7 +78,6 @@ class Upsert extends Action
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -89,7 +88,7 @@ class Upsert extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, EventProcessor $eventProcessor): void
public function action(string $databaseId, string $collectionId, array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Context $usage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, EventProcessor $eventProcessor): void
{
$database = $dbForProject->getDocument('databases', $databaseId);
if ($database->isEmpty()) {
@@ -166,12 +165,11 @@ class Upsert extends Action
return;
}
$dbForDatabases = $getDatabasesDB($database);
$upserted = [];
try {
$modified = $dbForDatabases->withPreserveDates(function () use ($dbForDatabases, $database, $collection, $documents, $plan, &$upserted) {
return $dbForDatabases->upsertDocuments(
$modified = $dbForProject->withPreserveDates(function () use ($dbForProject, $database, $collection, $documents, $plan, &$upserted) {
return $dbForProject->upsertDocuments(
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
$documents,
onNext: function (Document $document) use ($plan, &$upserted) {
@@ -197,8 +195,8 @@ class Upsert extends Action
}
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), \max(1, $modified));
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified));
$response->dynamic(new Document([
'total' => $modified,
@@ -85,7 +85,7 @@ class Create extends Action
new Parameter('documentId', optional: false),
new Parameter('data', optional: false),
new Parameter('permissions', optional: true),
new Parameter('transactionId', optional: true)
new Parameter('transactionId', optional: true),
],
deprecated: new Deprecated(
since: '1.8.0',
@@ -110,7 +110,7 @@ class Create extends Action
new Parameter('databaseId', optional: false),
new Parameter('collectionId', optional: false),
new Parameter('documents', optional: false),
new Parameter('transactionId', optional: true)
new Parameter('transactionId', optional: true),
],
deprecated: new Deprecated(
since: '1.8.0',
@@ -127,7 +127,6 @@ class Create extends Action
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('user')
->inject('queueForEvents')
->inject('usage')
@@ -139,7 +138,7 @@ class Create extends Action
->inject('eventProcessor')
->callback($this->action(...));
}
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Document $user, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization, EventProcessor $eventProcessor): void
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization, EventProcessor $eventProcessor): void
{
$data = \is_string($data)
? \json_decode($data, true)
@@ -448,12 +447,11 @@ class Create extends Action
return;
}
$dbForDatabases = $getDatabasesDB($database);
try {
$created = [];
$dbForDatabases->withPreserveDates(
function () use (&$created, $dbForDatabases, $database, $collection, $documents) {
$dbForDatabases->createDocuments(
$dbForProject->withPreserveDates(
function () use (&$created, $dbForProject, $database, $collection, $documents) {
$dbForProject->createDocuments(
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
$documents,
onNext: function ($doc) use (&$created) {
@@ -492,15 +490,15 @@ class Create extends Action
}
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), \max(1, $operations)); // per collection
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection
$response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED);
if ($isBulk) {
$response->dynamic(new Document([
'total' => count($created),
$this->getSDKGroup() => $created
$this->getSdkGroup() => $created
]), $this->getBulkResponseModel());
$this->triggerBulk(
@@ -79,7 +79,6 @@ class Delete extends Action
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
@@ -96,7 +95,6 @@ class Delete extends Action
?\DateTime $requestTimestamp,
UtopiaResponse $response,
Database $dbForProject,
callable $getDatabasesDB,
Event $queueForEvents,
Context $usage,
TransactionState $transactionState,
@@ -118,15 +116,14 @@ class Delete extends Action
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
}
$dbForDatabases = $getDatabasesDB($database);
// Read permission should not be required for delete
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
if ($transactionId !== null) {
// Use transaction-aware document retrieval to see changes from same transaction
$document = $transactionState->getDocument($database, $collectionTableId, $documentId, $transactionId);
$document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId);
} else {
$document = $authorization->skip(fn () => $dbForDatabases->getDocument($collectionTableId, $documentId));
$document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
}
if ($document->isEmpty()) {
@@ -190,8 +187,8 @@ class Delete extends Action
}
try {
$dbForDatabases->withRequestTimestamp($requestTimestamp, function () use ($dbForDatabases, $database, $collection, $documentId) {
$dbForDatabases->deleteDocument(
$dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) {
$dbForProject->deleteDocument(
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
$documentId
);
@@ -68,14 +68,13 @@ class Get extends Action
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID to read uncommitted changes within the transaction.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('transactionState')
->inject('authorization')
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Context $usage, TransactionState $transactionState, Authorization $authorization): void
{
$isAPIKey = User::isApp($authorization->getRoles());
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
@@ -87,7 +86,6 @@ class Get extends Action
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
$dbForDatabases = $getDatabasesDB($database);
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
}
@@ -101,17 +99,14 @@ class Get extends Action
try {
$selects = Query::groupByType($queries)['selections'] ?? [];
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
// Use transaction-aware document retrieval if transactionId is provided
if ($transactionId !== null) {
$document = $transactionState->getDocument($database, $collectionTableId, $documentId, $transactionId, $queries);
} elseif (! empty($selects)) {
// has selects, allow relationship on documents!
$document = $dbForDatabases->getDocument($collectionTableId, $documentId, $queries);
$document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId, $queries);
} elseif (!empty($selects)) {
$document = $dbForProject->getDocument($collectionTableId, $documentId, $queries);
} else {
// has no selects, disable relationship looping on documents!
$document = $dbForDatabases->skipRelationships(fn () => $dbForDatabases->getDocument($collectionTableId, $documentId, $queries));
$document = $dbForProject->skipRelationships(fn () => $dbForProject->getDocument($collectionTableId, $documentId, $queries));
}
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
@@ -134,8 +129,8 @@ class Get extends Action
);
$usage
->addMetric($this->getDatabasesOperationReadMetric(), max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationReadMetric()), $operations);
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
$response->addHeader('X-Debug-Operations', $operations);
@@ -70,7 +70,6 @@ class XList extends Action
->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)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('locale')
->inject('geodb')
->inject('authorization')
@@ -78,7 +77,7 @@ class XList extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void
{
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($database->isEmpty()) {
@@ -90,8 +89,7 @@ class XList extends Action
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
}
$dbForDatabases = $getDatabasesDB($database);
$document = $dbForDatabases->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId);
$document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId);
if ($document->isEmpty()) {
throw new Exception($this->getNotFoundException(), params: [$documentId]);
}
@@ -83,7 +83,6 @@ class Update extends Action
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
@@ -92,7 +91,7 @@ class Update extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void
{
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
@@ -119,16 +118,15 @@ class Update extends Action
$data = $this->parseOperators($data, $collection);
}
$dbForDatabases = $getDatabasesDB($database);
// Read permission should not be required for update
/** @var Document $document */
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
if ($transactionId !== null) {
// Use transaction-aware document retrieval to see changes from same transaction
$document = $transactionState->getDocument($database, $collectionTableId, $documentId, $transactionId);
$document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId);
} else {
$document = $authorization->skip(fn () => $dbForDatabases->getDocument($collectionTableId, $documentId));
$document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
}
if ($document->isEmpty()) {
@@ -249,8 +247,8 @@ class Update extends Action
$setCollection($collection, $newDocument);
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), $operations);
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations);
// Handle transaction staging
if ($transactionId !== null) {
@@ -321,9 +319,9 @@ class Update extends Action
try {
$document = $dbForDatabases->withRequestTimestamp(
$document = $dbForProject->withRequestTimestamp(
$requestTimestamp,
fn () => $dbForDatabases->withPreserveDates(fn () => $dbForDatabases->updateDocument(
fn () => $dbForProject->withPreserveDates(fn () => $dbForProject->updateDocument(
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
$document->getId(),
$newDocument
@@ -87,7 +87,6 @@ class Upsert extends Action
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
@@ -96,7 +95,7 @@ class Upsert extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void
{
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
@@ -125,7 +124,6 @@ class Upsert extends Action
$data = $this->parseOperators($data, $collection);
}
$dbForDatabases = $getDatabasesDB($database);
$allowedPermissions = [
Database::PERMISSION_READ,
Database::PERMISSION_UPDATE,
@@ -136,15 +134,13 @@ class Upsert extends Action
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
// If no permission, upsert permission from the old document if present (update scenario) else add default permission (create scenario)
if (\is_null($permissions)) {
if ($transactionId !== null) {
// Use transaction-aware document retrieval to see changes from same transaction
$oldDocument = $transactionState->getDocument($database, $collectionTableId, $documentId, $transactionId);
$oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId);
} else {
$oldDocument = $authorization->skip(fn () => $dbForDatabases->getDocument($collectionTableId, $documentId));
$oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
}
if ($oldDocument->isEmpty()) {
if (!empty($user->getId())) {
@@ -186,7 +182,7 @@ class Upsert extends Action
$newDocument = new Document($data);
$operations = 0;
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $dbForDatabases, $database, &$operations, $authorization) {
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) {
$operations++;
$relationships = \array_filter(
@@ -230,7 +226,7 @@ class Upsert extends Action
if ($relation instanceof Document) {
$relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser);
$oldDocument = $authorization->skip(fn () => $dbForDatabases->getDocument(
$oldDocument = $authorization->skip(fn () => $dbForProject->getDocument(
'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(),
$relation->getId()
));
@@ -261,8 +257,8 @@ class Upsert extends Action
$setCollection($collection, $newDocument);
$usage
->addMetric($this->getDatabasesOperationWriteMetric(), \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationWriteMetric()), \max(1, $operations));
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations));
// Handle transaction staging
if ($transactionId !== null) {
@@ -331,8 +327,8 @@ class Upsert extends Action
$upserted = [];
try {
$dbForDatabases->withPreserveDates(function () use (&$upserted, $dbForDatabases, $database, $collection, $newDocument) {
return $dbForDatabases->upsertDocuments(
$dbForProject->withPreserveDates(function () use (&$upserted, $dbForProject, $database, $collection, $newDocument) {
return $dbForProject->upsertDocuments(
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
[$newDocument],
onNext: function (Document $document) use (&$upserted) {
@@ -355,9 +351,9 @@ class Upsert extends Action
if (empty($upserted[0])) {
if ($transactionId !== null) {
// For transactions, get the document with transaction changes applied
$upserted[0] = $transactionState->getDocument($database, $collectionTableId, $documentId, $transactionId);
$upserted[0] = $transactionState->getDocument($collectionTableId, $documentId, $transactionId);
} else {
$upserted[0] = $dbForDatabases->getDocument($collectionTableId, $documentId);
$upserted[0] = $dbForProject->getDocument($collectionTableId, $documentId);
}
}
@@ -76,14 +76,13 @@ class XList extends Action
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('getDatabasesDB')
->inject('usage')
->inject('transactionState')
->inject('authorization')
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, Context $usage, TransactionState $transactionState, Authorization $authorization): void
{
$isAPIKey = User::isApp($authorization->getRoles());
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
@@ -104,7 +103,6 @@ class XList extends Action
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
$dbForDatabases = $getDatabasesDB($database);
$cursor = Query::getCursorQueries($queries, false);
$cursor = \reset($cursor);
@@ -116,7 +114,7 @@ class XList extends Action
$documentId = $cursor->getValue();
$cursorDocument = $authorization->skip(fn () => $dbForDatabases->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId));
$cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId));
if ($cursorDocument->isEmpty()) {
$type = ucfirst($this->getContext());
@@ -129,10 +127,11 @@ class XList extends Action
try {
$selectQueries = Query::groupByType($queries)['selections'] ?? [];
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
// Use transaction-aware document retrieval if transactionId is provided
if ($transactionId !== null) {
$documents = $transactionState->listDocuments($database, $collectionTableId, $transactionId, $queries);
$total = $includeTotal ? $transactionState->countDocuments($database, $collectionTableId, $transactionId, $queries) : 0;
$documents = $transactionState->listDocuments($collectionTableId, $transactionId, $queries);
$total = $includeTotal ? $transactionState->countDocuments($collectionTableId, $transactionId, $queries) : 0;
} elseif (! empty($selectQueries)) {
if ((int)$ttl > 0) {
@@ -171,7 +170,7 @@ class XList extends Action
}, $cachedDocuments);
$documentsCacheHit = true;
} else {
$documents = $dbForDatabases->find($collectionTableId, $queries);
$documents = $dbForProject->find($collectionTableId, $queries);
// Convert Document objects to arrays for caching
$documentsArray = \array_map(function ($doc) {
@@ -197,15 +196,15 @@ class XList extends Action
} else {
// has selects, allow relationship on documents
$documents = $dbForDatabases->find($collectionTableId, $queries);
$total = $includeTotal ? $dbForDatabases->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0;
$documents = $dbForProject->find($collectionTableId, $queries);
$total = $includeTotal ? $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0;
}
} else {
// has no selects, disable relationship loading on documents
/* @type Document[] $documents */
$documents = $dbForDatabases->skipRelationships(fn () => $dbForDatabases->find($collectionTableId, $queries));
$total = $includeTotal ? $dbForDatabases->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0;
$documents = $dbForProject->skipRelationships(fn () => $dbForProject->find($collectionTableId, $queries));
$total = $includeTotal ? $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0;
}
} catch (OrderException $e) {
$documents = $this->isCollectionsAPI() ? 'documents' : 'rows';
@@ -233,8 +232,8 @@ class XList extends Action
}
$usage
->addMetric($this->getDatabasesOperationReadMetric(), max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationReadMetric()), $operations);
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
$response->dynamic(new Document([
'total' => $total,
@@ -77,14 +77,13 @@ class Create extends Action
->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional: true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
{
$db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@@ -104,9 +103,7 @@ class Create extends Action
Query::equal('databaseInternalId', [$db->getSequence()])
], 61);
$dbForDatabases = $getDatabasesDB($db);
$limit = $dbForDatabases->getLimitForIndexes();
$limit = $dbForProject->getLimitForIndexes();
if ($count >= $limit) {
throw new Exception($this->getLimitException(), params: [$collectionId]);
@@ -148,35 +145,32 @@ class Create extends Action
];
$contextType = $this->getParentContext();
if ($dbForDatabases->getAdapter()->getSupportForAttributes()) {
foreach ($attributes as $i => $attribute) {
// find attribute metadata in collection document
$attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key'));
foreach ($attributes as $i => $attribute) {
$attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key'));
if ($attributeIndex === false) {
throw new Exception($this->getParentUnknownException(), params: [$attribute]);
}
if ($attributeIndex === false) {
throw new Exception($this->getParentUnknownException(), params: [$attribute]);
}
$attributeStatus = $oldAttributes[$attributeIndex]['status'];
$attributeType = $oldAttributes[$attributeIndex]['type'];
$attributeArray = $oldAttributes[$attributeIndex]['array'] ?? false;
$attributeStatus = $oldAttributes[$attributeIndex]['status'];
$attributeType = $oldAttributes[$attributeIndex]['type'];
$attributeArray = $oldAttributes[$attributeIndex]['array'] ?? false;
if ($attributeType === Database::VAR_RELATIONSHIP) {
throw new Exception($this->getParentInvalidTypeException(), "Cannot create an index for a relationship $contextType: " . $oldAttributes[$attributeIndex]['key']);
}
if ($attributeType === Database::VAR_RELATIONSHIP) {
throw new Exception($this->getParentInvalidTypeException(), "Cannot create an index for a relationship $contextType: " . $oldAttributes[$attributeIndex]['key']);
}
if ($attributeStatus !== 'available') {
throw new Exception($this->getParentNotAvailableException(), params: [$oldAttributes[$attributeIndex]['key']]);
}
if ($attributeStatus !== 'available') {
throw new Exception($this->getParentNotAvailableException(), params: [$oldAttributes[$attributeIndex]['key']]);
}
if (empty($lengths[$i])) {
$lengths[$i] = null;
}
if (empty($lengths[$i])) {
$lengths[$i] = null;
}
if ($attributeArray === true) {
// Because of a bug in MySQL, we cannot create indexes on array attributes for now, otherwise queries break.
throw new Exception(Exception::INDEX_INVALID, 'Creating indexes on array attributes is not currently supported.');
}
if ($attributeArray === true) {
// Because of a bug in MySQL, we cannot create indexes on array attributes for now, otherwise queries break.
throw new Exception(Exception::INDEX_INVALID, 'Creating indexes on array attributes is not currently supported.');
}
}
@@ -197,23 +191,21 @@ class Create extends Action
$validator = new IndexValidator(
$collection->getAttribute('attributes'),
$collection->getAttribute('indexes'),
$dbForDatabases->getAdapter()->getMaxIndexLength(),
$dbForDatabases->getAdapter()->getInternalIndexesKeys(),
$dbForDatabases->getAdapter()->getSupportForIndexArray(),
$dbForDatabases->getAdapter()->getSupportForSpatialIndexNull(),
$dbForDatabases->getAdapter()->getSupportForSpatialIndexOrder(),
$dbForDatabases->getAdapter()->getSupportForVectors(),
$dbForDatabases->getAdapter()->getSupportForAttributes(),
$dbForDatabases->getAdapter()->getSupportForMultipleFulltextIndexes(),
$dbForDatabases->getAdapter()->getSupportForIdenticalIndexes(),
$dbForDatabases->getAdapter()->getSupportForObjectIndexes(),
$dbForDatabases->getAdapter()->getSupportForTrigramIndex(),
$dbForDatabases->getAdapter()->getSupportForSpatialAttributes(),
$dbForDatabases->getAdapter()->getSupportForIndex(),
$dbForDatabases->getAdapter()->getSupportForUniqueIndex(),
$dbForDatabases->getAdapter()->getSupportForFulltextIndex(),
$dbForDatabases->getAdapter()->getSupportForTTLIndexes(),
$dbForDatabases->getAdapter()->getSupportForObject()
$dbForProject->getAdapter()->getMaxIndexLength(),
$dbForProject->getAdapter()->getInternalIndexesKeys(),
$dbForProject->getAdapter()->getSupportForIndexArray(),
$dbForProject->getAdapter()->getSupportForSpatialIndexNull(),
$dbForProject->getAdapter()->getSupportForSpatialIndexOrder(),
$dbForProject->getAdapter()->getSupportForVectors(),
$dbForProject->getAdapter()->getSupportForAttributes(),
$dbForProject->getAdapter()->getSupportForMultipleFulltextIndexes(),
$dbForProject->getAdapter()->getSupportForIdenticalIndexes(),
$dbForProject->getAdapter()->getSupportForObjectIndexes(),
$dbForProject->getAdapter()->getSupportForTrigramIndex(),
$dbForProject->getAdapter()->getSupportForSpatialAttributes(),
$dbForProject->getAdapter()->getSupportForIndex(),
$dbForProject->getAdapter()->getSupportForUniqueIndex(),
$dbForProject->getAdapter()->getSupportForFulltextIndex(),
);
if (!$validator->isValid($index)) {
@@ -70,13 +70,12 @@ class Update extends Action
->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, ?string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Authorization $authorization): void
public function action(string $databaseId, string $collectionId, ?string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
{
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($database->isEmpty()) {
@@ -111,8 +110,7 @@ class Update extends Action
->setAttribute('search', \implode(' ', [$collectionId, $searchName]))
);
$dbForDatabases = $getDatabasesDB($database);
$dbForDatabases->updateCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $permissions, $documentSecurity);
$dbForProject->updateCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $permissions, $documentSecurity);
$queueForEvents
->setContext('database', $database)
@@ -31,11 +31,6 @@ class Get extends Action
return UtopiaResponse::MODEL_USAGE_COLLECTION;
}
protected function getMetric(): string
{
return METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS;
}
public function __construct()
{
$this
@@ -69,16 +64,14 @@ class Get extends Action
->inject('response')
->inject('dbForProject')
->inject('authorization')
->inject('getDatabasesDB')
->callback($this->action(...));
}
public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization, callable $getDatabasesDB): void
public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void
{
$database = $dbForProject->getDocument('databases', $databaseId);
$collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId);
$dbForDatabases = $getDatabasesDB($database);
$collection = $dbForDatabases->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence());
$collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence());
if ($collection->isEmpty()) {
throw new Exception($this->getNotFoundException(), params: [$collectionId]);
@@ -88,7 +81,7 @@ class Get extends Action
$stats = $usage = [];
$days = $periods[$range];
$metrics = [
str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], $this->getMetric()),
str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS),
];
$authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) {
@@ -19,9 +19,7 @@ use Utopia\Database\Exception\Index as IndexException;
use Utopia\Database\Exception\Limit as LimitException;
use Utopia\Database\Exception\Structure as StructureException;
use Utopia\Database\Helpers\ID;
use Utopia\DSN\DSN;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\System\System;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
@@ -32,121 +30,6 @@ class Create extends Action
return 'createDatabase';
}
protected function getDatabaseDSN(Document $project): string
{
// TODO: use database worker for for creating the v2 schema if not present
// it is considered that the v2 metadata schema is already created during server start in the http.php
return $this->constructDatabaseDSNFromProjectDatabase($this->getDatabaseType(), $project->getAttribute('region'), $project->getAttribute('database'));
}
private function constructDatabaseDSNFromProjectDatabase(string $databasetype, $region, ?string $dsn = null): string
{
$databases = [];
$databaseKeys = [];
/**
* @var string|null $databaseOverride
*/
$databaseOverride = '';
$dbScheme = '';
$databaseSharedTables = [];
$databaseSharedTablesV1 = [];
$databaseSharedTablesV2 = [];
$projectSharedTables = [];
$projectSharedTablesV1 = [];
$projectSharedTablesV2 = [];
switch ($databasetype) {
case DOCUMENTSDB:
$databases = Config::getParam('pools-documentsdb', []);
$databaseKeys = System::getEnv('_APP_DATABASE_DOCUMENTSDB_KEYS', '');
$databaseOverride = System::getEnv('_APP_DATABASE_DOCUMENTSDB_OVERRIDE');
$dbScheme = System::getEnv('_APP_DB_HOST_DOCUMENTSDB', 'mongodb');
$databaseSharedTables = \explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES', ''));
$databaseSharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES_V1', ''));
break;
case VECTORSDB:
$databases = Config::getParam('pools-vectorsdb', []);
$databaseKeys = System::getEnv('_APP_DATABASE_VECTORSDB_KEYS', '');
$databaseOverride = System::getEnv('_APP_DATABASE_VECTORSDB_OVERRIDE');
$dbScheme = System::getEnv('_APP_DB_HOST_VECTORSDB', 'postgresql');
$databaseSharedTables = \explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES', ''));
$databaseSharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES_V1', ''));
break;
default:
// legacy/tablesdb
// it is already created during create project
return $dsn;
}
$isSharedTablesV1 = false;
$isSharedTablesV2 = false;
if (!empty($dsn)) {
try {
$parsedDsn = new DSN($dsn);
$dsnHost = $parsedDsn->getHost();
} catch (\InvalidArgumentException) {
$dsnHost = $dsn;
}
$projectSharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$projectSharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
$projectSharedTablesV2 = \array_diff($projectSharedTables, $projectSharedTablesV1);
$isSharedTablesV1 = \in_array($dsnHost, $projectSharedTablesV1);
$isSharedTablesV2 = \in_array($dsnHost, $projectSharedTablesV2);
}
if ($region !== 'default') {
$keys = explode(',', $databaseKeys);
$databases = array_filter($keys, function ($value) use ($region) {
return str_contains($value, $region);
});
}
$databaseSharedTablesV2 = \array_diff($databaseSharedTables, $databaseSharedTablesV1);
$index = \array_search($databaseOverride, $databases);
if ($index !== false) {
$selectedDsn = $databases[$index];
} else {
if (!empty($dsn)) {
$beforeFilter = \array_values($databases);
if ($isSharedTablesV1) {
$databases = array_filter($databases, fn ($value) => \in_array($value, $databaseSharedTablesV1));
} elseif ($isSharedTablesV2) {
$databases = array_filter($databases, fn ($value) => \in_array($value, $databaseSharedTablesV2));
} else {
$databases = array_filter($databases, fn ($value) => !\in_array($value, $databaseSharedTables));
}
}
$selectedDsn = !empty($databases) ? $databases[array_rand($databases)] : '';
}
if (\in_array($selectedDsn, $databaseSharedTables)) {
$schema = 'appwrite';
$database = 'appwrite';
$namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '');
$selectedDsn = $schema . '://' . $selectedDsn . '?database=' . $database;
if (!empty($namespace)) {
$selectedDsn .= '&namespace=' . $namespace;
}
}
try {
new DSN($selectedDsn);
} catch (\InvalidArgumentException) {
$selectedDsn = $dbScheme.'://' . $selectedDsn;
}
return $selectedDsn;
}
protected function getDatabaseCollection()
{
return match ($this->getDatabaseType()) {
'vectorsdb' => (Config::getParam('collections', [])['vectorsdb'] ?? [])['collections'] ?? [],
default => (Config::getParam('collections', [])['databases'] ?? [])['collections'] ?? [],
};
}
public function __construct()
{
$this
@@ -182,15 +65,13 @@ class Create extends Action
->param('databaseId', '', 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.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Database name. Max length: 128 chars.')
->param('enabled', true, new Boolean(), 'Is the database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true)
->inject('project')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->callback($this->action(...));
}
public function action(string $databaseId, string $name, bool $enabled, Document $project, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents): void
public function action(string $databaseId, string $name, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
{
$databaseId = $databaseId == 'unique()' ? ID::unique() : $databaseId;
@@ -201,7 +82,6 @@ class Create extends Action
'enabled' => $enabled,
'search' => implode(' ', [$databaseId, $name]),
'type' => $this->getDatabaseType(),
'database' => $this->getDatabaseDSN($project)
]));
} catch (DuplicateException) {
throw new Exception(Exception::DATABASE_ALREADY_EXISTS, params: [$databaseId]);
@@ -211,7 +91,7 @@ class Create extends Action
$database = $dbForProject->getDocument('databases', $databaseId);
$collections = $this->getDatabaseCollection();
$collections = (Config::getParam('collections', [])['databases'] ?? [])['collections'] ?? [];
if (empty($collections)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'The "collections" collection is not configured.');
}
@@ -10,45 +10,11 @@ abstract class Action extends DatabasesAction
* The current API context (either 'table' or 'collection').
*/
private ?string $context = COLLECTIONS;
private ?string $databaseType = LEGACY;
public function getDatabaseType(): string
{
return $this->databaseType;
}
protected function getDatabasesOperationWriteMetric(): string
{
if ($this->databaseType === LEGACY || $this->databaseType === TABLESDB) {
return METRIC_DATABASES_OPERATIONS_WRITES;
}
return $this->databaseType.'.'.METRIC_DATABASES_OPERATIONS_WRITES;
}
protected function getDatabasesIdOperationWriteMetric(): string
{
if ($this->databaseType === LEGACY || $this->databaseType === TABLESDB) {
return METRIC_DATABASE_ID_OPERATIONS_WRITES;
}
return $this->databaseType.'.'.METRIC_DATABASE_ID_OPERATIONS_WRITES;
}
public function setHttpPath(string $path): DatabasesAction
{
switch (true) {
case str_contains($path, '/tablesdb'):
$this->context = TABLES;
$this->databaseType = TABLESDB;
break;
case str_contains($path, '/documentsdb'):
$this->context = COLLECTIONS;
$this->databaseType = DOCUMENTSDB;
break;
case str_contains($path, '/vectorsdb'):
$this->context = COLLECTIONS;
$this->databaseType = VECTORSDB;
break;
if (\str_contains($path, '/tablesdb')) {
$this->context = TABLES;
}
return parent::setHttpPath($path);
}
@@ -148,7 +148,7 @@ class Create extends Action
$collectionKey = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
$isDependant = isset($dependants[$collectionKey][$documentId]);
$document = $transactionState->getDocument($database, $collectionKey, $documentId, $transactionId);
$document = $transactionState->getDocument($collectionKey, $documentId, $transactionId);
if ($document->isEmpty() && !$isDependant && $operation['action'] !== 'upsert') {
throw new Exception(Exception::DOCUMENT_NOT_FOUND, params: [$documentId]);
}
@@ -67,10 +67,8 @@ class Update extends Action
->param('transactionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Transaction ID.', false, ['dbForProject'])
->param('commit', false, new Boolean(), 'Commit transaction?', true)
->param('rollback', false, new Boolean(), 'Rollback transaction?', true)
->inject('project')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('user')
->inject('transactionState')
->inject('queueForDeletes')
@@ -90,7 +88,6 @@ class Update extends Action
* @param bool $rollback
* @param UtopiaResponse $response
* @param Database $dbForProject
* @param callable $getDatabasesDB
* @param Document $user
* @param TransactionState $transactionState
* @param Delete $queueForDeletes
@@ -109,7 +106,7 @@ class Update extends Action
* @throws Structure
* @throws \Utopia\Http\Exception
*/
public function action(string $transactionId, bool $commit, bool $rollback, Document $project, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization, EventProcessor $eventProcessor): void
public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization, EventProcessor $eventProcessor): void
{
if (!$commit && !$rollback) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true');
@@ -138,52 +135,14 @@ class Update extends Action
}
if ($commit) {
$operations = [];
$totalOperations = 0;
$databaseOperations = [];
$currentDocumentId = null;
$firstOperation = $authorization->skip(fn () => $dbForProject->findOne('transactionLogs', [
Query::equal('transactionInternalId', [$transaction->getSequence()]),
Query::orderAsc(),
]));
if ($firstOperation->isEmpty()) {
$transaction = $authorization->skip(fn () => $dbForProject->updateDocument(
'transactions',
$transactionId,
new Document(['status' => 'committed'])
));
$queueForDeletes
->setType(DELETE_TYPE_DOCUMENT)
->setDocument($transaction);
$response
->setStatusCode(SwooleResponse::STATUS_CODE_OK)
->dynamic($transaction, $this->getResponseModel());
return;
}
$databaseDoc = null;
switch ($this->getDatabaseType()) {
case DATABASE_TYPE_DOCUMENTSDB:
case DATABASE_TYPE_VECTORSDB:
$databaseDoc = $authorization->skip(fn () => $dbForProject->findOne('databases', [
Query::equal('$sequence', [$firstOperation['databaseInternalId']])
]));
break;
default:
// Legacy/tablesdb: use project-level database
$databaseDoc = new Document(['database' => $project->getAttribute('database')]);
break;
}
$dbForDatabases = $getDatabasesDB($databaseDoc);
try {
$dbForDatabases->withTransaction(function () use ($dbForDatabases, $dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $usage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) {
$dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $usage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) {
$authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([
'status' => 'committing',
])));
@@ -223,7 +182,7 @@ class Update extends Action
}
if ($action === 'delete' && $documentId && empty($data)) {
$doc = $dbForDatabases->getDocument($collectionId, $documentId);
$doc = $dbForProject->getDocument($collectionId, $documentId);
if (!$doc->isEmpty()) {
$operation['data'] = $doc->getArrayCopy();
$data = $operation['data'];
@@ -237,40 +196,40 @@ class Update extends Action
switch ($action) {
case 'create':
$this->handleCreateOperation($dbForDatabases, $collectionId, $documentId, $data, $createdAt, $state);
$this->handleCreateOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
break;
case 'update':
$this->handleUpdateOperation($dbForDatabases, $collectionId, $documentId, $data, $createdAt, $state);
$this->handleUpdateOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
break;
case 'upsert':
$this->handleUpsertOperation($dbForDatabases, $collectionId, $documentId, $data, $createdAt, $state);
$this->handleUpsertOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
break;
case 'delete':
$this->handleDeleteOperation($dbForDatabases, $collectionId, $documentId, $createdAt, $state);
$this->handleDeleteOperation($dbForProject, $collectionId, $documentId, $createdAt, $state);
break;
case 'increment':
$this->handleIncrementOperation($dbForDatabases, $collectionId, $documentId, $data, $createdAt, $state);
$this->handleIncrementOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
break;
case 'decrement':
$this->handleDecrementOperation($dbForDatabases, $collectionId, $documentId, $data, $createdAt, $state);
$this->handleDecrementOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
break;
case 'bulkCreate':
$count = $this->handleBulkCreateOperation($dbForDatabases, $collectionId, $data, $createdAt, $state);
$count = $this->handleBulkCreateOperation($dbForProject, $collectionId, $data, $createdAt, $state);
$totalOperations += $count;
$databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count;
break;
case 'bulkUpdate':
$count = $this->handleBulkUpdateOperation($dbForDatabases, $transactionState, $collectionId, $data, $createdAt, $state);
$count = $this->handleBulkUpdateOperation($dbForProject, $transactionState, $collectionId, $data, $createdAt, $state);
$totalOperations += $count;
$databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count;
break;
case 'bulkUpsert':
$count = $this->handleBulkUpsertOperation($dbForDatabases, $transactionState, $collectionId, $data, $createdAt, $state);
$count = $this->handleBulkUpsertOperation($dbForProject, $transactionState, $collectionId, $data, $createdAt, $state);
$totalOperations += $count;
$databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count;
break;
case 'bulkDelete':
$count = $this->handleBulkDeleteOperation($dbForDatabases, $transactionState, $collectionId, $data, $createdAt, $state);
$count = $this->handleBulkDeleteOperation($dbForProject, $transactionState, $collectionId, $data, $createdAt, $state);
$totalOperations += $count;
$databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count;
break;
@@ -320,16 +279,15 @@ class Update extends Action
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
$usage->addMetric($this->getDatabasesOperationWriteMetric(), $totalOperations);
$usage->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $totalOperations);
foreach ($databaseOperations as $sequence => $count) {
$usage->addMetric(
str_replace('{databaseInternalId}', $sequence, $this->getDatabasesIdOperationWriteMetric()),
str_replace('{databaseInternalId}', $sequence, METRIC_DATABASE_ID_OPERATIONS_WRITES),
$count
);
}
$dbCache = [];
foreach ($operations as $operation) {
$databaseInternalId = $operation['databaseInternalId'];
$collectionInternalId = $operation['collectionInternalId'];
@@ -342,16 +300,6 @@ class Update extends Action
$data = $data->getArrayCopy();
}
// using a dbCache so only one time database is set with databaseInternalId
if (!isset($dbCache[$databaseInternalId])) {
$databaseDoc = $authorization->skip(fn () => $dbForProject->findOne('databases', [
Query::equal('$sequence', [$databaseInternalId])
]));
$dbCache[$databaseInternalId] = $getDatabasesDB($databaseDoc);
}
$dbForDatabases = $dbCache[$databaseInternalId];
$database = $authorization->skip(fn () => $dbForProject->findOne('databases', [
Query::equal('$sequence', [$databaseInternalId])
]));
@@ -381,7 +329,7 @@ class Update extends Action
$eventAction = 'create';
$docId = $documentId ?? $data['$id'] ?? null;
if ($docId) {
$doc = $dbForDatabases->getDocument($collectionId, $docId);
$doc = $dbForProject->getDocument($collectionId, $docId);
if (!$doc->isEmpty()) {
$documentsToTrigger[] = $doc;
}
@@ -392,7 +340,7 @@ class Update extends Action
case 'decrement':
$eventAction = 'update';
if ($documentId) {
$doc = $dbForDatabases->getDocument($collectionId, $documentId);
$doc = $dbForProject->getDocument($collectionId, $documentId);
if (!$doc->isEmpty()) {
$documentsToTrigger[] = $doc;
}
@@ -408,7 +356,7 @@ class Update extends Action
$eventAction = 'update';
$docId = $documentId ?? $data['$id'] ?? null;
if ($docId) {
$doc = $dbForDatabases->getDocument($collectionId, $docId);
$doc = $dbForProject->getDocument($collectionId, $docId);
if (!$doc->isEmpty()) {
$documentsToTrigger[] = $doc;
}
@@ -26,43 +26,6 @@ class Get extends Action
return 'getDatabaseUsage';
}
protected $databaseType = DATABASE_TYPE_LEGACY;
public function setHttpPath(string $path): Action
{
$this->databaseType = match (true) {
str_contains($path, '/documentsdb') => DATABASE_TYPE_DOCUMENTSDB,
str_contains($path, '/vectorsdb') => DATABASE_TYPE_VECTORSDB,
default => DATABASE_TYPE_LEGACY,
};
return parent::setHttpPath($path);
}
protected function getMetrics(): array
{
$metrics = [
METRIC_DATABASE_ID_COLLECTIONS,
METRIC_DATABASE_ID_DOCUMENTS,
METRIC_DATABASE_ID_STORAGE,
METRIC_DATABASE_ID_OPERATIONS_READS,
METRIC_DATABASE_ID_OPERATIONS_WRITES
];
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return $metrics;
}
return array_map(
fn ($metric) => "{$this->databaseType}.{$metric}",
$metrics
);
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_USAGE_DATABASE;
}
public function __construct()
{
$this
@@ -111,10 +74,13 @@ class Get extends Action
$periods = Config::getParam('usage', []);
$stats = $usage = [];
$days = $periods[$range];
$metrics = array_map(
fn ($metric) => str_replace('{databaseInternalId}', $database->getSequence(), $metric),
$this->getMetrics()
);
$metrics = [
str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS),
str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_DOCUMENTS),
str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE),
str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS),
str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES)
];
$authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) {
foreach ($metrics as $metric) {
@@ -176,6 +142,6 @@ class Get extends Action
'storage' => $usage[$metrics[2]]['data'],
'databaseReads' => $usage[$metrics[3]]['data'],
'databaseWrites' => $usage[$metrics[4]]['data'],
]), $this->getResponseModel());
]), UtopiaResponse::MODEL_USAGE_DATABASE);
}
}
@@ -24,43 +24,6 @@ class XList extends Action
return 'listDatabaseUsage';
}
protected $databaseType = DATABASE_TYPE_LEGACY;
public function setHttpPath(string $path): Action
{
$this->databaseType = match (true) {
str_contains($path, '/documentsdb') => DATABASE_TYPE_DOCUMENTSDB,
str_contains($path, '/vectorsdb') => DATABASE_TYPE_VECTORSDB,
default => DATABASE_TYPE_LEGACY,
};
return parent::setHttpPath($path);
}
protected function getMetrics(): array
{
$metrics = [
METRIC_DATABASES,
METRIC_COLLECTIONS,
METRIC_DOCUMENTS,
METRIC_DATABASES_STORAGE,
METRIC_DATABASES_OPERATIONS_READS,
METRIC_DATABASES_OPERATIONS_WRITES,
];
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return $metrics;
}
return array_map(
fn ($metric) => "{$this->databaseType}.{$metric}",
$metrics
);
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_USAGE_DATABASES;
}
public function __construct()
{
$this
@@ -103,7 +66,14 @@ class XList extends Action
$periods = Config::getParam('usage', []);
$stats = $usage = [];
$days = $periods[$range];
$metrics = $this->getMetrics();
$metrics = [
METRIC_DATABASES,
METRIC_COLLECTIONS,
METRIC_DOCUMENTS,
METRIC_DATABASES_STORAGE,
METRIC_DATABASES_OPERATIONS_READS,
METRIC_DATABASES_OPERATIONS_WRITES,
];
$authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) {
foreach ($metrics as $metric) {
@@ -166,6 +136,6 @@ class XList extends Action
'storage' => $usage[$metrics[3]]['data'],
'databasesReads' => $usage[$metrics[4]]['data'],
'databasesWrites' => $usage[$metrics[5]]['data'],
]), $this->getResponseModel());
]), UtopiaResponse::MODEL_USAGE_DATABASES);
}
}
@@ -17,6 +17,7 @@ use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Query;
use Utopia\Database\Validator\Query\Cursor;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Platform\Action;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
@@ -91,8 +92,6 @@ class XList extends Action
$cursor->setValue($cursorDocument);
}
$queries[] = Query::equal('type', [$this->getDatabaseType()]);
try {
$databases = $dbForProject->find('databases', $queries);
$total = $includeTotal ? $dbForProject->count('databases', $queries, APP_LIMIT_COUNT) : 0;
@@ -1,75 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CollectionCreate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Boolean;
use Utopia\Validator\JSON;
use Utopia\Validator\Nullable;
use Utopia\Validator\Text;
class Create extends CollectionCreate
{
public static function getName(): string
{
return 'createDocumentsDBCollection';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_COLLECTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/documentsdb/:databaseId/collections')
->desc('Create collection')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].create')
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'collections.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'collections',
name: 'createCollection',
description: '/docs/references/documentsdb/create-collection.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', 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.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
->param('permissions', null, new Nullable(new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE)), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true)
->param('attributes', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attribute definitions to create. Each attribute should contain: key (string), type (string: string, integer, float, boolean, datetime, relationship), size (integer, required for string type), required (boolean, optional), default (mixed, optional), array (boolean, optional), and type-specific options.', true)
->param('indexes', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial), attributes (array of attribute keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional).', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,62 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as CollectionDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Delete extends CollectionDelete
{
public static function getName(): string
{
return 'deleteDocumentsDBCollection';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_COLLECTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId')
->desc('Delete collection')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].collections.[collectionId].delete')
->label('audits.event', 'collection.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'collections',
name: 'deleteCollection',
description: '/docs/references/documentsdb/delete-collection.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_NOCONTENT,
model: UtopiaResponse::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,73 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Attribute;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Decrement as DecrementDocumentAttribute;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Numeric;
class Decrement extends DecrementDocumentAttribute
{
public static function getName(): string
{
return 'decrementDocumentsDBDocumentAttribute';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId/:attribute/decrement')
->desc('Decrement document attribute')
->groups(['api', 'database'])
->label('event', 'documentsdb.[databaseId].collections.[collectionId].documents.[documentId].update')
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'decrementDocumentAttribute',
description: '/docs/references/documentsdb/decrement-document-attribute.md',
auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documentId', '', new UID(), 'Document ID.')
->param('attribute', '', new Key(), 'Attribute key.')
->param('value', 1, new Numeric(), 'Value to decrement the attribute by. The value must be a number.', true)
->param('min', null, new Numeric(), 'Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,73 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Attribute;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Increment as IncrementDocumentAttribute;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Numeric;
class Increment extends IncrementDocumentAttribute
{
public static function getName(): string
{
return 'incrementDocumentsDBDocumentAttribute';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId/:attribute/increment')
->desc('Increment document attribute')
->groups(['api', 'database'])
->label('event', 'documentsdb.[databaseId].collections.[collectionId].documents.[documentId].update')
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'incrementDocumentAttribute',
description: '/docs/references/documentsdb/increment-document-attribute.md',
auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documentId', '', new UID(), 'Document ID.')
->param('attribute', '', new Key(), 'Attribute key.')
->param('value', 1, new Numeric(), 'Value to increment the attribute by. The value must be a number.', true)
->param('max', null, new Numeric(), 'Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,72 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Bulk;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Delete as DocumentsDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Text;
class Delete extends DocumentsDelete
{
public static function getName(): string
{
return 'deleteDocumentsDBDocuments';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Delete documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'deleteDocuments',
description: '/docs/references/documentsdb/delete-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,74 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Bulk;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Update as DocumentsUpdate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\JSON;
use Utopia\Validator\Text;
class Update extends DocumentsUpdate
{
public static function getName(): string
{
return 'updateDocumentsDBDocuments';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Update documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'updateDocuments',
description: '/docs/references/documentsdb/update-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true)
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,74 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Bulk;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Upsert as DocumentsUpsert;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\JSON;
class Upsert extends DocumentsUpsert
{
public static function getName(): string
{
return 'upsertDocumentsDBDocuments';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Upsert documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'upsertDocuments',
description: '/docs/references/documentsdb/upsert-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON,
)
])
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of document data as JSON objects. May contain partial documents.', false, ['plan'])
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,116 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as DocumentCreate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Parameter;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\JSON;
class Create extends DocumentCreate
{
public static function getName(): string
{
return 'createDocumentsDBDocument';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
protected function getBulkResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Create document')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'createDocument',
desc: 'Create document',
description: '/docs/references/documentsdb/create-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON,
parameters: [
new Parameter('databaseId', optional: false),
new Parameter('collectionId', optional: false),
new Parameter('documentId', optional: false),
new Parameter('data', optional: false),
new Parameter('permissions', optional: true),
]
),
new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'createDocuments',
desc: 'Create documents',
description: '/docs/references/documentsdb/create-documents.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getBulkResponseModel(),
)
],
contentType: ContentType::JSON,
parameters: [
new Parameter('databaseId', optional: false),
new Parameter('collectionId', optional: false),
new Parameter('documents', optional: false),
]
)
])
->param('databaseId', '', new UID(), 'Database ID.')
->param('documentId', '', new CustomId(), 'Document 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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.')
->param('data', [], new JSON(), 'Document data as JSON object.', true, example: '{"username":"walter.obrien","email":"walter.obrien@example.com","fullName":"Walter O\'Brien","age":30,"isAdmin":false}')
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of documents data as JSON objects.', true, ['plan'])
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('user')
->inject('queueForEvents')
->inject('usage')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('authorization')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,76 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DocumentDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Delete extends DocumentDelete
{
public static function getName(): string
{
return 'deleteDocumentsDBDocument';
}
/**
* Same explanation as the parent action.
*
* 1. `SDKResponse` uses `UtopiaResponse::MODEL_NONE`.
* 2. But we later need the actual return type for events queue below!
*/
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Delete document')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].delete')
->label('audits.event', 'document.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{request.documentId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'deleteDocument',
description: '/docs/references/documentsdb/delete-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_NOCONTENT,
model: UtopiaResponse::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
->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('documentId', '', new UID(), 'Document ID.')
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,64 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as DocumentGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Text;
class Get extends DocumentGet
{
public static function getName(): string
{
return 'getDocumentsDBDocument';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Get document')
->groups(['api', 'database'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'getDocument',
description: '/docs/references/documentsdb/get-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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('documentId', '', new UID(), 'Document ID.')
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true)
->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('transactionState')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,59 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Logs;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Logs\XList as DocumentLogXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class XList extends DocumentLogXList
{
public static function getName(): string
{
return 'listDocumentsDBDocumentLogs';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId/logs')
->desc('List document logs')
->groups(['api', 'database'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'logs',
name: 'listDocumentLogs',
description: '/docs/references/documentsdb/get-document-logs.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON,
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documentId', '', new UID(), 'Document ID.')
->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)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('locale')
->inject('geodb')
->inject('authorization')
->inject('audit')
->callback($this->action(...));
}
}
@@ -1,75 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Update as DocumentUpdate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\JSON;
class Update extends DocumentUpdate
{
public static function getName(): string
{
return 'updateDocumentsDBDocument';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Update document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update')
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'updateDocument',
description: '/docs/references/documentsdb/update-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documentId', '', new UID(), 'Document ID.')
->param('data', [], new JSON(), 'Document data as JSON object. Include only fields and value pairs to be updated.', true)
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,78 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Upsert as DocumentUpsert;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\JSON;
class Upsert extends DocumentUpsert
{
public static function getName(): string
{
return 'upsertDocumentsDBDocument';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Upsert a document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert')
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.upsert')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'upsertDocument',
description: '/docs/references/documentsdb/upsert-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
),
])
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documentId', '', new UID(), 'Document ID.')
->param('data', [], new JSON(), 'Document data as JSON object. Include all required fields of the document to be created or updated.', true)
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('requestTimestamp')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,68 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\XList as DocumentXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Boolean;
use Utopia\Validator\Range;
use Utopia\Validator\Text;
class XList extends DocumentXList
{
public static function getName(): string
{
return 'listDocumentsDBDocuments';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('List documents')
->groups(['api', 'database'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'listDocuments',
description: '/docs/references/documentsdb/list-documents.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true)
->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true)
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->param('ttl', 0, new Range(min: 0, max: 86400), 'TTL (seconds) for cached responses when caching is enabled for select queries. Must be between 0 and 86400 (24 hours).', true)
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('getDatabasesDB')
->inject('usage')
->inject('transactionState')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,56 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Get as CollectionGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Get extends CollectionGet
{
public static function getName(): string
{
return 'getDocumentsDBCollection';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_COLLECTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId')
->desc('Get collection')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'collections',
name: 'getCollection',
description: '/docs/references/documentsdb/get-collection.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->inject('response')
->inject('dbForProject')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,73 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Create as IndexCreate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Integer;
use Utopia\Validator\Nullable;
use Utopia\Validator\WhiteList;
class Create extends IndexCreate
{
public static function getName(): string
{
return 'createDocumentsDBIndex';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_INDEX;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/indexes')
->desc('Create index')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].create')
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'index.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'createIndex',
description: '/docs/references/documentsdb/create-index.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_ACCEPTED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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', null, fn (Database $dbForProject) => new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Index Key.', false, ['dbForProject'])
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL]), 'Index type.')
->param('attributes', null, fn (Database $dbForProject) => new ArrayList(new Key(true, $dbForProject->getAdapter()->getMaxUIDLength()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.', false, ['dbForProject'])
->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true)
->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional: true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,67 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Delete as IndexDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Delete extends IndexDelete
{
public static function getName(): string
{
return 'deleteDocumentsDBIndex';
}
/**
* 1. `SDKResponse` uses `UtopiaResponse::MODEL_NONE`.
* 2. But we later need the actual return type for events queue below!
*/
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_INDEX;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/indexes/:key')
->desc('Delete index')
->groups(['api', 'database'])
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update')
->label('audits.event', 'index.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'deleteIndex', // getName needs to be different from parent action to avoid conflict in path name
description: '/docs/references/documentsdb/delete-index.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_NOCONTENT,
model: UtopiaResponse::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
->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(), 'Index Key.')
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,58 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Get as IndexGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Get extends IndexGet
{
public static function getName(): string
{
return 'getDocumentsDBIndex';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_INDEX;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/indexes/:key')
->desc('Get index')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'getIndex', // getName needs to be different from parent action to avoid conflict in path name
description: '/docs/references/documentsdb/get-index.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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', null, new Key(), 'Index Key.')
->inject('response')
->inject('dbForProject')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,60 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\XList as IndexXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\Queries\Indexes;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
class XList extends IndexXList
{
public static function getName(): string
{
return 'listDocumentsDBIndexes';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_INDEX_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/indexes')
->desc('List indexes')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'listIndexes', // getName needs to be different from parent action to avoid conflict in path name
description: '/docs/references/documentsdb/list-indexes.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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('queries', [], new Indexes(), '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(', ', Indexes::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')
->inject('dbForProject')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,58 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Logs;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Logs\XList as CollectionLogXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class XList extends CollectionLogXList
{
public static function getName(): string
{
return 'listDocumentsDBCollectionLogs';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/logs')
->desc('List collection logs')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: $this->getSdkGroup(),
name: 'listCollectionLogs',
description: '/docs/references/documentsdb/get-collection-logs.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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('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)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('authorization')
->inject('audit')
->callback($this->action(...));
}
}
@@ -1,68 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Update as CollectionUpdate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
class Update extends CollectionUpdate
{
public static function getName(): string
{
return 'updateDocumentsDBCollection';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_COLLECTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId')
->desc('Update collection')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].collections.[collectionId].update')
->label('audits.event', 'collection.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'collections',
name: 'updateCollection',
description: '/docs/references/documentsdb/update-collection.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_COLLECTION,
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.')
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,65 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Usage;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Usage\Get as CollectionUsageGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\WhiteList;
class Get extends CollectionUsageGet
{
public static function getName(): string
{
return 'getDocumentsDBCollectionUsage';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_USAGE_COLLECTION;
}
protected function getMetric(): string
{
return METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS_DOCUMENTSDB;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/usage')
->desc('Get collection usage stats')
->groups(['api', 'database', 'usage'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: null,
name: 'getCollectionUsage',
description: '/docs/references/documentsdb/get-collection-usage.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON,
))
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true)
->param('collectionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Collection ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('authorization')
->inject('getDatabasesDB')
->callback($this->action(...));
}
}
@@ -1,61 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\XList as CollectionXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\Queries\Collections;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
class XList extends CollectionXList
{
public static function getName(): string
{
return 'listDocumentsDBCollections';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_COLLECTION_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/collections')
->desc('List collections')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'collections',
name: 'listCollections',
description: '/docs/references/documentsdb/list-collections.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('queries', [], new Collections(), '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(', ', Collections::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)
->inject('response')
->inject('dbForProject')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,60 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB;
use Appwrite\Platform\Modules\Databases\Http\Databases\Create as DatabaseCreate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
class Create extends DatabaseCreate
{
public static function getName(): string
{
return 'createDocumentsDBDatabase';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/documentsdb')
->desc('Create database')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].create')
->label('scope', 'databases.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'database.create')
->label('audits.resource', 'database/{response.$id}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'documentsdb',
name: 'create',
description: '/docs/references/documentsdb/create.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: UtopiaResponse::MODEL_DATABASE,
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', 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.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Database name. Max length: 128 chars.')
->param('enabled', true, new Boolean(), 'Is the database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true)
->inject('project')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->callback($this->action(...));
}
}
@@ -1,56 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB;
use Appwrite\Platform\Modules\Databases\Http\Databases\Delete as DatabaseDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Delete extends DatabaseDelete
{
public static function getName(): string
{
return 'deleteDocumentsDBDatabase';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/documentsdb/:databaseId')
->desc('Delete database')
->groups(['api', 'database', 'schema'])
->label('scope', 'databases.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].delete')
->label('audits.event', 'database.delete')
->label('audits.resource', 'database/{request.databaseId}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'documentsdb',
name: 'delete',
description: '/docs/references/documentsdb/delete.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_NOCONTENT,
model: UtopiaResponse::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('usage')
->callback($this->action(...));
}
}
@@ -1,50 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB;
use Appwrite\Platform\Modules\Databases\Http\Databases\Get as DatabaseGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Get extends DatabaseGet
{
public static function getName(): string
{
return 'getDocumentsDBDatabase';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId')
->desc('Get database')
->groups(['api', 'database'])
->label('scope', 'databases.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'documentsdb',
name: 'get',
description: '/docs/references/documentsdb/get.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_DATABASE,
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->callback($this->action(...));
}
}
@@ -1,60 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Logs;
use Appwrite\Platform\Modules\Databases\Http\Databases\Logs\XList as DatabaseLogs;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class XList extends DatabaseLogs
{
public static function getName(): string
{
return 'listDocumentsDBLogs';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/logs')
->desc('List database logs')
->groups(['api', 'database'])
->label('scope', 'databases.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', [
new Method(
namespace: 'documentsDB',
group: 'logs',
name: 'listDatabaseLogs',
description: '/docs/references/documentsdb/get-logs.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_LOG_LIST,
)
],
contentType: ContentType::JSON
),
])
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database 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)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('authorization')
->inject('audit')
->callback($this->action(...));
}
}
@@ -1,56 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Transactions;
use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Create as TransactionsCreate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Range;
class Create extends TransactionsCreate
{
public static function getName(): string
{
return 'createDocumentsDBTransaction';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_TRANSACTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/documentsdb/transactions')
->desc('Create transaction')
->groups(['api', 'database', 'transactions'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'transactions',
name: 'createTransaction',
description: '/docs/references/documentsdb/create-transaction.md',
auth: [AuthType::ADMIN, AuthType::KEY, AuthType::SESSION, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: UtopiaResponse::MODEL_TRANSACTION,
)
],
contentType: ContentType::JSON
))
->param('ttl', APP_DATABASE_TXN_TTL_DEFAULT, new Range(min: APP_DATABASE_TXN_TTL_MIN, max: APP_DATABASE_TXN_TTL_MAX), 'Seconds before the transaction expires.', true)
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,55 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Transactions;
use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Delete as TransactionsDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Delete extends TransactionsDelete
{
public static function getName(): string
{
return 'deleteDocumentsDBTransaction';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_NONE;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/documentsdb/transactions/:transactionId')
->desc('Delete transaction')
->groups(['api', 'database', 'transactions'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'transactions',
name: 'deleteTransaction',
description: '/docs/references/documentsdb/delete-transaction.md',
auth: [AuthType::ADMIN, AuthType::KEY, AuthType::SESSION, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_NOCONTENT,
model: UtopiaResponse::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
->param('transactionId', '', new UID(), 'Transaction ID.')
->inject('response')
->inject('dbForProject')
->inject('queueForDeletes')
->callback($this->action(...));
}
}
@@ -1,54 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Transactions;
use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Get as TransactionsGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Get extends TransactionsGet
{
public static function getName(): string
{
return 'getDocumentsDBTransaction';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_TRANSACTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/transactions/:transactionId')
->desc('Get transaction')
->groups(['api', 'database', 'transactions'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'transactions',
name: 'getTransaction',
description: '/docs/references/documentsdb/get-transaction.md',
auth: [AuthType::ADMIN, AuthType::KEY, AuthType::SESSION, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_TRANSACTION,
)
],
contentType: ContentType::JSON
))
->param('transactionId', '', new UID(), 'Transaction ID.')
->inject('response')
->inject('dbForProject')
->callback($this->action(...));
}
}
@@ -1,60 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Transactions\Operations;
use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Operations\Create as OperationsCreate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\Operation;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
class Create extends OperationsCreate
{
public static function getName(): string
{
return 'createDocumentsDBOperations';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_TRANSACTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/documentsdb/transactions/:transactionId/operations')
->desc('Create operations')
->groups(['api', 'database', 'transactions'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'transactions',
name: 'createOperations',
description: '/docs/references/documentsdb/create-operations.md',
auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: UtopiaResponse::MODEL_TRANSACTION,
)
],
contentType: ContentType::JSON
))
->param('transactionId', '', new UID(), 'Transaction ID.')
->param('operations', [], new ArrayList(new Operation(type: 'documentsdb')), 'Array of staged operations.', true)
->inject('response')
->inject('dbForProject')
->inject('transactionState')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,69 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Transactions;
use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Update as TransactionsUpdate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
class Update extends TransactionsUpdate
{
public static function getName(): string
{
return 'updateDocumentsDBTransaction';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_TRANSACTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH)
->setHttpPath('/v1/documentsdb/transactions/:transactionId')
->desc('Update transaction')
->groups(['api', 'database', 'transactions'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'transactions',
name: 'updateTransaction',
description: '/docs/references/documentsdb/update-transaction.md',
auth: [AuthType::ADMIN, AuthType::KEY, AuthType::SESSION, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_TRANSACTION,
)
],
contentType: ContentType::JSON
))
->param('transactionId', '', new UID(), 'Transaction ID.')
->param('commit', false, new Boolean(), 'Commit transaction?', true)
->param('rollback', false, new Boolean(), 'Rollback transaction?', true)
->inject('project')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('user')
->inject('transactionState')
->inject('queueForDeletes')
->inject('queueForEvents')
->inject('usage')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('authorization')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,54 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Transactions;
use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\XList as TransactionsList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\Queries\Transactions;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class XList extends TransactionsList
{
public static function getName(): string
{
return 'listDocumentsDBTransactions';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_TRANSACTION_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/transactions')
->desc('List transactions')
->groups(['api', 'database', 'transactions'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'transactions',
name: 'listTransactions',
description: '/docs/references/documentsdb/list-transactions.md',
auth: [AuthType::ADMIN, AuthType::KEY, AuthType::SESSION, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_TRANSACTION_LIST,
)
],
contentType: ContentType::JSON
))
->param('queries', [], new Transactions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries).', true)
->inject('response')
->inject('dbForProject')
->callback($this->action(...));
}
}
@@ -1,58 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB;
use Appwrite\Platform\Modules\Databases\Http\Databases\Update as DatabaseUpdate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
class Update extends DatabaseUpdate
{
public static function getName(): string
{
return 'updateDocumentsDBDatabase';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/documentsdb/:databaseId')
->desc('Update database')
->groups(['api', 'database', 'schema'])
->label('scope', 'databases.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].update')
->label('audits.event', 'database.update')
->label('audits.resource', 'database/{response.$id}')
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'documentsdb',
name: 'update',
description: '/docs/references/documentsdb/update.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_DATABASE,
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('name', null, new Text(128), 'Database name. Max length: 128 chars.')
->param('enabled', true, new Boolean(), 'Is database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->callback($this->action(...));
}
}
@@ -1,60 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Usage;
use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\Get as DatabaseUsageGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\WhiteList;
class Get extends DatabaseUsageGet
{
public static function getName(): string
{
return 'getDocumentsDBUsage';
}
public function getResponseModel(): string
{
return UtopiaResponse::MODEL_USAGE_DOCUMENTSDB;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/:databaseId/usage')
->desc('Get DocumentsDB usage stats')
->groups(['api', 'database', 'usage'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', [
new Method(
namespace: 'documentsDB',
group: null,
name: 'getUsage',
description: '/docs/references/documentsdb/get-database-usage.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_USAGE_DOCUMENTSDB,
)
],
contentType: ContentType::JSON,
),
])
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForProject')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,56 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Usage;
use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\XList as DatabaseUsageXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\WhiteList;
class XList extends DatabaseUsageXList
{
public static function getName(): string
{
return 'listDocumentsDBUsage';
}
public function getResponseModel(): string
{
return UtopiaResponse::MODEL_USAGE_DOCUMENTSDBS;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb/usage')
->desc('Get DocumentsDB usage stats')
->groups(['api', 'database', 'usage'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', [
new Method(
namespace: 'documentsDB',
group: null,
name: 'listUsage',
description: '/docs/references/documentsdb/list-usage.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_USAGE_DATABASES,
)
],
contentType: ContentType::JSON
),
])
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForProject')
->callback($this->action(...));
}
}
@@ -1,53 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\DocumentsDB;
use Appwrite\Platform\Modules\Databases\Http\Databases\XList as DatabaseXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\Queries\Databases;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
class XList extends DatabaseXList
{
public static function getName(): string
{
return 'listDocumentsDBDatabases';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/documentsdb')
->desc('List databases')
->groups(['api', 'database'])
->label('scope', 'databases.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'documentsDB',
group: 'documentsdb',
name: 'list',
description: '/docs/references/documentsdb/list.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: UtopiaResponse::MODEL_DATABASE_LIST,
)
],
contentType: ContentType::JSON
))
->param('queries', [], new Databases(), '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 columns: ' . implode(', ', Databases::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)
->inject('response')
->inject('dbForProject')
->callback($this->action(...));
}
}
@@ -50,10 +50,8 @@ class Create extends DatabaseCreate
->param('databaseId', '', 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.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Database name. Max length: 128 chars.')
->param('enabled', true, new Boolean(), 'Is the database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true)
->inject('project')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->callback($this->action(...));
}
@@ -67,7 +67,6 @@ class Create extends CollectionCreate
->param('indexes', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial), attributes (array of column keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional).', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
@@ -54,7 +54,6 @@ class Delete extends CollectionDelete
->param('tableId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Table ID.', false, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
@@ -64,7 +64,6 @@ class Create extends IndexCreate
->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional: true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
@@ -61,7 +61,6 @@ class Delete extends DocumentsDelete
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -63,7 +63,6 @@ class Update extends DocumentsUpdate
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -63,7 +63,6 @@ class Upsert extends DocumentsUpsert
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -65,7 +65,6 @@ class Decrement extends DecrementDocumentAttribute
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('plan')
@@ -65,7 +65,6 @@ class Increment extends IncrementDocumentAttribute
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('plan')
@@ -104,7 +104,6 @@ class Create extends DocumentCreate
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID for staging the operation.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('user')
->inject('queueForEvents')
->inject('usage')
@@ -67,7 +67,6 @@ class Delete extends DocumentDelete
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
@@ -57,7 +57,6 @@ class Get extends DocumentGet
->param('transactionId', null, fn (Database $dbForProject) => new Nullable(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Transaction ID to read uncommitted changes within the transaction.', true, ['dbForProject'])
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('transactionState')
->inject('authorization')
@@ -50,7 +50,6 @@ class XList extends DocumentLogXList
->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)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('locale')
->inject('geodb')
->inject('authorization')
@@ -65,7 +65,6 @@ class Update extends DocumentUpdate
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
@@ -68,7 +68,6 @@ class Upsert extends DocumentUpsert
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
@@ -61,7 +61,6 @@ class XList extends DocumentXList
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('getDatabasesDB')
->inject('usage')
->inject('transactionState')
->inject('authorization')
@@ -62,7 +62,6 @@ class Update extends CollectionUpdate
->param('enabled', true, new Boolean(), 'Is table enabled? When set to \'disabled\', users cannot access the table but Server SDKs with and API key can still read and write to the table. No data is lost when this is toggled.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
@@ -54,7 +54,6 @@ class Get extends CollectionUsageGet
->inject('response')
->inject('dbForProject')
->inject('authorization')
->inject('getDatabasesDB')
->callback($this->action(...));
}
}
@@ -51,10 +51,8 @@ class Update extends TransactionsUpdate
->param('transactionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Transaction ID.', false, ['dbForProject'])
->param('commit', false, new Boolean(), 'Commit transaction?', true)
->param('rollback', false, new Boolean(), 'Rollback transaction?', true)
->inject('project')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('user')
->inject('transactionState')
->inject('queueForDeletes')
@@ -1,208 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Action as CollectionAction;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Index as IndexException;
use Utopia\Database\Exception\Limit as LimitException;
use Utopia\Database\Exception\NotFound as NotFoundException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
use Utopia\Validator\Range;
use Utopia\Validator\Text;
class Create extends CollectionAction
{
public static function getName(): string
{
return 'createVectorsDBCollection';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_VECTORSDB_COLLECTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/vectorsdb/:databaseId/collections')
->desc('Create collection')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].create')
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'collection.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}')
->label('sdk', new Method(
namespace: 'vectorsDB',
group: 'collections',
name: 'createCollection',
description: '/docs/references/vectorsdb/create-collection.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Database ID.', false, ['dbForProject'])
->param('collectionId', '', 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.', false, ['dbForProject'])
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
->param('dimension', null, new Range(MIN_VECTOR_DIMENSION, MAX_VECTOR_DIMENSION), 'Embedding dimension.')
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, string $name, int $dimension, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Authorization $authorization): void
{
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$collectionId = $collectionId === 'unique()' ? ID::unique() : $collectionId;
// Map aggregate permissions into the multiple permissions they represent.
$permissions = Permission::aggregate($permissions) ?? [];
try {
$collection = $dbForProject->createDocument('database_' . $database->getSequence(), new Document([
'$id' => $collectionId,
'databaseInternalId' => $database->getSequence(),
'databaseId' => $databaseId,
'$permissions' => $permissions,
'documentSecurity' => $documentSecurity,
'enabled' => $enabled,
'name' => $name,
'dimension' => $dimension,
'search' => \implode(' ', [$collectionId, $name]),
]));
} catch (DuplicateException) {
throw new Exception($this->getDuplicateException());
} catch (LimitException) {
throw new Exception($this->getLimitException());
} catch (NotFoundException) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
/** @var Database $dbForDatabases */
$dbForDatabases = $getDatabasesDB($database);
$attributes = [];
$indexes = [];
$collections = (Config::getParam('collections', [])['vectorsdb'] ?? [])['collections'] ?? [];
foreach ($collections['defaultAttributes'] as $attribute) {
if ($attribute['$id'] === 'embeddings') {
$attribute['size'] = $dimension;
}
$attributes[] = new Document($attribute);
}
foreach ($collections['defaultIndexes'] as $index) {
$indexes[] = new Document($index);
}
try {
// passing null in creates only creates the metadata collection
if (!$dbForDatabases->exists(null, Database::METADATA)) {
$dbForDatabases->create();
}
$dbForDatabases->createCollection(
id: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
permissions: $permissions,
documentSecurity: $documentSecurity,
attributes:$attributes,
indexes:$indexes
);
// Create attribute and indexes metadata documents in the attributes and indexes collections
// needed for the get and list calls
$attributeDocs = array_map(function ($attributeConfig) use ($database, $collection, $databaseId, $collectionId, $dimension) {
$key = \is_string($attributeConfig['$id']) ? $attributeConfig['$id'] : (string) $attributeConfig['$id'];
return new Document([
'$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key),
'key' => $key,
'databaseInternalId' => $database->getSequence(),
'databaseId' => $databaseId,
'collectionInternalId' => $collection->getSequence(),
'collectionId' => $collectionId,
'type' => $attributeConfig['type'],
'status' => 'available',
'size' => $dimension,
'required' => $attributeConfig['required'] ?? false,
'signed' => $attributeConfig['signed'] ?? false,
'default' => $attributeConfig['default'] ?? null,
'array' => $attributeConfig['array'] ?? false,
'format' => $attributeConfig['format'] ?? '',
'formatOptions' => $attributeConfig['formatOptions'] ?? [],
'filters' => $attributeConfig['filters'] ?? [],
'options' => $attributeConfig['options'] ?? [],
]);
}, $collections['defaultAttributes']);
$dbForProject->createDocuments('attributes', $attributeDocs);
$indexDocs = array_map(function ($indexConfig) use ($database, $collection, $databaseId, $collectionId) {
$key = \is_string($indexConfig['$id']) ? $indexConfig['$id'] : (string) $indexConfig['$id'];
return new Document([
'$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key),
'key' => $key,
'status' => 'available',
'databaseInternalId' => $database->getSequence(),
'databaseId' => $databaseId,
'collectionInternalId' => $collection->getSequence(),
'collectionId' => $collectionId,
'type' => $indexConfig['type'],
'attributes' => $indexConfig['attributes'] ?? [],
'lengths' => $indexConfig['lengths'] ?? [],
'orders' => $indexConfig['orders'] ?? [],
]);
}, $collections['defaultIndexes']);
if (!empty($indexDocs)) {
$dbForProject->createDocuments('indexes', $indexDocs);
}
} catch (DuplicateException) {
throw new Exception($this->getDuplicateException());
} catch (IndexException) {
throw new Exception($this->getInvalidIndexException());
} catch (LimitException) {
throw new Exception($this->getLimitException());
}
$queueForEvents
->setContext('database', $database)
->setParam('databaseId', $databaseId)
->setParam($this->getEventsParamKey(), $collection->getId());
$response
->setStatusCode(SwooleResponse::STATUS_CODE_CREATED)
->dynamic($collection, $this->getResponseModel());
}
}
@@ -1,62 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as CollectionDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Delete extends CollectionDelete
{
public static function getName(): string
{
return 'deleteVectorsDBCollection';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_VECTORSDB_COLLECTION;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId')
->desc('Delete collection')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].collections.[collectionId].delete')
->label('audits.event', 'collection.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'vectorsDB',
group: 'collections',
name: 'deleteCollection',
description: '/docs/references/vectorsdb/delete-collection.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_NOCONTENT,
model: UtopiaResponse::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,72 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections\Documents\Bulk;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Delete as DocumentsDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Text;
class Delete extends DocumentsDelete
{
public static function getName(): string
{
return 'deleteVectorsDBDocuments';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId/documents')
->desc('Delete documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'vectorsDB',
group: $this->getSdkGroup(),
name: 'deleteDocuments',
description: '/docs/references/vectorsdb/delete-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,74 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections\Documents\Bulk;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Update as DocumentsUpdate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\JSON;
use Utopia\Validator\Text;
class Update extends DocumentsUpdate
{
public static function getName(): string
{
return 'updateVectorsDBDocuments';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId/documents')
->desc('Update documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'vectorsDB',
group: $this->getSdkGroup(),
name: 'updateDocuments',
description: '/docs/references/vectorsdb/update-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true)
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true)
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,74 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections\Documents\Bulk;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Upsert as DocumentsUpsert;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\JSON;
class Upsert extends DocumentsUpsert
{
public static function getName(): string
{
return 'upsertVectorsDBDocuments';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId/documents')
->desc('Upsert documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: 'vectorsDB',
group: $this->getSdkGroup(),
name: 'upsertDocuments',
description: '/docs/references/vectorsdb/upsert-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON,
)
])
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of document data as JSON objects. May contain partial documents.', false, ['plan'])
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('queueForEvents')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,116 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as DocumentCreate;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Parameter;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\JSON;
class Create extends DocumentCreate
{
public static function getName(): string
{
return 'createVectorsDBDocument';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
protected function getBulkResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT_LIST;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId/documents')
->desc('Create document')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: 'vectorsDB',
group: $this->getSdkGroup(),
name: 'createDocument',
desc: 'Create document',
description: '/docs/references/vectorsdb/create-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON,
parameters: [
new Parameter('databaseId', optional: false),
new Parameter('collectionId', optional: false),
new Parameter('documentId', optional: false),
new Parameter('data', optional: false),
new Parameter('permissions', optional: true),
]
),
new Method(
namespace: 'vectorsDB',
group: $this->getSdkGroup(),
name: 'createDocuments',
desc: 'Create documents',
description: '/docs/references/vectorsdb/create-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_CREATED,
model: $this->getBulkResponseModel(),
)
],
contentType: ContentType::JSON,
parameters: [
new Parameter('databaseId', optional: false),
new Parameter('collectionId', optional: false),
new Parameter('documents', optional: false),
]
)
])
->param('databaseId', '', new UID(), 'Database ID.')
->param('documentId', '', new CustomId(), 'Document 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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.')
->param('data', [], new JSON(), 'Document data as JSON object.', true, example: '{"embeddings": [0.12, -0.55, 0.88, 1.02], "metadata": {"key":"value"} }')
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of documents data as JSON objects.', true, ['plan'])
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('user')
->inject('queueForEvents')
->inject('usage')
->inject('queueForRealtime')
->inject('queueForFunctions')
->inject('queueForWebhooks')
->inject('plan')
->inject('authorization')
->inject('eventProcessor')
->callback($this->action(...));
}
}
@@ -1,76 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DocumentDelete;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class Delete extends DocumentDelete
{
public static function getName(): string
{
return 'deleteVectorsDBDocument';
}
/**
* Same explanation as the parent action.
*
* 1. `SDKResponse` uses `UtopiaResponse::MODEL_NONE`.
* 2. But we later need the actual return type for events queue below!
*/
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Delete document')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].delete')
->label('audits.event', 'document.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{request.documentId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'vectorsDB',
group: $this->getSdkGroup(),
name: 'deleteDocument',
description: '/docs/references/vectorsdb/delete-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_NOCONTENT,
model: UtopiaResponse::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
->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('documentId', '', new UID(), 'Document ID.')
->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true)
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('queueForEvents')
->inject('usage')
->inject('transactionState')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,64 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections\Documents;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as DocumentGet;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Text;
class Get extends DocumentGet
{
public static function getName(): string
{
return 'getVectorsDBDocument';
}
protected function getResponseModel(): string
{
return UtopiaResponse::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Get document')
->groups(['api', 'database'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'vectorsDB',
group: $this->getSdkGroup(),
name: 'getDocument',
description: '/docs/references/vectorsdb/get-document.md',
auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON
))
->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('documentId', '', new UID(), 'Document ID.')
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true)
->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('usage')
->inject('transactionState')
->inject('authorization')
->callback($this->action(...));
}
}
@@ -1,59 +0,0 @@
<?php
namespace Appwrite\Platform\Modules\Databases\Http\VectorsDB\Collections\Documents\Logs;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Logs\XList as DocumentLogXList;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
class XList extends DocumentLogXList
{
public static function getName(): string
{
return 'listVectorsDBDocumentLogs';
}
public function __construct()
{
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/v1/vectorsdb/:databaseId/collections/:collectionId/documents/:documentId/logs')
->desc('List document logs')
->groups(['api', 'database'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'vectorsDB',
group: 'logs',
name: 'listDocumentLogs',
description: '/docs/references/vectorsdb/get-document-logs.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: SwooleResponse::STATUS_CODE_OK,
model: $this->getResponseModel(),
)
],
contentType: ContentType::JSON,
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documentId', '', new UID(), 'Document ID.')
->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)
->inject('response')
->inject('dbForProject')
->inject('getDatabasesDB')
->inject('locale')
->inject('geodb')
->inject('authorization')
->inject('audit')
->callback($this->action(...));
}
}

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