mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
address comments.
This commit is contained in:
@@ -69,9 +69,14 @@ return [
|
||||
'description' => 'The request contains one or more invalid arguments. Please refer to the endpoint documentation.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::GENERAL_QUERY_LIMIT_EXCEEDED => [
|
||||
'name' => Exception::GENERAL_QUERY_LIMIT_EXCEEDED,
|
||||
'description' => 'Query limit exceeded for the current attribute/column. Usage of more than 100 query values on a single attribute/column is prohibited.',
|
||||
Exception::GENERAL_ATTRIBUTE_QUERY_LIMIT_EXCEEDED => [
|
||||
'name' => Exception::GENERAL_ATTRIBUTE_QUERY_LIMIT_EXCEEDED,
|
||||
'description' => 'Query limit exceeded for the current attribute.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::GENERAL_COLUMN_QUERY_LIMIT_EXCEEDED => [
|
||||
'name' => Exception::GENERAL_COLUMN_QUERY_LIMIT_EXCEEDED,
|
||||
'description' => 'Query limit exceeded for the current column.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::GENERAL_QUERY_INVALID => [
|
||||
@@ -813,7 +818,7 @@ return [
|
||||
],
|
||||
Exception::ATTRIBUTE_INVALID_RESIZE => [
|
||||
'name' => Exception::ATTRIBUTE_INVALID_RESIZE,
|
||||
'description' => "Existing data is too large for new size, truncate your existing data then try again.",
|
||||
'description' => 'Existing data is too large for new size, truncate your existing data then try again.',
|
||||
'code' => 400,
|
||||
],
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ return [
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any columns event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when an column is created.',
|
||||
'$description' => 'This event triggers when a column is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an column is deleted.'
|
||||
|
||||
@@ -265,15 +265,3 @@ const TOKENS_RESOURCE_TYPE_FILES = 'files';
|
||||
const TOKENS_RESOURCE_TYPE_SITES = 'sites';
|
||||
const TOKENS_RESOURCE_TYPE_FUNCTIONS = 'functions';
|
||||
const TOKENS_RESOURCE_TYPE_DATABASES = 'databases';
|
||||
|
||||
// Context constants for database
|
||||
|
||||
const DATABASE_ROWS_CONTEXT = 'row';
|
||||
const DATABASE_TABLES_CONTEXT = 'table';
|
||||
const DATABASE_COLUMNS_CONTEXT = 'column';
|
||||
const DATABASE_INDEX_CONTEXT = 'index';
|
||||
|
||||
const DATABASE_DOCUMENTS_CONTEXT = 'document';
|
||||
const DATABASE_ATTRIBUTES_CONTEXT = 'attribute';
|
||||
const DATABASE_COLLECTIONS_CONTEXT = 'collection';
|
||||
const DATABASE_COLUMN_INDEX_CONTEXT = 'columnIndex';
|
||||
|
||||
@@ -576,7 +576,12 @@ class Event
|
||||
/**
|
||||
* Force a non-assoc array.
|
||||
*/
|
||||
return \array_values($events);
|
||||
$eventValues = \array_values($events);
|
||||
|
||||
/**
|
||||
* Return a combined list of table, collection events.
|
||||
*/
|
||||
return Event::mirrorCollectionEvents($pattern, $eventValues[0], $eventValues);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -597,4 +602,45 @@ class Event
|
||||
$this->context = $event->context;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds `table` events for `collection` events.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* `databases.*.collections.*.documents.*.update` →\
|
||||
* `[databases.*.collections.*.documents.*.update, databases.*.tables.*.rows.*.update]`
|
||||
*/
|
||||
private static function mirrorCollectionEvents(string $pattern, string $firstEvent, array $events): array
|
||||
{
|
||||
$tableEventMap = [
|
||||
'documents' => 'rows',
|
||||
'collections' => 'tables',
|
||||
'attributes' => 'columns',
|
||||
];
|
||||
|
||||
if (
|
||||
str_contains($pattern, 'databases.') &&
|
||||
str_contains($firstEvent, 'collections')
|
||||
) {
|
||||
$pairedEvents = [];
|
||||
|
||||
foreach ($events as $event) {
|
||||
$pairedEvents[] = $event;
|
||||
|
||||
if (str_contains($event, 'collections')) {
|
||||
$tableSideEvent = str_replace(
|
||||
array_keys($tableEventMap),
|
||||
array_values($tableEventMap),
|
||||
$event
|
||||
);
|
||||
$pairedEvents[] = $tableSideEvent;
|
||||
}
|
||||
}
|
||||
|
||||
$events = $pairedEvents;
|
||||
}
|
||||
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,11 +72,7 @@ class Realtime extends Event
|
||||
return false;
|
||||
}
|
||||
|
||||
$events = Event::generateEvents($this->getEvent(), $this->getParams());
|
||||
$firstEvent = $events[0]; // most verbose event pattern
|
||||
|
||||
// generate and merge all collection and tables api events.
|
||||
$events = $this->mirrorCollectionEvents($firstEvent, $events);
|
||||
$allEvents = Event::generateEvents($this->getEvent(), $this->getParams());
|
||||
|
||||
$payload = new Document($this->getPayload());
|
||||
|
||||
@@ -87,7 +83,7 @@ class Realtime extends Event
|
||||
$tableOrCollection = $this->getContext('table') ?? $this->getContext('collection');
|
||||
|
||||
$target = RealtimeAdapter::fromPayload(
|
||||
event: $firstEvent,
|
||||
event: $allEvents[0],
|
||||
payload: $payload,
|
||||
project: $this->getProject(),
|
||||
database: $db,
|
||||
@@ -103,7 +99,7 @@ class Realtime extends Event
|
||||
$this->realtime->send(
|
||||
projectId: $projectId,
|
||||
payload: $this->getRealtimePayload(),
|
||||
events: $events,
|
||||
events: $allEvents,
|
||||
channels: $target['channels'],
|
||||
roles: $target['roles'],
|
||||
options: [
|
||||
@@ -115,45 +111,4 @@ class Realtime extends Event
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds `table` events for `collection` events.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* `databases.*.collections.*.documents.*.update` →\
|
||||
* `[databases.*.collections.*.documents.*.update, databases.*.tables.*.rows.*.update]`
|
||||
*/
|
||||
private function mirrorCollectionEvents(string $firstEvent, array $events): array
|
||||
{
|
||||
$tableEventMap = [
|
||||
'documents' => 'rows',
|
||||
'collections' => 'tables',
|
||||
'attributes' => 'columns',
|
||||
];
|
||||
|
||||
if (
|
||||
str_contains($this->getEvent(), 'databases.') &&
|
||||
str_contains($firstEvent, 'collections')
|
||||
) {
|
||||
$pairedEvents = [];
|
||||
|
||||
foreach ($events as $event) {
|
||||
$pairedEvents[] = $event;
|
||||
|
||||
if (str_contains($event, 'collections')) {
|
||||
$tableSideEvent = str_replace(
|
||||
array_keys($tableEventMap),
|
||||
array_values($tableEventMap),
|
||||
$event
|
||||
);
|
||||
$pairedEvents[] = $tableSideEvent;
|
||||
}
|
||||
}
|
||||
|
||||
$events = $pairedEvents;
|
||||
}
|
||||
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ class Exception extends \Exception
|
||||
public const GENERAL_SMTP_DISABLED = 'general_smtp_disabled';
|
||||
public const GENERAL_PHONE_DISABLED = 'general_phone_disabled';
|
||||
public const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid';
|
||||
public const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded';
|
||||
public const GENERAL_COLUMN_QUERY_LIMIT_EXCEEDED = 'general_column_query_limit_exceeded';
|
||||
public const GENERAL_ATTRIBUTE_QUERY_LIMIT_EXCEEDED = 'general_attribute_query_limit_exceeded';
|
||||
public const GENERAL_QUERY_INVALID = 'general_query_invalid';
|
||||
public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found';
|
||||
public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found';
|
||||
@@ -197,9 +198,9 @@ class Exception extends \Exception
|
||||
public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded';
|
||||
|
||||
/** Tables */
|
||||
public const TABLE_NOT_FOUND = 'table_not_found';
|
||||
public const TABLE_ALREADY_EXISTS = 'table_already_exists';
|
||||
public const TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded';
|
||||
public const TABLE_NOT_FOUND = 'table_not_found';
|
||||
public const TABLE_ALREADY_EXISTS = 'table_already_exists';
|
||||
public const TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded';
|
||||
|
||||
/** Documents */
|
||||
public const DOCUMENT_NOT_FOUND = 'document_not_found';
|
||||
@@ -211,13 +212,13 @@ class Exception extends \Exception
|
||||
public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted';
|
||||
|
||||
/** Rows */
|
||||
public const ROW_NOT_FOUND = 'row_not_found';
|
||||
public const ROW_INVALID_STRUCTURE = 'row_invalid_structure';
|
||||
public const ROW_MISSING_DATA = 'row_missing_data';
|
||||
public const ROW_MISSING_PAYLOAD = 'row_missing_payload';
|
||||
public const ROW_ALREADY_EXISTS = 'row_already_exists';
|
||||
public const ROW_UPDATE_CONFLICT = 'row_update_conflict';
|
||||
public const ROW_DELETE_RESTRICTED = 'row_delete_restricted';
|
||||
public const ROW_NOT_FOUND = 'row_not_found';
|
||||
public const ROW_INVALID_STRUCTURE = 'row_invalid_structure';
|
||||
public const ROW_MISSING_DATA = 'row_missing_data';
|
||||
public const ROW_MISSING_PAYLOAD = 'row_missing_payload';
|
||||
public const ROW_ALREADY_EXISTS = 'row_already_exists';
|
||||
public const ROW_UPDATE_CONFLICT = 'row_update_conflict';
|
||||
public const ROW_DELETE_RESTRICTED = 'row_delete_restricted';
|
||||
|
||||
/** Attributes */
|
||||
public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found';
|
||||
@@ -232,16 +233,16 @@ class Exception extends \Exception
|
||||
public const ATTRIBUTE_INVALID_RESIZE = 'attribute_invalid_resize';
|
||||
|
||||
/** Columns */
|
||||
public const COLUMN_NOT_FOUND = 'column_not_found';
|
||||
public const COLUMN_UNKNOWN = 'column_unknown';
|
||||
public const COLUMN_NOT_AVAILABLE = 'column_not_available';
|
||||
public const COLUMN_FORMAT_UNSUPPORTED = 'column_format_unsupported';
|
||||
public const COLUMN_DEFAULT_UNSUPPORTED = 'column_default_unsupported';
|
||||
public const COLUMN_ALREADY_EXISTS = 'column_already_exists';
|
||||
public const COLUMN_LIMIT_EXCEEDED = 'column_limit_exceeded';
|
||||
public const COLUMN_VALUE_INVALID = 'column_value_invalid';
|
||||
public const COLUMN_TYPE_INVALID = 'column_type_invalid';
|
||||
public const COLUMN_INVALID_RESIZE = 'column_invalid_resize';
|
||||
public const COLUMN_NOT_FOUND = 'column_not_found';
|
||||
public const COLUMN_UNKNOWN = 'column_unknown';
|
||||
public const COLUMN_NOT_AVAILABLE = 'column_not_available';
|
||||
public const COLUMN_FORMAT_UNSUPPORTED = 'column_format_unsupported';
|
||||
public const COLUMN_DEFAULT_UNSUPPORTED = 'column_default_unsupported';
|
||||
public const COLUMN_ALREADY_EXISTS = 'column_already_exists';
|
||||
public const COLUMN_LIMIT_EXCEEDED = 'column_limit_exceeded';
|
||||
public const COLUMN_VALUE_INVALID = 'column_value_invalid';
|
||||
public const COLUMN_TYPE_INVALID = 'column_type_invalid';
|
||||
public const COLUMN_INVALID_RESIZE = 'column_invalid_resize';
|
||||
|
||||
/** Relationship */
|
||||
public const RELATIONSHIP_VALUE_INVALID = 'relationship_value_invalid';
|
||||
@@ -347,7 +348,7 @@ class Exception extends \Exception
|
||||
public const MESSAGE_MISSING_SCHEDULE = 'message_missing_schedule';
|
||||
|
||||
/** Targets */
|
||||
public const TARGET_PROVIDER_INVALID_TYPE = 'target_provider_invalid_type';
|
||||
public const TARGET_PROVIDER_INVALID_TYPE = 'target_provider_invalid_type';
|
||||
|
||||
/** Schedules */
|
||||
public const SCHEDULE_NOT_FOUND = 'schedule_not_found';
|
||||
|
||||
@@ -312,12 +312,10 @@ class Realtime extends Adapter
|
||||
throw new \Exception('Collection or the Table needs to be passed to Realtime for Document/Row events in the Database.');
|
||||
}
|
||||
|
||||
// 1.7.x - Tables API
|
||||
$channels[] = 'rows';
|
||||
$channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows';
|
||||
$channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows.' . $payload->getId();
|
||||
|
||||
// 1.6.x - Collections API
|
||||
$channels[] = 'documents';
|
||||
$channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents';
|
||||
$channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents.' . $payload->getId();
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Context constants for identifying database resource types.
|
||||
*
|
||||
* Tables vs. Collections, Rows vs. Documents, and Columns vs. Attributes
|
||||
* are functionally equivalent and share the same underlying API structure.
|
||||
*
|
||||
* These constants help distinguish the context of an action,
|
||||
* enabling accurate error messages, realtime event triggers, and other context-aware behaviors.
|
||||
*/
|
||||
|
||||
// Context constants for database
|
||||
|
||||
const DATABASE_ROWS_CONTEXT = 'row';
|
||||
const DATABASE_TABLES_CONTEXT = 'table';
|
||||
const DATABASE_COLUMNS_CONTEXT = 'column';
|
||||
const DATABASE_INDEX_CONTEXT = 'index';
|
||||
|
||||
const DATABASE_DOCUMENTS_CONTEXT = 'document';
|
||||
const DATABASE_ATTRIBUTES_CONTEXT = 'attribute';
|
||||
const DATABASE_COLLECTIONS_CONTEXT = 'collection';
|
||||
const DATABASE_COLUMN_INDEX_CONTEXT = 'columnIndex';
|
||||
Reference in New Issue
Block a user