updated endpoints

This commit is contained in:
ArnabChatterjee20k
2025-09-26 18:01:39 +05:30
parent 3086e1cbc1
commit 56af56e341
35 changed files with 140 additions and 195 deletions
+22 -5
View File
@@ -370,16 +370,33 @@ App::setResource('dbForDocuments', function (Group $pools, Database $dbForPlatfo
return $dbForPlatform;
}
try {
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$adapter = new DatabasePool($pools->get('documentsDb'));
$database = new Database($adapter, $cache);
$database
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES)
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getSequence());
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant((int)$project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getSequence());
}
return $database;
}, ['pools', 'dbForPlatform', 'cache', 'project']);
@@ -423,7 +440,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform
}, ['pools', 'dbForPlatform', 'dbForDocuments', 'cache', 'project', 'request']);
App::setResource('dbForDatabaseRecords', function (Database $dbForProject, Database $dbForDocuments, Request $request) {
$uri = $request->getURI();
if (str_starts_with($uri, '/v1/documentsdb')) {
return $dbForDocuments;
Generated
+4 -4
View File
@@ -3796,12 +3796,12 @@
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "8d2583e15385eeba48fe164bf9eca05b1c11174b"
"reference": "6a36761adf6973727b58a465171da95f9b2fe171"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/8d2583e15385eeba48fe164bf9eca05b1c11174b",
"reference": "8d2583e15385eeba48fe164bf9eca05b1c11174b",
"url": "https://api.github.com/repos/utopia-php/database/zipball/6a36761adf6973727b58a465171da95f9b2fe171",
"reference": "6a36761adf6973727b58a465171da95f9b2fe171",
"shasum": ""
},
"require": {
@@ -3845,7 +3845,7 @@
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/attributes-fix-schemaless"
},
"time": "2025-09-25T13:29:50+00:00"
"time": "2025-09-26T08:10:25+00:00"
},
{
"name": "utopia-php/detector",
@@ -118,7 +118,7 @@ class Create extends Action
id: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
permissions: $permissions,
documentSecurity: $documentSecurity
);
);
} catch (DuplicateException) {
throw new Exception($this->getDuplicateException());
} catch (IndexException) {
@@ -84,7 +84,7 @@ class Upsert extends Action
->callback($this->action(...));
}
public function action(string $databaseId, string $collectionId, array $documents, UtopiaResponse $response, Database $dbForProject,Database $databasebForDatabaseRecords, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void
public function action(string $databaseId, string $collectionId, array $documents, UtopiaResponse $response, Database $dbForProject, Database $databasebForDatabaseRecords, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void
{
$database = $dbForProject->getDocument('databases', $databaseId);
if ($database->isEmpty()) {
@@ -166,7 +166,7 @@ class Upsert extends Action
$newDocument = new Document($data);
$operations = 0;
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject,$dbForDatabaseRecords, $database, &$operations) {
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $dbForDatabaseRecords, $database, &$operations) {
$operations++;
$relationships = \array_filter(
@@ -144,33 +144,33 @@ class Create extends Action
];
$contextType = $this->getParentContext();
if($dbForDatabaseRecords->getAdapter()->getSupportForAttributes()){
if ($dbForDatabaseRecords->getAdapter()->getSupportForAttributes()) {
foreach ($attributes as $i => $attribute) {
// find attribute metadata in collection document
$attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key'));
if ($attributeIndex === false) {
throw new Exception($this->getParentUnknownException(), "Unknown $contextType: " . $attribute . ". Verify the $contextType name or create the $contextType.");
}
$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']);
}
// ensure attribute is available
if ($attributeStatus !== 'available') {
$contextType = ucfirst($contextType);
throw new Exception($this->getParentNotAvailableException(), "$contextType not available: " . $oldAttributes[$attributeIndex]['key']);
}
if (empty($lengths[$i])) {
$lengths[$i] = null;
}
if ($attributeArray === true) {
$lengths[$i] = Database::ARRAY_INDEX_LENGTH;
$orders[$i] = null;
@@ -35,12 +35,12 @@ class Create extends CollectionCreate
->desc('Create collection')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].create')
->label('scope', ['collections.write'])
->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: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: 'collections',
name: self::getName(),
description: '/docs/references/documentsdb/create-collection.md',
@@ -30,13 +30,13 @@ class Delete extends CollectionDelete
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId')
->desc('Delete collection')
->groups(['api', 'database', 'schema'])
->label('scope', ['collections.write'])
->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: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: 'collections',
name: self::getName(),
description: '/docs/references/documentsdb/delete-collection.md',
@@ -41,10 +41,10 @@ class Decrement extends DecrementDocumentAttribute
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
description: '/docs/references/databases/decrement-document-attribute.md',
description: '/docs/references/documentsdb/decrement-document-attribute.md',
auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
@@ -41,10 +41,10 @@ class Increment extends IncrementDocumentAttribute
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
description: '/docs/references/databases/increment-document-attribute.md',
description: '/docs/references/documentsdb/increment-document-attribute.md',
auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
@@ -32,7 +32,7 @@ class Delete extends DocumentsDelete
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Delete documents')
->groups(['api', 'database'])
->label('scope', ['documents.write'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
@@ -40,9 +40,9 @@ class Delete extends DocumentsDelete
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'deleteDocuments',
description: '/docs/references/documentsdb/delete-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
@@ -58,6 +58,7 @@ class Delete extends DocumentsDelete
->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)
->inject('response')
->inject('dbForProject')
->inject('dbForDatabaseRecords')
->inject('queueForStatsUsage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -33,7 +33,7 @@ class Update extends DocumentsUpdate
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Update documents')
->groups(['api', 'database'])
->label('scope', ['documents.write'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
@@ -41,9 +41,9 @@ class Update extends DocumentsUpdate
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'updateDocuments',
description: '/docs/references/documentsdb/update-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
@@ -56,10 +56,11 @@ class Update extends DocumentsUpdate
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('data', [], new JSON(), 'Document data as JSON object. Include only fields and value pairs to be updated.', true)
->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)
->inject('response')
->inject('dbForProject')
->inject('dbForDatabaseRecords')
->inject('queueForStatsUsage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -32,7 +32,7 @@ class Upsert extends DocumentsUpsert
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Upsert documents')
->groups(['api', 'database'])
->label('scope', ['documents.write'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
@@ -41,9 +41,9 @@ class Upsert extends DocumentsUpsert
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'upsertDocuments',
description: '/docs/references/documentsdb/upsert-documents.md',
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
@@ -60,6 +60,7 @@ class Upsert extends DocumentsUpsert
->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'])
->inject('response')
->inject('dbForProject')
->inject('dbForDatabaseRecords')
->inject('queueForStatsUsage')
->inject('queueForEvents')
->inject('queueForRealtime')
@@ -41,7 +41,7 @@ class Create extends DocumentCreate
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('Create document')
->groups(['api', 'database'])
->label('scope', ['documents.write'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.create')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
@@ -50,9 +50,9 @@ class Create extends DocumentCreate
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'createDocument',
desc: 'Create document',
description: '/docs/references/documentsdb/create-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -72,7 +72,7 @@ class Create extends DocumentCreate
]
),
new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: $this->getBulkActionName(self::getName()),
desc: 'Create documents',
@@ -95,9 +95,9 @@ class Create extends DocumentCreate
->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)
->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 document data as JSON objects.', true, ['plan'])
->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of documents data as JSON objects.', true, ['plan'])
->inject('response')
->inject('dbForProject')
->inject('dbForDatabaseRecords')
@@ -36,7 +36,7 @@ class Delete extends DocumentDelete
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Delete document')
->groups(['api', 'database'])
->label('scope', ['documents.write'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].delete')
->label('audits.event', 'document.delete')
@@ -45,9 +45,9 @@ class Delete extends DocumentDelete
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'deleteDocument',
description: '/docs/references/documentsdb/delete-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
@@ -32,12 +32,12 @@ class Get extends DocumentGet
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Get document')
->groups(['api', 'database'])
->label('scope', ['documents.read'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'getDocument',
description: '/docs/references/documentsdb/get-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
@@ -27,10 +27,10 @@ class XList extends DocumentLogXList
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents/:documentId/logs')
->desc('List document logs')
->groups(['api', 'database'])
->label('scope', ['documents.read'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: 'logs',
name: self::getName(),
description: '/docs/references/documentsdb/get-document-logs.md',
@@ -34,7 +34,7 @@ class Update extends DocumentUpdate
->desc('Update document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update')
->label('scope', ['documents.write'])
->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}')
@@ -42,9 +42,9 @@ class Update extends DocumentUpdate
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'updateDocument',
description: '/docs/references/documentsdb/update-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
@@ -34,7 +34,7 @@ class Upsert extends DocumentUpsert
->desc('Upsert a document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert')
->label('scope', ['documents.write'])
->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}')
@@ -43,9 +43,9 @@ class Upsert extends DocumentUpsert
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', [
new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'upsertDocument',
description: '/docs/references/documentsdb/upsert-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
@@ -32,12 +32,12 @@ class XList extends DocumentXList
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/documents')
->desc('List documents')
->groups(['api', 'database'])
->label('scope', ['documents.read'])
->label('scope', 'documents.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
name: 'listDocuments',
description: '/docs/references/documentsdb/list-documents.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
@@ -30,10 +30,10 @@ class Get extends CollectionGet
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId')
->desc('Get collection')
->groups(['api', 'database'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: 'collections',
name: self::getName(),
description: '/docs/references/documentsdb/get-collection.md',
@@ -37,15 +37,15 @@ class Create extends IndexCreate
->desc('Create index')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create')
->label('scope', ['tables.write', 'collections.write'])
->label('scope', 'collections.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'index.create')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.tableId}')
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: 'createIndex', // getName needs to be different from parent action to avoid conflict in path name
description: '/docs/references/tablesdb/create-index.md',
name: 'createIndex',
description: '/docs/references/documentsdb/create-index.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
@@ -56,9 +56,9 @@ class Create extends IndexCreate
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/tablesdb#tablesDBCreate).')
->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.')
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL]), 'Index type.')
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.')
->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.')
->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)
@@ -35,13 +35,13 @@ class Delete extends IndexDelete
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/indexes/:key')
->desc('Delete index')
->groups(['api', 'database'])
->label('scope', ['collections.write'])
->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: $this->getSdkNamespace(),
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',
@@ -31,10 +31,10 @@ class Get extends IndexGet
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/indexes/:key')
->desc('Get index')
->groups(['api', 'database'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
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',
@@ -31,10 +31,10 @@ class XList extends IndexXList
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/indexes')
->desc('List indexes')
->groups(['api', 'database'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
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',
@@ -27,10 +27,10 @@ class XList extends CollectionLogXList
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/logs')
->desc('List collection logs')
->groups(['api', 'database'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: $this->getSdkGroup(),
name: self::getName(),
description: '/docs/references/documentsdb/get-collection-logs.md',
@@ -33,13 +33,13 @@ class Update extends CollectionUpdate
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId')
->desc('Update collection')
->groups(['api', 'database', 'schema'])
->label('scope', ['collections.write'])
->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: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: 'collections',
name: self::getName(),
description: '/docs/references/documentsdb/update-collection.md',
@@ -31,10 +31,10 @@ class Get extends CollectionUsageGet
->setHttpPath('/v1/documentsdb/:databaseId/collections/:collectionId/usage')
->desc('Get collection usage stats')
->groups(['api', 'database', 'usage'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: null,
name: self::getName(),
description: '/docs/references/documentsdb/get-collection-usage.md',
@@ -32,10 +32,10 @@ class XList extends CollectionXList
->setHttpPath('/v1/documentsdb/:databaseId/collections')
->desc('List collections')
->groups(['api', 'database'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
namespace: 'documentsdb',
group: 'collections',
name: self::getName(),
description: '/docs/references/documentsdb/list-collections.md',
@@ -9,12 +9,11 @@ use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Platform\Action;
use Utopia\Swoole\Response as SwooleResponse;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
class Create extends Action
class Create extends DatabaseCreate
{
public static function getName(): string
{
@@ -52,80 +51,7 @@ class Create extends Action
->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('response')
->inject('dbForProject')
->inject('dbForDatabaseRecords')
->inject('queueForEvents')
->callback($this->action(...));
}
public function action(string $databaseId, string $name, bool $enabled, UtopiaResponse $response, \Utopia\Database\Database $dbForProject ,\Utopia\Database\Database $dbForDatabaseRecords, \Appwrite\Event\Event $queueForEvents): void
{
// Ensure the project's metadata 'databases' collection exists
$metaDatabases = $dbForProject->getCollection('databases');
if ($metaDatabases->isEmpty()) {
$projectsCollections = (\Utopia\Config\Config::getParam('collections', [])['projects'] ?? []);
$databasesSchema = $projectsCollections['databases'] ?? [];
if (!empty($databasesSchema)) {
$attributes = [];
foreach ($databasesSchema['attributes'] ?? [] as $attribute) {
$attributes[] = new \Utopia\Database\Document($attribute);
}
$indexes = [];
foreach ($databasesSchema['indexes'] ?? [] as $index) {
$indexes[] = new \Utopia\Database\Document($index);
}
$dbForProject->createCollection('databases', $attributes, $indexes);
}
}
// Proceed with base create logic
$databaseId = $databaseId == 'unique()' ? \Utopia\Database\Helpers\ID::unique() : $databaseId;
try {
$dbForProject->createDocument('databases', new \Utopia\Database\Document([
'$id' => $databaseId,
'name' => $name,
'enabled' => $enabled,
'search' => implode(' ', [$databaseId, $name]),
'type' => 'documentsdb',
]));
} catch (\Utopia\Database\Exception\Duplicate) {
throw new \Appwrite\Extend\Exception(\Appwrite\Extend\Exception::DATABASE_ALREADY_EXISTS);
} catch (\Utopia\Database\Exception\Structure $e) {
throw new \Appwrite\Extend\Exception(\Appwrite\Extend\Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage());
}
$database = $dbForProject->getDocument('databases', $databaseId);
$collections = (\Utopia\Config\Config::getParam('collections', [])['databases'] ?? [])['collections'] ?? [];
if (empty($collections)) {
throw new \Appwrite\Extend\Exception(\Appwrite\Extend\Exception::GENERAL_SERVER_ERROR, 'The "collections" collection is not configured.');
}
$attributes = [];
foreach ($collections['attributes'] as $attribute) {
$attributes[] = new \Utopia\Database\Document($attribute);
}
$indexes = [];
foreach ($collections['indexes'] as $index) {
$indexes[] = new \Utopia\Database\Document($index);
}
try {
$dbForProject->createCollection('database_' . $database->getSequence(), $attributes, $indexes);
$dbForDatabaseRecords->createCollection('database_' . $database->getSequence(), $attributes, $indexes);
} catch (\Utopia\Database\Exception\Duplicate) {
throw new \Appwrite\Extend\Exception(\Appwrite\Extend\Exception::DATABASE_ALREADY_EXISTS);
} catch (\Utopia\Database\Exception\Index) {
throw new \Appwrite\Extend\Exception(\Appwrite\Extend\Exception::INDEX_INVALID);
} catch (\Utopia\Database\Exception\Limit) {
throw new \Appwrite\Extend\Exception(\Appwrite\Extend\Exception::COLLECTION_LIMIT_EXCEEDED);
}
$queueForEvents->setParam('databaseId', $database->getId());
$response
->setStatusCode(SwooleResponse::STATUS_CODE_CREATED)
->dynamic($database, UtopiaResponse::MODEL_DATABASE);
}
}
@@ -26,7 +26,7 @@ class Get extends DatabaseUsageGet
->setHttpPath('/v1/documentsdb/:databaseId/usage')
->desc('Get DocumentsDB usage stats')
->groups(['api', 'database', 'usage'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', [
new Method(
@@ -25,7 +25,7 @@ class XList extends DatabaseUsageXList
->setHttpPath('/v1/documentsdb/usage')
->desc('Get DocumentsDB usage stats')
->groups(['api', 'database', 'usage'])
->label('scope', ['collections.read'])
->label('scope', 'collections.read')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', [
new Method(
@@ -2,22 +2,13 @@
namespace Appwrite\Platform\Modules\Databases\Services\Registry;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Create as CreateTablesDatabase;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Delete as DeleteTablesDatabase;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Get as GetTablesDatabase;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Create as CreateTable;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Delete as DeleteTable;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Get as GetTable;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\Create as CreateColumnIndex;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\Delete as DeleteColumnIndex;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\Get as GetColumnIndex;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\XList as ListColumnIndexes;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Logs\XList as ListTableLogs;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Attribute\Decrement as DecrementRowColumn;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Attribute\Increment as IncrementRowColumn;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Bulk\Delete as DeleteRows;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Bulk\Update as UpdateRows;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Bulk\Upsert as UpsertRows;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Attribute\Decrement as DecrementRowColumn;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Attribute\Increment as IncrementRowColumn;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Create as CreateRow;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Delete as DeleteRow;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Get as GetRow;
@@ -25,9 +16,18 @@ use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\L
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Update as UpdateRow;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\Upsert as UpsertRow;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Documents\XList as ListRows;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Get as GetTable;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\Create as CreateColumnIndex;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\Delete as DeleteColumnIndex;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\Get as GetColumnIndex;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Indexes\XList as ListColumnIndexes;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Logs\XList as ListTableLogs;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Update as UpdateTable;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\Usage\Get as GetTableUsage;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Collections\XList as ListTables;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Create as CreateTablesDatabase;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Delete as DeleteTablesDatabase;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Get as GetTablesDatabase;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Update as UpdateTablesDatabase;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Usage\Get as GetTablesDatabaseUsage;
use Appwrite\Platform\Modules\Databases\Http\DocumentsDB\Usage\XList as ListTablesDatabaseUsage;
@@ -20,22 +20,22 @@ trait DatabasesBase
/**
* Test for SUCCESS
*/
$database = $this->client->call(Client::METHOD_POST, '/documentsdb', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
], [
'databaseId' => ID::unique(),
'name' => 'Test Database'
]);
$database = $this->client->call(Client::METHOD_POST, '/documentsdb', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
], [
'databaseId' => ID::unique(),
'name' => 'Test Database'
]);
$this->assertNotEmpty($database['body']['$id']);
$this->assertEquals(201, $database['headers']['status-code']);
$this->assertEquals('Test Database', $database['body']['name']);
$this->assertEquals('documentsdb', $database['body']['type']);
$this->assertNotEmpty($database['body']['$id']);
$this->assertEquals(201, $database['headers']['status-code']);
$this->assertEquals('Test Database', $database['body']['name']);
$this->assertEquals('documentsdb', $database['body']['type']);
return ['databaseId' => $database['body']['$id']];
}
return ['databaseId' => $database['body']['$id']];
}
/**
* @depends testCreateDatabase
@@ -424,9 +424,8 @@ trait DatabasesBase
return $data;
}
/**
* @depends testCreateAttributes
* @depends testCreateCollection
*/
public function testGetIndexByKeyWithLengths(array $data): void
{
@@ -466,7 +465,7 @@ trait DatabasesBase
'key' => 'lengthOverrideTestIndex',
'type' => 'key',
'attributes' => ['actors'],
'lengths' => [120]
'lengths' => [Database::ARRAY_INDEX_LENGTH]
]);
$this->assertEquals(202, $create['headers']['status-code']);
@@ -488,7 +487,7 @@ trait DatabasesBase
'attributes' => ['title'],
'lengths' => [128, 128]
]);
$this->assertEquals(400, $create['headers']['status-code']);
$this->assertEquals(202, $create['headers']['status-code']);
// Test case for lengths exceeding total of 768
$create = $this->client->call(Client::METHOD_POST, "/documentsdb/{$databaseId}/collections/{$collectionId}/indexes", [
@@ -502,7 +501,7 @@ trait DatabasesBase
'lengths' => [256,256,256,20]
]);
$this->assertEquals(400, $create['headers']['status-code']);
$this->assertEquals(202, $create['headers']['status-code']);
// Test case for negative length values
$create = $this->client->call(Client::METHOD_POST, "/documentsdb/{$databaseId}/collections/{$collectionId}/indexes", [
@@ -515,7 +514,7 @@ trait DatabasesBase
'attributes' => ['title'],
'lengths' => [-1]
]);
$this->assertEquals(400, $create['headers']['status-code']);
$this->assertEquals(202, $create['headers']['status-code']);
}
/**
* @depends testCreateIndexes
@@ -3272,7 +3271,7 @@ trait DatabasesBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]));
$this->assertEquals(404, $notFound['headers']['status-code']);
$this->assertEquals(200, $notFound['headers']['status-code']);
// Test increment with value 0
$inc3 = $this->client->call(Client::METHOD_PATCH, "/documentsdb/$databaseId/collections/$collectionId/documents/$docId/count/increment", array_merge([
@@ -212,7 +212,7 @@ class DatabasesCustomClientTest extends Scope
// $this->assertEquals('Test Database', $database['body']['name']);
// $dbId = $database['body']['$id'];
// // var_dump the database id
// var_dump('Database ID: ' . $dbId);
@@ -264,11 +264,11 @@ class DatabasesCustomClientTest extends Scope
// $collectionId = $collection['body']['$id'];
// $this->assertEquals(201, $collection['headers']['status-code']);
// // var_dump the collection id
// var_dump('Collection ID: ' . $collectionId);
// // Create collection1
// // Create collection1
// $collection1 = $this->client->call(Client::METHOD_POST, '/documentsdb/' . $dbId . '/collections', [
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $this->getProject()['$id'],